11package com.bazel_diff.hash
22
3+ import com.bazel_diff.log.Logger
34import com.google.common.cache.CacheBuilder
45import com.google.common.cache.CacheLoader
56import org.koin.core.component.KoinComponent
7+ import org.koin.core.component.inject
68import java.nio.file.Files
79import java.nio.file.Path
810import java.nio.file.Paths
911
1012class ExternalRepoResolver (
11- private val workingDirectory : Path ,
12- private val bazelPath : Path ,
13- private val outputBase : Path ,
13+ private val workingDirectory : Path ,
14+ private val bazelPath : Path ,
15+ private val outputBase : Path ,
1416) : KoinComponent {
17+ private val logger: Logger by inject()
18+
1519 private val externalRoot: Path by lazy {
1620 outputBase.resolve(" external" )
1721 }
@@ -30,13 +34,32 @@ class ExternalRepoResolver(
3034
3135 private fun resolveBzlModPath (repoName : String ): Path {
3236 // Query result line should look something like "<exec root>/external/<canonical repo name>/some/bazel/target: <kind> <label>"
33- val queryResultLine = runProcessAndCaptureFirstLine(bazelPath.toString(), " query" , " @$repoName //..." , " --output" , " location" )
37+ val queryResultLine = runProcessAndCaptureFirstLine(
38+ bazelPath.toString(),
39+ " query" ,
40+ " @$repoName //..." ,
41+ " --keep_going" ,
42+ " --output" ,
43+ " location"
44+ )
45+ if (queryResultLine == null ) {
46+ // Fallback to the default external repo root if nothing was found via bazel query.
47+ // Normally this should not happen since any external repo should have at least one
48+ // target to be consumed. But if it does, we just return the default external repo root
49+ // and caller would handle the non-existent path.
50+ logger.w {
51+ " External repo $repoName has no target under it. You probably want to remove " +
52+ " this repo from `fineGrainedHashExternalRepos` since bazel-diff is not " +
53+ " able to correctly generate fine-grained hash for it."
54+ }
55+ return externalRoot.resolve(repoName);
56+ }
3457 val path = Paths .get(queryResultLine.split(" : " , limit = 2 )[0 ])
3558 val bzlModRelativePath = path.relativize(externalRoot).first()
3659 return externalRoot.resolve(bzlModRelativePath)
3760 }
3861
39- private fun runProcessAndCaptureFirstLine (vararg command : String ): String {
62+ private fun runProcessAndCaptureFirstLine (vararg command : String ): String? {
4063 val process = ProcessBuilder (* command).directory(workingDirectory.toFile()).start()
4164 process.inputStream.bufferedReader().use {
4265 // read the first line and close the stream so that Bazel doesn't need to continue
0 commit comments