diff --git a/src/query/whatinputs.go b/src/query/whatinputs.go index 70cd57d74..1fcfb33bd 100644 --- a/src/query/whatinputs.go +++ b/src/query/whatinputs.go @@ -1,8 +1,10 @@ package query import ( + "cmp" "fmt" - "sort" + "maps" + "slices" "github.com/thought-machine/please/src/core" ) @@ -11,10 +13,10 @@ import ( // The targets are printed in the same order as the provided files, separated by a newline // Use printFiles to additionally echo the files themselves (i.e. print ) func WhatInputs(graph *core.BuildGraph, files []string, hidden, printFiles, ignoreUnknown bool) { - targets := graph.AllTargets() + inputs := whatInputs(graph.AllTargets(), files, hidden) for _, file := range files { - if inputLabels := whatInputs(targets, file, hidden); len(inputLabels) > 0 { + if inputLabels := inputs[file]; len(inputLabels) > 0 { for _, label := range inputLabels { if printFiles { fmt.Printf("%s ", file) @@ -27,11 +29,14 @@ func WhatInputs(graph *core.BuildGraph, files []string, hidden, printFiles, igno } } -func whatInputs(targets []*core.BuildTarget, file string, hidden bool) []core.BuildLabel { - labels := make(map[core.BuildLabel]struct{}) +func whatInputs(targets []*core.BuildTarget, files []string, hidden bool) map[string]core.BuildLabels { + filesMap := make(map[string]map[core.BuildLabel]struct{}, len(files)) + for _, file := range files { + filesMap[file] = make(map[core.BuildLabel]struct{}) + } for _, target := range targets { for _, source := range target.AllLocalSourcePaths() { - if source == file { + if labels, ok := filesMap[source]; ok { label := target.Label if !hidden { label = target.Label.Parent() @@ -40,12 +45,9 @@ func whatInputs(targets []*core.BuildTarget, file string, hidden bool) []core.Bu } } } - - ret := make(core.BuildLabels, 0, len(labels)) - for label := range labels { - ret = append(ret, label) + ret := make(map[string]core.BuildLabels, len(filesMap)) + for file, labels := range filesMap { + ret[file] = slices.SortedFunc(maps.Keys(labels), func(a, b core.BuildLabel) int { return cmp.Compare(a.String(), b.String()) }) } - sort.Sort(ret) - return ret } diff --git a/src/query/whatinputs_test.go b/src/query/whatinputs_test.go index 09e82712b..9bb56a937 100644 --- a/src/query/whatinputs_test.go +++ b/src/query/whatinputs_test.go @@ -25,8 +25,15 @@ func TestWhatInputsSingleTarget(t *testing.T) { addNewTarget(graph, pkg1, "target1", []core.BuildInput{fileSource}) graph.AddPackage(pkg1) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } func TestWhatInputsMultipleTargets(t *testing.T) { @@ -37,8 +44,64 @@ func TestWhatInputsMultipleTargets(t *testing.T) { addNewTarget(graph, pkg, "target2", []core.BuildInput{fileSource}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}, {PackageName: "package1", Name: "target2"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + {PackageName: "package1", Name: "target2"}, + }, + }, + inputLabels, + ) +} + +func TestWhatInputsMultipleFiles(t *testing.T) { + graph := core.NewGraph() + pkg := core.NewPackage("package1") + fileSource1 := core.FileLabel{File: "file1.txt", Package: pkg.Name} + addNewTarget(graph, pkg, "target1", []core.BuildInput{fileSource1}) + fileSource2 := core.FileLabel{File: "file2.txt", Package: pkg.Name} + addNewTarget(graph, pkg, "target2", []core.BuildInput{fileSource2}) + graph.AddPackage(pkg) + + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt", "package1/file2.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + "package1/file2.txt": { + {PackageName: "package1", Name: "target2"}, + }, + }, + inputLabels, + ) +} + +func TestWhatInputsMultiplePackages(t *testing.T) { + graph := core.NewGraph() + pkg1 := core.NewPackage("package1") + fileSource1 := core.FileLabel{File: "file1.txt", Package: pkg1.Name} + addNewTarget(graph, pkg1, "target1", []core.BuildInput{fileSource1}) + graph.AddPackage(pkg1) + pkg2 := core.NewPackage("package2") + fileSource2 := core.FileLabel{File: "file2.txt", Package: pkg2.Name} + addNewTarget(graph, pkg2, "target2", []core.BuildInput{fileSource2}) + graph.AddPackage(pkg2) + + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt", "package2/file2.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + "package2/file2.txt": { + {PackageName: "package2", Name: "target2"}, + }, + }, + inputLabels, + ) } func TestWhatInputsInternalTargetHidden(t *testing.T) { @@ -49,8 +112,15 @@ func TestWhatInputsInternalTargetHidden(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } func TestWhatInputsInternalTargetShown(t *testing.T) { @@ -61,8 +131,15 @@ func TestWhatInputsInternalTargetShown(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", true) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "_target1#srcs"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, true) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "_target1#srcs"}, + }, + }, + inputLabels, + ) } func TestWhatInputsSourceBothTargets(t *testing.T) { @@ -73,8 +150,15 @@ func TestWhatInputsSourceBothTargets(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{fileSource, internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } func TestWhatInputsSourceBothTargetsHidden(t *testing.T) { @@ -85,6 +169,14 @@ func TestWhatInputsSourceBothTargetsHidden(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{fileSource, internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", true) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "_target1#srcs"}, {PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, true) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "_target1#srcs"}, + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) }