]> Cypherpunks.ru repositories - goredo.git/blob - targets.go
isModified check must only look at ifchanges
[goredo.git] / targets.go
1 /*
2 goredo -- djb's redo implementation on pure Go
3 Copyright (C) 2020-2021 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 package main
19
20 import (
21         "io"
22         "os"
23         "path"
24         "path/filepath"
25         "strings"
26 )
27
28 func targetsCollect(root string, tgts map[string]struct{}) error {
29         root, err := filepath.Abs(root)
30         if err != nil {
31                 panic(err)
32         }
33         dir, err := os.Open(root)
34         if err != nil {
35                 return err
36         }
37         defer dir.Close()
38         for {
39                 fis, err := dir.Readdir(1 << 10)
40                 if err != nil {
41                         if err == io.EOF {
42                                 break
43                         }
44                         return err
45                 }
46                 for _, fi := range fis {
47                         if !fi.IsDir() {
48                                 continue
49                         }
50                         pth := path.Join(root, fi.Name())
51                         if fi.Name() == RedoDir {
52                                 redoDir, err := os.Open(pth)
53                                 if err != nil {
54                                         return err
55                                 }
56                                 redoFis, err := redoDir.Readdir(0)
57                                 if err != nil {
58                                         return err
59                                 }
60                                 for _, redoFi := range redoFis {
61                                         name := redoFi.Name()
62                                         if strings.HasSuffix(name, DepSuffix) {
63                                                 name = cwdMustRel(root, name)
64                                                 tgts[name[:len(name)-len(DepSuffix)]] = struct{}{}
65                                         }
66                                 }
67                                 redoDir.Close()
68                         } else {
69                                 if err = targetsCollect(pth, tgts); err != nil {
70                                         return err
71                                 }
72                         }
73                 }
74         }
75         return dir.Close()
76 }
77
78 func targetsWalker(tgts []string) ([]string, error) {
79         tgtsMap := map[string]struct{}{}
80         for _, tgt := range tgts {
81                 if err := targetsCollect(tgt, tgtsMap); err != nil {
82                         return nil, err
83                 }
84         }
85         tgts = make([]string, 0, len(tgtsMap))
86         for tgt := range tgtsMap {
87                 tgts = append(tgts, tgt)
88         }
89         return tgts, nil
90 }
91
92 func collectWholeDeps(
93         tgts map[string]struct{},
94         deps map[string]map[string]struct{},
95         seen map[string]struct{},
96 ) {
97         for tgt := range tgts {
98                 seen[tgt] = struct{}{}
99                 collectWholeDeps(deps[tgt], deps, seen)
100         }
101 }