Skip to content

Commit a0975b9

Browse files
authored
fix: Use consistent labels for cquery (#244)
1 parent fe58e24 commit a0975b9

File tree

9 files changed

+59
-29
lines changed

9 files changed

+59
-29
lines changed

MODULE.bazel.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ workspace.
143143
targets. For example, one wants to specify `maven`
144144
here if they user rules_jvm_external so that
145145
individual third party dependency change won't
146-
invalidate all targets in the mono repo.
146+
invalidate all targets in the mono repo. Note that
147+
when `--useCquery` is used, the canonical repo name
148+
must be provided but with single `@`, e.g.
149+
`@rules_jvm_external~~maven~maven`
147150
-h, --help Show this help message and exit.
148151
--ignoredRuleHashingAttributes=<ignoredRuleHashingAttributes>
149152
Attributes that should be ignored when hashing rule

cli/src/main/kotlin/com/bazel_diff/bazel/BazelQueryService.kt

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class BazelQueryService(
4545
val targets = outputFile.inputStream().buffered().use { proto ->
4646
if (useCquery) {
4747
val cqueryResult = AnalysisProtosV2.CqueryResult.parseFrom(proto)
48-
cqueryResult.resultsList.filter { inCompatibleTargetSet(it, compatibleTargetSet) }.map { it.target }
48+
cqueryResult.resultsList.filter { it.target.rule.name in compatibleTargetSet }.map { it.target }
4949
} else {
5050
mutableListOf<Build.Target>().apply {
5151
while (true) {
@@ -60,15 +60,6 @@ class BazelQueryService(
6060
return targets
6161
}
6262

63-
private fun inCompatibleTargetSet(
64-
target: AnalysisProtosV2.ConfiguredTarget,
65-
compatibleTargetSet: Set<String>
66-
): Boolean {
67-
val name = target.target.rule.name
68-
return name in compatibleTargetSet ||
69-
name.startsWith("@") && !name.startsWith("@@") && "@${name}" in compatibleTargetSet
70-
}
71-
7263
@OptIn(ExperimentalCoroutinesApi::class)
7364
private suspend fun runQuery(
7465
query: String,
@@ -111,13 +102,7 @@ class BazelQueryService(
111102
# printed
112103
return ""
113104
if "IncompatiblePlatformProvider" not in providers(target):
114-
label = str(target.label)
115-
# normalize label to be consistent with content inside proto
116-
if label.startswith("@//"):
117-
return label[1:]
118-
if label.startswith("@@//"):
119-
return label[2:]
120-
return label
105+
return str(target.label)
121106
return ""
122107
""".trimIndent())
123108
add(cqueryOutputFile.toString())
@@ -137,6 +122,7 @@ class BazelQueryService(
137122
}
138123
if (useCquery) {
139124
addAll(cqueryOptions)
125+
add("--consistent_labels")
140126
} else {
141127
addAll(commandOptions)
142128
}

cli/src/main/kotlin/com/bazel_diff/bazel/BazelRule.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class BazelRule(private val rule: Build.Rule) {
3737
val name: String = rule.name
3838

3939
private fun transformRuleInput(fineGrainedHashExternalRepos: Set<String>, ruleInput: String): String {
40-
if (ruleInput.startsWith("@") && fineGrainedHashExternalRepos.none { ruleInput.startsWith("@$it") || ruleInput.startsWith("@@${it}") }) {
40+
if (isNotMainRepo(ruleInput) && ruleInput.startsWith("@") && fineGrainedHashExternalRepos.none { ruleInput.startsWith("@$it") || ruleInput.startsWith("@@${it}") }) {
4141
val splitRule = ruleInput.split("//".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
4242
if (splitRule.size == 2) {
4343
var externalRule = splitRule[0]
@@ -47,4 +47,8 @@ class BazelRule(private val rule: Build.Rule) {
4747
}
4848
return ruleInput
4949
}
50+
51+
private fun isNotMainRepo(ruleInput: String): Boolean {
52+
return !ruleInput.startsWith("//") && !ruleInput.startsWith("@//") && !ruleInput.startsWith("@@//")
53+
}
5054
}

cli/src/main/kotlin/com/bazel_diff/hash/SourceFileHasher.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ class SourceFileHasher : KoinComponent {
4444
): ByteArray {
4545
return sha256 {
4646
val name = sourceFileTarget.name
47-
val filenamePath = if (name.startsWith("//")) {
48-
val filenameSubstring = name.substring(2)
47+
val index = isMainRepo(name);
48+
val filenamePath = if (index != -1) {
49+
val filenameSubstring = name.substring(index)
4950
Paths.get(filenameSubstring.removePrefix(":").replace(':', '/'))
5051
} else if (name.startsWith("@")) {
5152
val parts = if (name.startsWith("@@")) {
@@ -95,14 +96,28 @@ class SourceFileHasher : KoinComponent {
9596

9697
fun softDigest(sourceFileTarget: BazelSourceFileTarget, modifiedFilepaths: Set<Path> = emptySet()): ByteArray? {
9798
val name = sourceFileTarget.name
98-
if (!name.startsWith("//")) return null
99+
val index = isMainRepo(name)
100+
if (index == -1) return null
99101

100-
val filenameSubstring = name.substring(2)
102+
val filenameSubstring = name.substring(index)
101103
val filenamePath = filenameSubstring.replaceFirst(":".toRegex(), "/")
102104
val absoluteFilePath = Paths.get(workingDirectory.toString(), filenamePath)
103105
val file = absoluteFilePath.toFile()
104106
if (!file.exists() || !file.isFile) return null
105107

106108
return digest(sourceFileTarget, modifiedFilepaths)
107109
}
110+
111+
private fun isMainRepo(name: String): Int {
112+
if (name.startsWith("//")) {
113+
return 2;
114+
}
115+
if (name.startsWith("@//")) {
116+
return 3;
117+
}
118+
if (name.startsWith("@@//")) {
119+
return 4;
120+
}
121+
return -1;
122+
}
108123
}

cli/src/test/kotlin/com/bazel_diff/e2e/E2ETest.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ class E2ETest {
123123
assertThat(actual).isEqualTo(expected)
124124
}
125125

126-
@Test
127-
fun testFineGrainedHashBzlMod() {
126+
private fun testFineGrainedHashBzlMod(extraGenerateHashesArgs: List<String>, fineGrainedHashExternalRepo: String, expectedResultFile: String) {
128127
// The difference between these two snapshots is simply upgrading the Guava version.
129128
// Following is the diff. (The diff on maven_install.json is omitted)
130129
//
@@ -161,11 +160,11 @@ class E2ETest {
161160
val cli = CommandLine(BazelDiff())
162161
//From
163162
cli.execute(
164-
"generate-hashes", "-w", workingDirectoryA.absolutePath, "-b", bazelPath, "--fineGrainedHashExternalRepos", "bazel_diff_maven", from.absolutePath
163+
listOf("generate-hashes", "-w", workingDirectoryA.absolutePath, "-b", bazelPath, "--fineGrainedHashExternalRepos", fineGrainedHashExternalRepo, from.absolutePath) + extraGenerateHashesArgs
165164
)
166165
//To
167166
cli.execute(
168-
"generate-hashes", "-w", workingDirectoryB.absolutePath, "-b", bazelPath, "--fineGrainedHashExternalRepos", "bazel_diff_maven", to.absolutePath
167+
listOf("generate-hashes", "-w", workingDirectoryB.absolutePath, "-b", bazelPath, "--fineGrainedHashExternalRepos", fineGrainedHashExternalRepo, to.absolutePath) + extraGenerateHashesArgs
169168
)
170169
//Impacted targets
171170
cli.execute(
@@ -174,11 +173,21 @@ class E2ETest {
174173

175174
val actual: Set<String> = impactedTargetsOutput.readLines().filter { it.isNotBlank() }.toSet()
176175
val expected: Set<String> =
177-
javaClass.getResourceAsStream("/fixture/fine-grained-hash-bzlmod-test-impacted-targets.txt").use { it.bufferedReader().readLines().filter { it.isNotBlank() }.toSet() }
176+
javaClass.getResourceAsStream(expectedResultFile).use { it.bufferedReader().readLines().filter { it.isNotBlank() }.toSet() }
178177

179178
assertThat(actual).isEqualTo(expected)
180179
}
181180

181+
@Test
182+
fun testFineGrainedHashBzlMod() {
183+
testFineGrainedHashBzlMod(emptyList(), "bazel_diff_maven", "/fixture/fine-grained-hash-bzlmod-test-impacted-targets.txt")
184+
}
185+
186+
@Test
187+
fun testFineGrainedHashBzlModCquery() {
188+
testFineGrainedHashBzlMod(listOf("--useCquery"), "@rules_jvm_external~~maven~maven", "/fixture/fine-grained-hash-bzlmod-cquery-test-impacted-targets.txt")
189+
}
190+
182191
// TODO: re-enable the test after https://github.com/bazelbuild/bazel/issues/21010 is fixed
183192
@Ignore("cquery mode is broken with Bazel 7 because --transition=lite is crashes due to https://github.com/bazelbuild/bazel/issues/21010")
184193
@Test
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@@//src/main/java/com/integration:guava-user
2+
@@rules_jvm_external~~maven~com_google_errorprone_error_prone_annotations_2_18_0//file:file
3+
@@rules_jvm_external~~maven~com_google_guava_guava_32_0_0_jre//file:file
4+
@@rules_jvm_external~~maven~com_google_j2objc_j2objc_annotations_2_8//file:file
5+
@@rules_jvm_external~~maven~maven//:com_google_errorprone_error_prone_annotations
6+
@@rules_jvm_external~~maven~maven//:com_google_errorprone_error_prone_annotations_2_18_0_extension
7+
@@rules_jvm_external~~maven~maven//:com_google_guava_guava
8+
@@rules_jvm_external~~maven~maven//:com_google_guava_guava_32_0_0_jre_extension
9+
@@rules_jvm_external~~maven~maven//:com_google_j2objc_j2objc_annotations
10+
@@rules_jvm_external~~maven~maven//:com_google_j2objc_j2objc_annotations_2_8_extension
11+
@@rules_jvm_external~~maven~maven//:org_checkerframework_checker_qual
12+
@@rules_jvm_external~~maven~maven//:org_checkerframework_checker_qual_3_33_0_extension
13+
@@rules_jvm_external~~maven~org_checkerframework_checker_qual_3_33_0//file:file
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)