X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=targets.go;h=334de9c847ee9520df24c93fb02bdf91dbcc44e2;hb=19b13ea1334d377dd9c6a36ea70c9141b8fd447d;hp=602fd942abbf16b1741df0c946167f06aa703877;hpb=609842c96d2bb25c509f3d2949fe26f60ec03a5f;p=goredo.git diff --git a/targets.go b/targets.go index 602fd94..334de9c 100644 --- a/targets.go +++ b/targets.go @@ -1,6 +1,6 @@ /* goredo -- djb's redo implementation on pure Go -Copyright (C) 2020-2021 Sergey Matveev +Copyright (C) 2020-2022 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,24 +25,23 @@ import ( "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() { @@ -52,28 +51,51 @@ func targetsWalker(root string) ([]string, error) { if fi.Name() == RedoDir { redoDir, err := os.Open(pth) if err != nil { - return tgts, err + return err } redoFis, err := redoDir.Readdir(0) + redoDir.Close() 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 nil +} + +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) + } }