github.com/sercand/please@v13.4.0+incompatible/src/query/somepath.go (about) 1 package query 2 3 import "fmt" 4 5 import "github.com/thought-machine/please/src/core" 6 7 // SomePath finds and returns a path between two targets. 8 // Useful for a "why on earth do I depend on this thing" type query. 9 func SomePath(graph *core.BuildGraph, label1 core.BuildLabel, label2 core.BuildLabel) { 10 // Awkwardly either target can be :all. This is an extremely useful idiom though so despite 11 // trickiness is worth supporting. 12 // Of course this calculation is also quadratic but it's not very obvious how to avoid that. 13 if label1.IsAllTargets() { 14 for _, target := range graph.PackageOrDie(label1).AllTargets() { 15 if querySomePath1(graph, target, label2, false) { 16 return 17 } 18 } 19 fmt.Printf("Couldn't find any dependency path between %s and %s\n", label1, label2) 20 } else { 21 querySomePath1(graph, graph.TargetOrDie(label1), label2, true) 22 } 23 } 24 25 func querySomePath1(graph *core.BuildGraph, target1 *core.BuildTarget, label2 core.BuildLabel, print bool) bool { 26 // Now we do the same for label2. 27 if label2.IsAllTargets() { 28 for _, target2 := range graph.PackageOrDie(label2).AllTargets() { 29 if querySomePath2(graph, target1, target2, false) { 30 return true 31 } 32 } 33 return false 34 } 35 return querySomePath2(graph, target1, graph.TargetOrDie(label2), print) 36 } 37 38 func querySomePath2(graph *core.BuildGraph, target1, target2 *core.BuildTarget, print bool) bool { 39 if !printSomePath(graph, target1, target2) && !printSomePath(graph, target2, target1) { 40 if print { 41 fmt.Printf("Couldn't find any dependency path between %s and %s\n", target1.Label, target2.Label) 42 } 43 return false 44 } 45 return true 46 } 47 48 // This is just a simple DFS through the graph. 49 func printSomePath(graph *core.BuildGraph, target1, target2 *core.BuildTarget) bool { 50 if target1 == target2 { 51 fmt.Printf("Found path:\n %s\n", target1.Label) 52 return true 53 } 54 for _, target := range graph.ReverseDependencies(target2) { 55 if printSomePath(graph, target1, target) { 56 if target2.Parent(graph) != target { 57 fmt.Printf(" %s\n", target2.Label) 58 } 59 return true 60 } 61 } 62 return false 63 }