diff --git a/src/bazel.rs b/src/bazel.rs index c5b1abc4..4691e2b4 100644 --- a/src/bazel.rs +++ b/src/bazel.rs @@ -1552,7 +1552,14 @@ impl BazelOptions { if "IncompatiblePlatformProvider" not in providers(target): target_repr = repr(target) if ": in query mode a change +/// behind a main-repository `alias` reaches the target that uses the alias. +#[test] +fn main_repo_alias_change_reaches_consumer_query() { + let first = copy_workspace("cquery_main_repo_alias"); + let second = copy_workspace("cquery_main_repo_alias"); + fs::write(second.path().join("bar/baz.txt"), "after\n").unwrap(); + let impacted = diff_workspaces(first.path(), second.path(), &[]); + for name in ["//bar:baz.txt", "//bar:baz", "//:tool", "//:wrapper"] { + assert!( + impacted + .iter() + .any(|label| label == name || label.trim_start_matches("@@") == name), + "{name} should be impacted through the alias, got {impacted:?}" + ); + } +} + +/// Reproducer for : under `--useCquery` +/// the compatible-target cquery names a main-repository alias by `repr(target)`, which +/// Bazel prints with its apparent label (`//:tool`) even under `--consistent_labels`, +/// while the target itself is named canonically (`@@//:tool`). The two never match, so +/// the alias is filtered out as if it were platform-incompatible and takes its edges with +/// it: `//:wrapper` has no node for `//:tool` to depend on and is never impacted. +#[test] +fn main_repo_alias_change_reaches_consumer_cquery() { + let first = copy_workspace("cquery_main_repo_alias"); + let second = copy_workspace("cquery_main_repo_alias"); + fs::write(second.path().join("bar/baz.txt"), "after\n").unwrap(); + + let output = tempfile::tempdir().unwrap(); + let from = output.path().join("from.json"); + let to = output.path().join("to.json"); + let edges_file = output.path().join("edges.json"); + let result = output.path().join("impacted.txt"); + assert!(generate(first.path(), &from, &["--useCquery"]) + .status + .success()); + assert!(generate( + second.path(), + &to, + &[ + "--useCquery", + "--depEdgesFile", + edges_file.to_str().unwrap() + ], + ) + .status + .success()); + assert!(impacted(second.path(), &from, &to, &result, &[]) + .status + .success()); + + let hashes = hashes(&to); + assert!( + hashes.keys().any(|label| label.ends_with("//:tool")), + "the alias //:tool was dropped from the cquery hashes: {:?}", + hashes.keys().collect::>() + ); + let edges = dep_edges(&edges_file); + let wrapper_edges = edges + .iter() + .find(|(label, _)| label.ends_with("//:wrapper")) + .map(|(_, deps)| deps.clone()) + .expect("//:wrapper has dep edges"); + assert!( + wrapper_edges.iter().any(|dep| dep.ends_with("//:tool")), + "//:wrapper lost its edge to the alias //:tool: {wrapper_edges:?}" + ); + + let impacted = read_lines(&result); + for name in ["//bar:baz.txt", "//bar:baz", "//:tool", "//:wrapper"] { + assert!( + impacted + .iter() + .any(|label| label == name || label.trim_start_matches("@@") == name), + "{name} should be impacted through the alias under cquery, got {impacted:?}" + ); + } +} diff --git a/tests/resources/workspaces/cquery_main_repo_alias/BUILD.bazel b/tests/resources/workspaces/cquery_main_repo_alias/BUILD.bazel new file mode 100644 index 00000000..a03cb29a --- /dev/null +++ b/tests/resources/workspaces/cquery_main_repo_alias/BUILD.bazel @@ -0,0 +1,14 @@ +# A main-repository alias in front of the file that changes. `//:wrapper` +# reaches `bar/baz.txt` only through the alias, so it must be impacted when +# the file changes. +alias( + name = "tool", + actual = "//bar:baz", +) + +genrule( + name = "wrapper", + srcs = [":tool"], + outs = ["wrapper.txt"], + cmd = "cat $(SRCS) > $@", +) diff --git a/tests/resources/workspaces/cquery_main_repo_alias/MODULE.bazel b/tests/resources/workspaces/cquery_main_repo_alias/MODULE.bazel new file mode 100644 index 00000000..4e5587d4 --- /dev/null +++ b/tests/resources/workspaces/cquery_main_repo_alias/MODULE.bazel @@ -0,0 +1,4 @@ +module( + name = "cquery_main_repo_alias", + version = "0.0.0", +) diff --git a/tests/resources/workspaces/cquery_main_repo_alias/README.md b/tests/resources/workspaces/cquery_main_repo_alias/README.md new file mode 100644 index 00000000..11dc4456 --- /dev/null +++ b/tests/resources/workspaces/cquery_main_repo_alias/README.md @@ -0,0 +1,25 @@ +# Main-repository alias under cquery + +Reproduces [GitHub Issue #612](https://github.com/Tinder/bazel-diff/issues/612): +with `--useCquery`, a target that reaches its inputs through a main-repository +`alias` stops seeing changes to them. + +## The graph + +`//:wrapper` (a `genrule`) lists `//:tool` in its `srcs`. `//:tool` is an +`alias` of `//bar:baz`, a `filegroup` over `bar/baz.txt`. + +## Expected behaviour + +Changing `bar/baz.txt` impacts `//bar:baz.txt`, `//bar:baz`, `//:tool`, +`//:wrapper` and `//:wrapper.txt`, in query mode and in cquery mode alike. + +## Behaviour before the fix + +The compatible-target cquery that filters out `IncompatiblePlatformProvider` +targets names an alias by `repr(target)`, and Bazel prints a main-repository +alias with its apparent label (`//:tool`) even under `--consistent_labels`, +while every other target is canonical (`@@//:tool`). The two never match, so +the alias is dropped as if it were incompatible, and with it every edge from +`//:wrapper` through it. Under cquery only `@@//bar:baz` and `@@//bar:baz.txt` +are reported as impacted. diff --git a/tests/resources/workspaces/cquery_main_repo_alias/bar/BUILD.bazel b/tests/resources/workspaces/cquery_main_repo_alias/bar/BUILD.bazel new file mode 100644 index 00000000..e31cb197 --- /dev/null +++ b/tests/resources/workspaces/cquery_main_repo_alias/bar/BUILD.bazel @@ -0,0 +1,5 @@ +filegroup( + name = "baz", + srcs = ["baz.txt"], + visibility = ["//visibility:public"], +) diff --git a/tests/resources/workspaces/cquery_main_repo_alias/bar/baz.txt b/tests/resources/workspaces/cquery_main_repo_alias/bar/baz.txt new file mode 100644 index 00000000..90be1f30 --- /dev/null +++ b/tests/resources/workspaces/cquery_main_repo_alias/bar/baz.txt @@ -0,0 +1 @@ +before diff --git a/tools/e2e/rust_e2e_cases.bzl b/tools/e2e/rust_e2e_cases.bzl index 14ac6d94..c4daaa2c 100644 --- a/tools/e2e/rust_e2e_cases.bzl +++ b/tools/e2e/rust_e2e_cases.bzl @@ -223,6 +223,14 @@ RUST_E2E_SUITES = [ "name": "regressions::macro_bzl_change_impacts_callers", "timeout": "moderate", }, + { + "name": "regressions::main_repo_alias_change_reaches_consumer_cquery", + "timeout": "moderate", + }, + { + "name": "regressions::main_repo_alias_change_reaches_consumer_query", + "timeout": "moderate", + }, { "name": "regressions::module_comment_and_lock_reformat_are_noops", "timeout": "moderate",