// ReverseDeps For each input label, finds all targets which depend upon it. func ReverseDeps(graph *core.BuildGraph, labels []core.BuildLabel) { uniqueTargets := make(map[core.BuildLabel]struct{}) for _, label := range labels { for _, child := range graph.PackageOrDie(label.PackageName).AllChildren(graph.TargetOrDie(label)) { for _, target := range graph.ReverseDependencies(child) { if parent := target.Parent(graph); parent != nil { uniqueTargets[parent.Label] = struct{}{} } else { uniqueTargets[target.Label] = struct{}{} } } } } // Check for anything subincluding this guy too for _, pkg := range graph.PackageMap() { for _, label := range labels { if pkg.HasSubinclude(label) { uniqueTargets[core.BuildLabel{PackageName: pkg.Name, Name: "all"}] = struct{}{} } } } targets := make(core.BuildLabels, 0, len(uniqueTargets)) for target := range uniqueTargets { targets = append(targets, target) } sort.Sort(targets) for _, target := range targets { fmt.Printf("%s\n", target) } }
func addJSONTarget(graph *core.BuildGraph, ret *JSONGraph, label core.BuildLabel, done map[core.BuildLabel]struct{}) { if _, present := done[label]; present { return } done[label] = struct{}{} if label.IsAllTargets() { pkg := graph.PackageOrDie(label.PackageName) for _, target := range pkg.Targets { addJSONTarget(graph, ret, target.Label, done) } return } target := graph.TargetOrDie(label) if _, present := ret.Packages[label.PackageName]; present { ret.Packages[label.PackageName].Targets[label.Name] = makeJSONTarget(graph, target) } else { ret.Packages[label.PackageName] = JSONPackage{ Targets: map[string]JSONTarget{ label.Name: makeJSONTarget(graph, target), }, } } for _, dep := range target.Dependencies() { addJSONTarget(graph, ret, dep.Label, done) } }
func querySomePath1(graph *core.BuildGraph, target1 *core.BuildTarget, label2 core.BuildLabel, print bool) bool { // Now we do the same for label2. if label2.IsAllTargets() { for _, target2 := range graph.PackageOrDie(label2.PackageName).Targets { if querySomePath2(graph, target1, target2, false) { return true } } return false } return querySomePath2(graph, target1, graph.TargetOrDie(label2), print) }
// QuerySomePath finds and returns a path between two targets. // Useful for a "why on earth do I depend on this thing" type query. func QuerySomePath(graph *core.BuildGraph, label1 core.BuildLabel, label2 core.BuildLabel) { // Awkwardly either target can be :all. This is an extremely useful idiom though so despite // trickiness is worth supporting. // Of course this calculation is also quadratic but it's not very obvious how to avoid that. if label1.IsAllTargets() { for _, target := range graph.PackageOrDie(label1.PackageName).Targets { if querySomePath1(graph, target, label2, false) { return } } fmt.Printf("Couldn't find any dependency path between %s and %s\n", label1, label2) } else { querySomePath1(graph, graph.TargetOrDie(label1), label2, true) } }
// Queries a set of possible completions for some build labels. // If 'binary' is true it will complete only targets that are runnable binaries (but not tests). // If 'test' is true it will similarly complete only targets that are tests. func QueryCompletions(graph *core.BuildGraph, labels []core.BuildLabel, binary, test bool) { for _, label := range labels { count := 0 for _, target := range graph.PackageOrDie(label.PackageName).Targets { if (binary && (!target.IsBinary || target.IsTest)) || (test && !target.IsTest) { continue } if !strings.HasPrefix(target.Label.Name, "_") { fmt.Printf("%s\n", target.Label) count++ } } if !binary && count > 1 { fmt.Printf("//%s:all\n", label.PackageName) } } }