forked from twpayne/go-vfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
walk.go
55 lines (49 loc) · 1.36 KB
/
walk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package vfs
import (
"os"
"path/filepath"
"sort"
)
// A LstatReadDirer implements all the functionality needed by Walk.
type LstatReadDirer interface {
Lstat(name string) (os.FileInfo, error)
ReadDir(dirname string) ([]os.FileInfo, error)
}
type infosByName []os.FileInfo
func (is infosByName) Len() int { return len(is) }
func (is infosByName) Less(i, j int) bool { return is[i].Name() < is[j].Name() }
func (is infosByName) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
// walk recursively walks fs from path.
func walk(fs LstatReadDirer, path string, walkFn filepath.WalkFunc, info os.FileInfo, err error) error {
if err != nil {
return walkFn(path, info, err)
}
err = walkFn(path, info, nil)
if !info.IsDir() {
return err
}
if err == filepath.SkipDir {
return nil
}
infos, err := fs.ReadDir(path)
if err != nil {
return err
}
sort.Sort(infosByName(infos))
for _, info := range infos {
name := info.Name()
if name == "." || name == ".." {
continue
}
if err := walk(fs, filepath.Join(path, info.Name()), walkFn, info, nil); err != nil {
return err
}
}
return nil
}
// Walk is the equivalent of filepath.Walk but operates on fs. Entries are
// returned in lexicographical order.
func Walk(fs LstatReadDirer, path string, walkFn filepath.WalkFunc) error {
info, err := fs.Lstat(path)
return walk(fs, path, walkFn, info, err)
}