github.com/tiagovtristao/plz@v13.4.0+incompatible/src/query/changed.go (about) 1 package query 2 3 import ( 4 "github.com/thought-machine/please/src/core" 5 "github.com/thought-machine/please/src/scm" 6 ) 7 8 // ChangedRequest is a simple parameter object 9 type ChangedRequest struct { 10 Since string 11 DiffSpec string 12 IncludeDependees string 13 } 14 15 // ChangedLabels returns all BuildLabels that have changed according to the given request. 16 func ChangedLabels(state *core.BuildState, request ChangedRequest) []core.BuildLabel { 17 workspaceChangedFiles := changedFiles(request.Since, request.DiffSpec) 18 if len(workspaceChangedFiles) == 0 { 19 return []core.BuildLabel{} 20 } 21 22 var labels []core.BuildLabel 23 targets := targetsForChangedFiles(state.Graph, workspaceChangedFiles, request.IncludeDependees) 24 for _, t := range targets { 25 if state.ShouldInclude(t) { 26 labels = append(labels, t.Label) 27 } 28 } 29 30 return labels 31 } 32 33 func changedFiles(since string, diffSpec string) []string { 34 if diffSpec != "" { 35 return scm.ChangesIn(diffSpec, "") 36 } 37 38 if since == "" { 39 since = scm.CurrentRevIdentifier() 40 } 41 42 return scm.ChangedFiles(since, true, "") 43 } 44 45 func targetsForChangedFiles(graph *core.BuildGraph, files []string, includeDependees string) []*core.BuildTarget { 46 addresses := make(map[*core.BuildTarget]struct{}) 47 for _, target := range graph.AllTargets() { 48 for _, file := range files { 49 if target.HasAbsoluteSource(file) { 50 addresses[target] = struct{}{} 51 } 52 } 53 } 54 if includeDependees != "direct" && includeDependees != "transitive" { 55 keys := make([]*core.BuildTarget, len(addresses)) 56 57 i := 0 58 for k := range addresses { 59 keys[i] = k 60 i++ 61 } 62 63 return keys 64 } 65 66 dependents := make(map[*core.BuildTarget]struct{}) 67 if includeDependees == "direct" { 68 for target := range addresses { 69 dependents[target] = struct{}{} 70 71 for _, dep := range graph.ReverseDependencies(target) { 72 dependents[dep] = struct{}{} 73 } 74 } 75 } else { 76 for target := range addresses { 77 visit(dependents, target, graph.ReverseDependencies) 78 } 79 } 80 keys := make([]*core.BuildTarget, len(dependents)) 81 82 i := 0 83 for k := range dependents { 84 keys[i] = k 85 i++ 86 } 87 88 return keys 89 } 90 91 func visit(dependents map[*core.BuildTarget]struct{}, target *core.BuildTarget, f func(*core.BuildTarget) []*core.BuildTarget) { 92 for _, dep := range f(target) { 93 if _, exists := dependents[dep]; !exists { 94 dependents[dep] = struct{}{} 95 visit(dependents, dep, f) 96 } 97 } 98 }