X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=ifchange.go;h=5c294013f7bf270e7dc89a5c50db0586e3213492;hb=HEAD;hp=bfe65f1d6468c6e163825d29b7a866f4a68104d4;hpb=c03c318031de26da3ca8e8af5f50f04727a85e91;p=goredo.git diff --git a/ifchange.go b/ifchange.go index bfe65f1..5c29401 100644 --- a/ifchange.go +++ b/ifchange.go @@ -1,107 +1,91 @@ -/* -goredo -- djb's redo implementation on pure Go -Copyright (C) 2020-2023 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 import ( - "path" "strings" ) func collectDeps( - cwd, tgtOrig string, + tgt *Tgt, level int, - deps map[string]map[string]struct{}, + deps map[string]map[string]*Tgt, includeSrc bool, - seen map[string]struct{}, -) []string { - cwd, tgt := cwdAndTgt(path.Join(cwd, tgtOrig)) - tgtFull := path.Join(cwd, tgt) - if _, ok := seen[tgtFull]; ok { +) []*Tgt { + if _, ok := DepCache[tgt.rel]; ok { return nil } - depPath := path.Join(cwd, RedoDir, tgt+DepSuffix) - depInfo, err := depRead(depPath) + dep, err := depRead(tgt) if err != nil { return nil } - // DepInfoCache[depPath] = depInfo - seen[tgtFull] = struct{}{} - var alwayses []string + DepCache[tgt.rel] = dep + var alwayses []*Tgt returnReady := false - tgtRel := cwdMustRel(cwd, tgt) - if depInfo.always { - if depInfo.build == BuildUUID { - tracef( - CDebug, "ood: %s%s always, but already build", - strings.Repeat(". ", level), tgtOrig, - ) + if dep.always { + if dep.build == BuildUUID { + tracef(CDebug, "ood: %s%s always, but already build", + strings.Repeat(". ", level), tgt) returnReady = true } else { - tracef(CDebug, "ood: %s%s always", strings.Repeat(". ", level), tgtOrig) - alwayses = append(alwayses, tgtRel) + tracef(CDebug, "ood: %s%s always", strings.Repeat(". ", level), tgt) + alwayses = append(alwayses, tgt) returnReady = true } } - for _, dep := range depInfo.ifchanges { - if dep.tgt == tgt { + for _, ifchange := range dep.ifchanges { + if ifchange.tgt.rel == tgt.rel { continue } - if !includeSrc && isSrc(cwd, dep.tgt) { + if !includeSrc && isSrc(ifchange.tgt) { continue } if !returnReady { - depRel := cwdMustRel(cwd, dep.tgt) - if m, ok := deps[depRel]; ok { - m[tgtRel] = struct{}{} + if m, ok := deps[ifchange.tgt.rel]; ok { + m[tgt.rel] = tgt } else { - m = map[string]struct{}{} - m[tgtRel] = struct{}{} - deps[depRel] = m + deps[ifchange.tgt.rel] = map[string]*Tgt{tgt.rel: tgt} } alwayses = append(alwayses, - collectDeps(cwd, dep.tgt, level+1, deps, includeSrc, seen)...) + collectDeps(ifchange.tgt, level+1, deps, includeSrc)...) } } return alwayses } -func buildDependants(tgts []string) map[string]struct{} { +func buildDependants(tgts []*Tgt) map[string]*Tgt { defer Jobs.Wait() tracef(CDebug, "collecting deps") - seen := map[string]struct{}{} - deps := map[string]map[string]struct{}{} - collectDepsSeen := make(map[string]struct{}) + seen := make(map[string]*Tgt) + deps := make(map[string]map[string]*Tgt) for _, tgtInitial := range tgts { - for _, tgt := range collectDeps(Cwd, tgtInitial, 0, deps, false, collectDepsSeen) { - if tgt != tgtInitial { - seen[tgt] = struct{}{} + for _, tgt := range collectDeps(tgtInitial, 0, deps, false) { + if tgt.rel != tgtInitial.rel { + seen[tgt.rel] = tgt } } } + TgtCache = make(map[string]*Tgt) + IfchangeCache = nil if len(seen) == 0 { return seen } - collectDepsSeen = nil levelOrig := Level - defer func() { - Level = levelOrig - }() + defer func() { Level = levelOrig }() Level = 1 tracef(CDebug, "building %d alwayses: %v", len(seen), seen) errs := make(chan error, len(seen)) @@ -113,7 +97,7 @@ func buildDependants(tgts []string) map[string]struct{} { } close(okChecker) }() - for tgt := range seen { + for _, tgt := range seen { if err := runScript(tgt, errs, false, false); err != nil { tracef(CErr, "always run error: %s, skipping dependants", err) Jobs.Wait() @@ -129,20 +113,17 @@ func buildDependants(tgts []string) map[string]struct{} { return nil } - queueSrc := make([]string, 0, len(seen)) - for tgt := range seen { + queueSrc := make([]*Tgt, 0, len(seen)) + for _, tgt := range seen { queueSrc = append(queueSrc, tgt) } - if len(queueSrc) == 0 { - return seen - } RebuildDeps: tracef(CDebug, "checking %d dependant targets: %v", len(queueSrc), queueSrc) - queue := map[string]struct{}{} + queue := make(map[string]*Tgt) for _, tgt := range queueSrc { - for dep := range deps[tgt] { - queue[dep] = struct{}{} + for _, dep := range deps[tgt.rel] { + queue[dep.rel] = dep } } @@ -150,15 +131,15 @@ RebuildDeps: errs = make(chan error, len(queue)) okChecker = make(chan struct{}) jobs := 0 - queueSrc = []string{} + queueSrc = make([]*Tgt, 0) go func() { for err := range errs { ok = isOkRun(err) && ok } close(okChecker) }() - for tgt := range queue { - ood, err := isOODWithTrace(Cwd, tgt, 0, seen) + for _, tgt := range queue { + ood, err := isOODWithTrace(tgt, 0, seen) if err != nil { tracef(CErr, "dependant error: %s, skipping dependants", err) return nil @@ -171,7 +152,7 @@ RebuildDeps: return nil } queueSrc = append(queueSrc, tgt) - seen[tgt] = struct{}{} + seen[tgt.rel] = tgt jobs++ } Jobs.Wait() @@ -188,17 +169,18 @@ RebuildDeps: goto RebuildDeps } -func ifchange(tgts []string, forced, traced bool) (bool, error) { - // only unique elements - m := make(map[string]struct{}) - for _, t := range tgts { - m[t] = struct{}{} - } - tgts = tgts[:0] - for t := range m { - tgts = append(tgts, t) +func ifchange(tgts []*Tgt, forced, traced bool) (bool, error) { + { + // only unique elements + m := make(map[string]*Tgt) + for _, t := range tgts { + m[t.a] = t + } + tgts = tgts[:0] + for _, t := range m { + tgts = append(tgts, t) + } } - m = nil jsInit() if !IsTopRedo { @@ -223,13 +205,13 @@ func ifchange(tgts []string, forced, traced bool) (bool, error) { close(okChecker) }() for _, tgt := range tgts { - if _, ok := seen[tgt]; ok { + if _, ok := seen[tgt.rel]; ok { tracef(CDebug, "%s was already build as a dependant", tgt) continue } ood = true if !forced { - ood, err = isOODWithTrace(Cwd, tgt, 0, seen) + ood, err = isOODWithTrace(tgt, 0, seen) if err != nil { Jobs.Wait() close(errs) @@ -239,7 +221,7 @@ func ifchange(tgts []string, forced, traced bool) (bool, error) { if !ood { continue } - if isSrc(Cwd, tgt) { + if isSrc(tgt) { tracef(CDebug, "%s is source, not redoing", tgt) continue }