forked from monochromegane/dragon-imports
/
walk.go
57 lines (49 loc) · 1 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
56
57
package dragon
import (
"io/ioutil"
"os"
"path/filepath"
"golang.org/x/sync/errgroup"
)
type walkFunc func(info fileInfo) error
func concurrentWalk(root string, walkFn walkFunc) error {
info, err := os.Lstat(root)
if err != nil {
return err
}
sem := make(chan struct{}, 16)
return walk(newFileInfo(root, info), walkFn, sem)
}
func walk(info fileInfo, walkFn walkFunc, sem chan struct{}) error {
walkError := walkFn(info)
if walkError != nil {
if info.IsDir() && walkError == filepath.SkipDir {
return nil
}
return walkError
}
if !info.IsDir() {
return nil
}
path := info.path
files, err := ioutil.ReadDir(path)
if err != nil {
return err
}
eg := &errgroup.Group{}
for _, file := range files {
f := newFileInfo(filepath.Join(path, file.Name()), file)
select {
case sem <- struct{}{}:
eg.Go(func() error {
defer func() { <-sem }()
return walk(f, walkFn, sem)
})
default:
if err := walk(f, walkFn, sem); err != nil {
return err
}
}
}
return eg.Wait()
}