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  }