main
Raw Download raw file
 1package util
 2
 3import (
 4	"os"
 5	"path/filepath"
 6
 7	"github.com/go-git/go-billy/v5"
 8)
 9
10// walk recursively descends path, calling walkFn
11// adapted from https://golang.org/src/path/filepath/path.go
12func walk(fs billy.Filesystem, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
13	if !info.IsDir() {
14		return walkFn(path, info, nil)
15	}
16
17	names, err := readdirnames(fs, path)
18	err1 := walkFn(path, info, err)
19	// If err != nil, walk can't walk into this directory.
20	// err1 != nil means walkFn want walk to skip this directory or stop walking.
21	// Therefore, if one of err and err1 isn't nil, walk will return.
22	if err != nil || err1 != nil {
23		// The caller's behavior is controlled by the return value, which is decided
24		// by walkFn. walkFn may ignore err and return nil.
25		// If walkFn returns SkipDir, it will be handled by the caller.
26		// So walk should return whatever walkFn returns.
27		return err1
28	}
29
30	for _, name := range names {
31		filename := filepath.Join(path, name)
32		fileInfo, err := fs.Lstat(filename)
33		if err != nil {
34			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
35				return err
36			}
37		} else {
38			err = walk(fs, filename, fileInfo, walkFn)
39			if err != nil {
40				if !fileInfo.IsDir() || err != filepath.SkipDir {
41					return err
42				}
43			}
44		}
45	}
46	return nil
47}
48
49// Walk walks the file tree rooted at root, calling fn for each file or 
50// directory in the tree, including root. All errors that arise visiting files
51// and directories are filtered by fn: see the WalkFunc documentation for
52// details.
53//
54// The files are walked in lexical order, which makes the output deterministic
55// but requires Walk to read an entire directory into memory before proceeding
56// to walk that directory. Walk does not follow symbolic links.
57// 
58// Function adapted from https://github.com/golang/go/blob/3b770f2ccb1fa6fecc22ea822a19447b10b70c5c/src/path/filepath/path.go#L500
59func Walk(fs billy.Filesystem, root string, walkFn filepath.WalkFunc) error {
60	info, err := fs.Lstat(root)
61	if err != nil {
62		err = walkFn(root, nil, err)
63	} else {
64		err = walk(fs, root, info, walkFn)
65	}
66	
67	if err == filepath.SkipDir {
68		return nil
69	}
70	
71	return err
72}