"strings"
)
-func targetsWalker(root string) ([]string, error) {
+func targetsCollect(root string, tgts map[string]struct{}) error {
root, err := filepath.Abs(root)
if err != nil {
panic(err)
}
dir, err := os.Open(root)
if err != nil {
- return nil, err
+ return err
}
defer dir.Close()
- tgts := make([]string, 0, 1<<10)
for {
fis, err := dir.Readdir(1 << 10)
if err != nil {
if err == io.EOF {
break
}
- return tgts, err
+ return err
}
for _, fi := range fis {
if !fi.IsDir() {
if fi.Name() == RedoDir {
redoDir, err := os.Open(pth)
if err != nil {
- return tgts, err
+ return err
}
redoFis, err := redoDir.Readdir(0)
if err != nil {
- return tgts, err
+ return err
}
for _, redoFi := range redoFis {
name := redoFi.Name()
if strings.HasSuffix(name, DepSuffix) {
name = cwdMustRel(root, name)
- tgts = append(tgts, name[:len(name)-len(DepSuffix)])
+ tgts[name[:len(name)-len(DepSuffix)]] = struct{}{}
}
}
redoDir.Close()
} else {
- subTgts, err := targetsWalker(pth)
- tgts = append(tgts, subTgts...)
- if err != nil {
- return tgts, err
+ if err = targetsCollect(pth, tgts); err != nil {
+ return err
}
}
}
}
- return tgts, dir.Close()
+ return dir.Close()
+}
+
+func targetsWalker(tgts []string) ([]string, error) {
+ tgtsMap := map[string]struct{}{}
+ for _, tgt := range tgts {
+ if err := targetsCollect(tgt, tgtsMap); err != nil {
+ return nil, err
+ }
+ }
+ tgts = make([]string, 0, len(tgtsMap))
+ for tgt := range tgtsMap {
+ tgts = append(tgts, tgt)
+ }
+ return tgts, nil
+}
+
+func collectWholeDeps(
+ tgts map[string]struct{},
+ deps map[string]map[string]struct{},
+ seen map[string]struct{},
+) {
+ for tgt := range tgts {
+ seen[tgt] = struct{}{}
+ collectWholeDeps(deps[tgt], deps, seen)
+ }
}