Path: blob/main/vendor/github.com/spf13/afero/path.go
2875 views
// Copyright ©2015 The Go Authors1// Copyright ©2015 Steve Francia <[email protected]>2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7// http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.1415package afero1617import (18"os"19"path/filepath"20"sort"21)2223// readDirNames reads the directory named by dirname and returns24// a sorted list of directory entries.25// adapted from https://golang.org/src/path/filepath/path.go26func readDirNames(fs Fs, dirname string) ([]string, error) {27f, err := fs.Open(dirname)28if err != nil {29return nil, err30}31names, err := f.Readdirnames(-1)32f.Close()33if err != nil {34return nil, err35}36sort.Strings(names)37return names, nil38}3940// walk recursively descends path, calling walkFn41// adapted from https://golang.org/src/path/filepath/path.go42func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {43err := walkFn(path, info, nil)44if err != nil {45if info.IsDir() && err == filepath.SkipDir {46return nil47}48return err49}5051if !info.IsDir() {52return nil53}5455names, err := readDirNames(fs, path)56if err != nil {57return walkFn(path, info, err)58}5960for _, name := range names {61filename := filepath.Join(path, name)62fileInfo, err := lstatIfPossible(fs, filename)63if err != nil {64if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {65return err66}67} else {68err = walk(fs, filename, fileInfo, walkFn)69if err != nil {70if !fileInfo.IsDir() || err != filepath.SkipDir {71return err72}73}74}75}76return nil77}7879// if the filesystem supports it, use Lstat, else use fs.Stat80func lstatIfPossible(fs Fs, path string) (os.FileInfo, error) {81if lfs, ok := fs.(Lstater); ok {82fi, _, err := lfs.LstatIfPossible(path)83return fi, err84}85return fs.Stat(path)86}8788// Walk walks the file tree rooted at root, calling walkFn for each file or89// directory in the tree, including root. All errors that arise visiting files90// and directories are filtered by walkFn. The files are walked in lexical91// order, which makes the output deterministic but means that for very92// large directories Walk can be inefficient.93// Walk does not follow symbolic links.9495func (a Afero) Walk(root string, walkFn filepath.WalkFunc) error {96return Walk(a.Fs, root, walkFn)97}9899func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error {100info, err := lstatIfPossible(fs, root)101if err != nil {102return walkFn(root, nil, err)103}104return walk(fs, root, info, walkFn)105}106107108