X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=targets.go;h=bd1fac3d383cefc1c412e19c2efd5d17b575e1da;hb=HEAD;hp=602fd942abbf16b1741df0c946167f06aa703877;hpb=609842c96d2bb25c509f3d2949fe26f60ec03a5f;p=goredo.git diff --git a/targets.go b/targets.go index 602fd94..bd1fac3 100644 --- a/targets.go +++ b/targets.go @@ -1,19 +1,17 @@ -/* -goredo -- djb's redo implementation on pure Go -Copyright (C) 2020-2021 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 -the Free Software Foundation, version 3 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ +// goredo -- djb's redo implementation on pure Go +// Copyright (C) 2020-2024 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 +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . package main @@ -21,59 +19,79 @@ import ( "io" "os" "path" - "path/filepath" "strings" ) -func targetsWalker(root string) ([]string, error) { - root, err := filepath.Abs(root) - if err != nil { - panic(err) - } +func targetsCollect(root string, tgts map[string]struct{}) error { dir, err := os.Open(root) if err != nil { - return nil, err + return ErrLine(err) } defer dir.Close() - tgts := make([]string, 0, 1<<10) for { - fis, err := dir.Readdir(1 << 10) + entries, err := dir.ReadDir(1 << 10) if err != nil { if err == io.EOF { break } - return tgts, err + return ErrLine(err) } - for _, fi := range fis { - if !fi.IsDir() { + for _, entry := range entries { + if !entry.IsDir() { continue } - pth := path.Join(root, fi.Name()) - if fi.Name() == RedoDir { + pth := path.Join(root, entry.Name()) + if entry.Name() == RedoDir { redoDir, err := os.Open(pth) if err != nil { - return tgts, err + return ErrLine(err) } - redoFis, err := redoDir.Readdir(0) + redoEntries, err := redoDir.ReadDir(0) + redoDir.Close() if err != nil { - return tgts, err + return ErrLine(err) } - for _, redoFi := range redoFis { - name := redoFi.Name() + for _, redoEntry := range redoEntries { + name := redoEntry.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 := make(map[string]struct{}) + for _, tgt := range tgts { + if err := targetsCollect(mustAbs(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]*Tgt, + deps map[string]map[string]*Tgt, + seen map[string]*Tgt, +) { + for _, tgt := range tgts { + if _, exists := seen[tgt.rel]; exists { + continue + } + seen[tgt.rel] = tgt + collectWholeDeps(deps[tgt.rel], deps, seen) + } }