github.com/tiagovtristao/plz@v13.4.0+incompatible/src/query/roots.go (about) 1 package query 2 3 import ( 4 "github.com/thought-machine/please/src/core" 5 "fmt" 6 "sort" 7 ) 8 9 // Roots returns build labels with no dependents from the given list. 10 // i.e. if `labels` contains `A` and `B` such that `A` depends-on `B` (possibly through some indirect path) 11 // only `B` will be output. 12 // This does not perform an ordering of the labels, but theoretically you could call this method repeatedly with a 13 // shrinking set of labels. 14 func Roots(graph *core.BuildGraph, labels core.BuildLabels) { 15 // allSeenTargets is every single reverse dependency of the passed in labels. 16 allSeenTargets := map[*core.BuildTarget]struct{}{} 17 for _, label := range labels { 18 target := graph.TargetOrDie(label) 19 // Minor efficiency, if we've seen this target already there's no point iterating it 20 // As any of its reverse dependencies will also have already been found. 21 _, ok := allSeenTargets[target] 22 if ok { 23 continue 24 } 25 26 targets := map[*core.BuildTarget]struct{}{} 27 uniqueReverseDependencies(graph, target, targets) 28 // We need to remove the current target from the returned list as it is a false positive at this point. 29 delete(targets, target) 30 for parent := range targets { 31 allSeenTargets[parent] = struct{}{} 32 } 33 } 34 for parent := range allSeenTargets { 35 // See if any of the reverse deps were passed in 36 i := indexOf(labels, parent.Label) 37 if i != -1 { 38 // If so, we know it must not be a root, so remove it from the set 39 labels[i] = labels[len(labels)-1] 40 labels[len(labels)-1] = core.BuildLabel{} 41 labels = labels[:len(labels)-1] 42 } 43 } 44 sort.Sort(labels) 45 for _, l := range labels { 46 fmt.Printf("%s\n", l) 47 } 48 } 49 50 func indexOf(labels []core.BuildLabel, label core.BuildLabel) int { 51 for i, l := range labels { 52 if l == label { 53 return i 54 } 55 } 56 return -1 57 } 58 59 func uniqueReverseDependencies(graph *core.BuildGraph, target *core.BuildTarget, targets map[*core.BuildTarget]struct{}) { 60 _, ok := targets[target] 61 if ok { 62 return 63 } 64 targets[target] = struct{}{} 65 // ReverseDependencies are the smaller order collection, so more efficient to iterate. 66 for _, child := range graph.ReverseDependencies(target) { 67 uniqueReverseDependencies(graph, child, targets) 68 } 69 }