gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

path.go (2928B)


      1 // Copyright ©2015 The Go Authors
      2 // Copyright ©2015 Steve Francia <spf@spf13.com>
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //     http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 
     16 package afero
     17 
     18 import (
     19 	"os"
     20 	"path/filepath"
     21 	"sort"
     22 )
     23 
     24 // readDirNames reads the directory named by dirname and returns
     25 // a sorted list of directory entries.
     26 // adapted from https://golang.org/src/path/filepath/path.go
     27 func readDirNames(fs Fs, dirname string) ([]string, error) {
     28 	f, err := fs.Open(dirname)
     29 	if err != nil {
     30 		return nil, err
     31 	}
     32 	names, err := f.Readdirnames(-1)
     33 	f.Close()
     34 	if err != nil {
     35 		return nil, err
     36 	}
     37 	sort.Strings(names)
     38 	return names, nil
     39 }
     40 
     41 // walk recursively descends path, calling walkFn
     42 // adapted from https://golang.org/src/path/filepath/path.go
     43 func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
     44 	err := walkFn(path, info, nil)
     45 	if err != nil {
     46 		if info.IsDir() && err == filepath.SkipDir {
     47 			return nil
     48 		}
     49 		return err
     50 	}
     51 
     52 	if !info.IsDir() {
     53 		return nil
     54 	}
     55 
     56 	names, err := readDirNames(fs, path)
     57 	if err != nil {
     58 		return walkFn(path, info, err)
     59 	}
     60 
     61 	for _, name := range names {
     62 		filename := filepath.Join(path, name)
     63 		fileInfo, err := lstatIfPossible(fs, filename)
     64 		if err != nil {
     65 			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
     66 				return err
     67 			}
     68 		} else {
     69 			err = walk(fs, filename, fileInfo, walkFn)
     70 			if err != nil {
     71 				if !fileInfo.IsDir() || err != filepath.SkipDir {
     72 					return err
     73 				}
     74 			}
     75 		}
     76 	}
     77 	return nil
     78 }
     79 
     80 // if the filesystem supports it, use Lstat, else use fs.Stat
     81 func lstatIfPossible(fs Fs, path string) (os.FileInfo, error) {
     82 	if lfs, ok := fs.(Lstater); ok {
     83 		fi, _, err := lfs.LstatIfPossible(path)
     84 		return fi, err
     85 	}
     86 	return fs.Stat(path)
     87 }
     88 
     89 // Walk walks the file tree rooted at root, calling walkFn for each file or
     90 // directory in the tree, including root. All errors that arise visiting files
     91 // and directories are filtered by walkFn. The files are walked in lexical
     92 // order, which makes the output deterministic but means that for very
     93 // large directories Walk can be inefficient.
     94 // Walk does not follow symbolic links.
     95 
     96 func (a Afero) Walk(root string, walkFn filepath.WalkFunc) error {
     97 	return Walk(a.Fs, root, walkFn)
     98 }
     99 
    100 func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error {
    101 	info, err := lstatIfPossible(fs, root)
    102 	if err != nil {
    103 		return walkFn(root, nil, err)
    104 	}
    105 	return walk(fs, root, info, walkFn)
    106 }