summaryrefslogtreecommitdiff
path: root/src/pkg/path/filepath/path.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/path/filepath/path.go')
-rw-r--r--src/pkg/path/filepath/path.go467
1 files changed, 0 insertions, 467 deletions
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
deleted file mode 100644
index 71603cc59..000000000
--- a/src/pkg/path/filepath/path.go
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package filepath implements utility routines for manipulating filename paths
-// in a way compatible with the target operating system-defined file paths.
-package filepath
-
-import (
- "errors"
- "os"
- "sort"
- "strings"
-)
-
-// A lazybuf is a lazily constructed path buffer.
-// It supports append, reading previously appended bytes,
-// and retrieving the final string. It does not allocate a buffer
-// to hold the output until that output diverges from s.
-type lazybuf struct {
- path string
- buf []byte
- w int
- volAndPath string
- volLen int
-}
-
-func (b *lazybuf) index(i int) byte {
- if b.buf != nil {
- return b.buf[i]
- }
- return b.path[i]
-}
-
-func (b *lazybuf) append(c byte) {
- if b.buf == nil {
- if b.w < len(b.path) && b.path[b.w] == c {
- b.w++
- return
- }
- b.buf = make([]byte, len(b.path))
- copy(b.buf, b.path[:b.w])
- }
- b.buf[b.w] = c
- b.w++
-}
-
-func (b *lazybuf) string() string {
- if b.buf == nil {
- return b.volAndPath[:b.volLen+b.w]
- }
- return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
-}
-
-const (
- Separator = os.PathSeparator
- ListSeparator = os.PathListSeparator
-)
-
-// Clean returns the shortest path name equivalent to path
-// by purely lexical processing. It applies the following rules
-// iteratively until no further processing can be done:
-//
-// 1. Replace multiple Separator elements with a single one.
-// 2. Eliminate each . path name element (the current directory).
-// 3. Eliminate each inner .. path name element (the parent directory)
-// along with the non-.. element that precedes it.
-// 4. Eliminate .. elements that begin a rooted path:
-// that is, replace "/.." by "/" at the beginning of a path,
-// assuming Separator is '/'.
-//
-// The returned path ends in a slash only if it represents a root directory,
-// such as "/" on Unix or `C:\` on Windows.
-//
-// If the result of this process is an empty string, Clean
-// returns the string ".".
-//
-// See also Rob Pike, ``Lexical File Names in Plan 9 or
-// Getting Dot-Dot Right,''
-// http://plan9.bell-labs.com/sys/doc/lexnames.html
-func Clean(path string) string {
- originalPath := path
- volLen := volumeNameLen(path)
- path = path[volLen:]
- if path == "" {
- if volLen > 1 && originalPath[1] != ':' {
- // should be UNC
- return FromSlash(originalPath)
- }
- return originalPath + "."
- }
- rooted := os.IsPathSeparator(path[0])
-
- // Invariants:
- // reading from path; r is index of next byte to process.
- // writing to buf; w is index of next byte to write.
- // dotdot is index in buf where .. must stop, either because
- // it is the leading slash or it is a leading ../../.. prefix.
- n := len(path)
- out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
- r, dotdot := 0, 0
- if rooted {
- out.append(Separator)
- r, dotdot = 1, 1
- }
-
- for r < n {
- switch {
- case os.IsPathSeparator(path[r]):
- // empty path element
- r++
- case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
- // . element
- r++
- case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
- // .. element: remove to last separator
- r += 2
- switch {
- case out.w > dotdot:
- // can backtrack
- out.w--
- for out.w > dotdot && !os.IsPathSeparator(out.index(out.w)) {
- out.w--
- }
- case !rooted:
- // cannot backtrack, but not rooted, so append .. element.
- if out.w > 0 {
- out.append(Separator)
- }
- out.append('.')
- out.append('.')
- dotdot = out.w
- }
- default:
- // real path element.
- // add slash if needed
- if rooted && out.w != 1 || !rooted && out.w != 0 {
- out.append(Separator)
- }
- // copy element
- for ; r < n && !os.IsPathSeparator(path[r]); r++ {
- out.append(path[r])
- }
- }
- }
-
- // Turn empty string into "."
- if out.w == 0 {
- out.append('.')
- }
-
- return FromSlash(out.string())
-}
-
-// ToSlash returns the result of replacing each separator character
-// in path with a slash ('/') character. Multiple separators are
-// replaced by multiple slashes.
-func ToSlash(path string) string {
- if Separator == '/' {
- return path
- }
- return strings.Replace(path, string(Separator), "/", -1)
-}
-
-// FromSlash returns the result of replacing each slash ('/') character
-// in path with a separator character. Multiple slashes are replaced
-// by multiple separators.
-func FromSlash(path string) string {
- if Separator == '/' {
- return path
- }
- return strings.Replace(path, "/", string(Separator), -1)
-}
-
-// SplitList splits a list of paths joined by the OS-specific ListSeparator,
-// usually found in PATH or GOPATH environment variables.
-// Unlike strings.Split, SplitList returns an empty slice when passed an empty string.
-func SplitList(path string) []string {
- return splitList(path)
-}
-
-// Split splits path immediately following the final Separator,
-// separating it into a directory and file name component.
-// If there is no Separator in path, Split returns an empty dir
-// and file set to path.
-// The returned values have the property that path = dir+file.
-func Split(path string) (dir, file string) {
- vol := VolumeName(path)
- i := len(path) - 1
- for i >= len(vol) && !os.IsPathSeparator(path[i]) {
- i--
- }
- return path[:i+1], path[i+1:]
-}
-
-// Join joins any number of path elements into a single path, adding
-// a Separator if necessary. The result is Cleaned, in particular
-// all empty strings are ignored.
-func Join(elem ...string) string {
- for i, e := range elem {
- if e != "" {
- return Clean(strings.Join(elem[i:], string(Separator)))
- }
- }
- return ""
-}
-
-// Ext returns the file name extension used by path.
-// The extension is the suffix beginning at the final dot
-// in the final element of path; it is empty if there is
-// no dot.
-func Ext(path string) string {
- for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
- if path[i] == '.' {
- return path[i:]
- }
- }
- return ""
-}
-
-// EvalSymlinks returns the path name after the evaluation of any symbolic
-// links.
-// If path is relative the result will be relative to the current directory,
-// unless one of the components is an absolute symbolic link.
-func EvalSymlinks(path string) (string, error) {
- return evalSymlinks(path)
-}
-
-// Abs returns an absolute representation of path.
-// If the path is not absolute it will be joined with the current
-// working directory to turn it into an absolute path. The absolute
-// path name for a given file is not guaranteed to be unique.
-func Abs(path string) (string, error) {
- if IsAbs(path) {
- return Clean(path), nil
- }
- wd, err := os.Getwd()
- if err != nil {
- return "", err
- }
- return Join(wd, path), nil
-}
-
-// Rel returns a relative path that is lexically equivalent to targpath when
-// joined to basepath with an intervening separator. That is,
-// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself.
-// On success, the returned path will always be relative to basepath,
-// even if basepath and targpath share no elements.
-// An error is returned if targpath can't be made relative to basepath or if
-// knowing the current working directory would be necessary to compute it.
-func Rel(basepath, targpath string) (string, error) {
- baseVol := VolumeName(basepath)
- targVol := VolumeName(targpath)
- base := Clean(basepath)
- targ := Clean(targpath)
- if targ == base {
- return ".", nil
- }
- base = base[len(baseVol):]
- targ = targ[len(targVol):]
- if base == "." {
- base = ""
- }
- // Can't use IsAbs - `\a` and `a` are both relative in Windows.
- baseSlashed := len(base) > 0 && base[0] == Separator
- targSlashed := len(targ) > 0 && targ[0] == Separator
- if baseSlashed != targSlashed || baseVol != targVol {
- return "", errors.New("Rel: can't make " + targ + " relative to " + base)
- }
- // Position base[b0:bi] and targ[t0:ti] at the first differing elements.
- bl := len(base)
- tl := len(targ)
- var b0, bi, t0, ti int
- for {
- for bi < bl && base[bi] != Separator {
- bi++
- }
- for ti < tl && targ[ti] != Separator {
- ti++
- }
- if targ[t0:ti] != base[b0:bi] {
- break
- }
- if bi < bl {
- bi++
- }
- if ti < tl {
- ti++
- }
- b0 = bi
- t0 = ti
- }
- if base[b0:bi] == ".." {
- return "", errors.New("Rel: can't make " + targ + " relative to " + base)
- }
- if b0 != bl {
- // Base elements left. Must go up before going down.
- seps := strings.Count(base[b0:bl], string(Separator))
- size := 2 + seps*3
- if tl != t0 {
- size += 1 + tl - t0
- }
- buf := make([]byte, size)
- n := copy(buf, "..")
- for i := 0; i < seps; i++ {
- buf[n] = Separator
- copy(buf[n+1:], "..")
- n += 3
- }
- if t0 != tl {
- buf[n] = Separator
- copy(buf[n+1:], targ[t0:])
- }
- return string(buf), nil
- }
- return targ[t0:], nil
-}
-
-// SkipDir is used as a return value from WalkFuncs to indicate that
-// the directory named in the call is to be skipped. It is not returned
-// as an error by any function.
-var SkipDir = errors.New("skip this directory")
-
-// WalkFunc is the type of the function called for each file or directory
-// visited by Walk. The path argument contains the argument to Walk as a
-// prefix; that is, if Walk is called with "dir", which is a directory
-// containing the file "a", the walk function will be called with argument
-// "dir/a". The info argument is the os.FileInfo for the named path.
-//
-// If there was a problem walking to the file or directory named by path, the
-// incoming error will describe the problem and the function can decide how
-// to handle that error (and Walk will not descend into that directory). If
-// an error is returned, processing stops. The sole exception is that if path
-// is a directory and the function returns the special value SkipDir, the
-// contents of the directory are skipped and processing continues as usual on
-// the next file.
-type WalkFunc func(path string, info os.FileInfo, err error) error
-
-var lstat = os.Lstat // for testing
-
-// walk recursively descends path, calling w.
-func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
- err := walkFn(path, info, nil)
- if err != nil {
- if info.IsDir() && err == SkipDir {
- return nil
- }
- return err
- }
-
- if !info.IsDir() {
- return nil
- }
-
- names, err := readDirNames(path)
- if err != nil {
- return walkFn(path, info, err)
- }
-
- for _, name := range names {
- filename := Join(path, name)
- fileInfo, err := lstat(filename)
- if err != nil {
- if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir {
- return err
- }
- } else {
- err = walk(filename, fileInfo, walkFn)
- if err != nil {
- if !fileInfo.IsDir() || err != SkipDir {
- return err
- }
- }
- }
- }
- return nil
-}
-
-// Walk walks the file tree rooted at root, calling walkFn for each file or
-// directory in the tree, including root. All errors that arise visiting files
-// and directories are filtered by walkFn. The files are walked in lexical
-// order, which makes the output deterministic but means that for very
-// large directories Walk can be inefficient.
-// Walk does not follow symbolic links.
-func Walk(root string, walkFn WalkFunc) error {
- info, err := os.Lstat(root)
- if err != nil {
- return walkFn(root, nil, err)
- }
- return walk(root, info, walkFn)
-}
-
-// readDirNames reads the directory named by dirname and returns
-// a sorted list of directory entries.
-func readDirNames(dirname string) ([]string, error) {
- f, err := os.Open(dirname)
- if err != nil {
- return nil, err
- }
- names, err := f.Readdirnames(-1)
- f.Close()
- if err != nil {
- return nil, err
- }
- sort.Strings(names)
- return names, nil
-}
-
-// Base returns the last element of path.
-// Trailing path separators are removed before extracting the last element.
-// If the path is empty, Base returns ".".
-// If the path consists entirely of separators, Base returns a single separator.
-func Base(path string) string {
- if path == "" {
- return "."
- }
- // Strip trailing slashes.
- for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
- path = path[0 : len(path)-1]
- }
- // Throw away volume name
- path = path[len(VolumeName(path)):]
- // Find the last element
- i := len(path) - 1
- for i >= 0 && !os.IsPathSeparator(path[i]) {
- i--
- }
- if i >= 0 {
- path = path[i+1:]
- }
- // If empty now, it had only slashes.
- if path == "" {
- return string(Separator)
- }
- return path
-}
-
-// Dir returns all but the last element of path, typically the path's directory.
-// After dropping the final element, the path is Cleaned and trailing
-// slashes are removed.
-// If the path is empty, Dir returns ".".
-// If the path consists entirely of separators, Dir returns a single separator.
-// The returned path does not end in a separator unless it is the root directory.
-func Dir(path string) string {
- vol := VolumeName(path)
- i := len(path) - 1
- for i >= len(vol) && !os.IsPathSeparator(path[i]) {
- i--
- }
- dir := Clean(path[len(vol) : i+1])
- last := len(dir) - 1
- if last > 0 && os.IsPathSeparator(dir[last]) {
- dir = dir[:last]
- }
- if dir == "" {
- dir = "."
- }
- return vol + dir
-}
-
-// VolumeName returns leading volume name.
-// Given "C:\foo\bar" it returns "C:" under windows.
-// Given "\\host\share\foo" it returns "\\host\share".
-// On other platforms it returns "".
-func VolumeName(path string) (v string) {
- return path[:volumeNameLen(path)]
-}