2 goredo -- djb's redo implementation on pure Go
3 Copyright (C) 2020-2023 Sergey Matveev <stargrave@stargrave.org>
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.
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.
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/>.
27 deps map[string]map[string]*Tgt,
30 if _, ok := DepCache[tgt.rel]; ok {
33 dep, err := depRead(tgt)
37 DepCache[tgt.rel] = dep
41 if dep.build == BuildUUID {
42 tracef(CDebug, "ood: %s%s always, but already build",
43 strings.Repeat(". ", level), tgt)
46 tracef(CDebug, "ood: %s%s always", strings.Repeat(". ", level), tgt)
47 alwayses = append(alwayses, tgt)
51 for _, ifchange := range dep.ifchanges {
52 if ifchange.tgt.rel == tgt.rel {
55 if !includeSrc && isSrc(ifchange.tgt) {
59 if m, ok := deps[ifchange.tgt.rel]; ok {
62 deps[ifchange.tgt.rel] = map[string]*Tgt{tgt.rel: tgt}
64 alwayses = append(alwayses,
65 collectDeps(ifchange.tgt, level+1, deps, includeSrc)...)
71 func buildDependants(tgts []*Tgt) map[string]*Tgt {
73 tracef(CDebug, "collecting deps")
74 seen := make(map[string]*Tgt)
75 deps := make(map[string]map[string]*Tgt)
76 for _, tgtInitial := range tgts {
77 for _, tgt := range collectDeps(tgtInitial, 0, deps, false) {
78 if tgt.rel != tgtInitial.rel {
90 defer func() { Level = levelOrig }()
92 tracef(CDebug, "building %d alwayses: %v", len(seen), seen)
93 errs := make(chan error, len(seen))
95 okChecker := make(chan struct{})
97 for err := range errs {
98 ok = isOkRun(err) && ok
102 for _, tgt := range seen {
103 if err := runScript(tgt, errs, false, false); err != nil {
104 tracef(CErr, "always run error: %s, skipping dependants", err)
114 tracef(CDebug, "alwayses failed, skipping dependants")
118 queueSrc := make([]*Tgt, 0, len(seen))
119 for _, tgt := range seen {
120 queueSrc = append(queueSrc, tgt)
124 tracef(CDebug, "checking %d dependant targets: %v", len(queueSrc), queueSrc)
125 queue := make(map[string]*Tgt)
126 for _, tgt := range queueSrc {
127 for _, dep := range deps[tgt.rel] {
132 tracef(CDebug, "building %d dependant targets: %v", len(queue), queue)
133 errs = make(chan error, len(queue))
134 okChecker = make(chan struct{})
136 queueSrc = make([]*Tgt, 0)
138 for err := range errs {
139 ok = isOkRun(err) && ok
143 for _, tgt := range queue {
144 ood, err := isOODWithTrace(tgt, 0, seen)
146 tracef(CErr, "dependant error: %s, skipping dependants", err)
152 if err := runScript(tgt, errs, false, false); err != nil {
153 tracef(CErr, "dependant error: %s, skipping dependants", err)
156 queueSrc = append(queueSrc, tgt)
164 tracef(CDebug, "dependants failed, skipping them")
174 func ifchange(tgts []*Tgt, forced, traced bool) (bool, error) {
176 // only unique elements
177 m := make(map[string]*Tgt)
178 for _, t := range tgts {
182 for _, t := range m {
183 tgts = append(tgts, t)
189 defer jsAcquire("ifchange exiting")
191 seen := buildDependants(tgts)
197 tracef(CDebug, "building %d targets: %v", len(tgts), tgts)
201 okChecker := make(chan struct{})
202 errs := make(chan error, len(tgts))
204 for err := range errs {
205 ok = isOkRun(err) && ok
209 for _, tgt := range tgts {
210 if _, ok := seen[tgt.rel]; ok {
211 tracef(CDebug, "%s was already build as a dependant", tgt)
216 ood, err = isOODWithTrace(tgt, 0, seen)
220 return false, ErrLine(err)
227 tracef(CDebug, "%s is source, not redoing", tgt)
230 if err = runScript(tgt, errs, forced, traced); err != nil {
233 return false, ErrLine(err)