diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000..09b254e --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +6.0.0 diff --git a/.gitignore b/.gitignore index 19436cd..165251c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ bazel-bin bazel-out bazel-testlogs bazel-execlog-parser +bazel-exec-log-differ diff --git a/src/main/java/com/airbnb/execlog_parser/ExecLogParser.kt b/src/main/java/com/airbnb/execlog_parser/ExecLogParser.kt index 667bc0a..c0b39c4 100644 --- a/src/main/java/com/airbnb/execlog_parser/ExecLogParser.kt +++ b/src/main/java/com/airbnb/execlog_parser/ExecLogParser.kt @@ -6,6 +6,7 @@ import java.io.File import java.io.FileInputStream import java.io.IOException import java.io.InputStream +import java.nio.file.Paths import kotlin.jvm.Throws object ExecLogParser { @@ -20,8 +21,12 @@ object ExecLogParser { return SpawnExec.parseDelimitedFrom(inputStream) } + fun normalizePath(path: String): String { + return path.replace(Regex("^bazel-out/.*?/"), "/") + } + @Throws(IOException::class) - fun getFileDigests(logPath: String): LinkedHashMap { + fun getFileDigests(logPath: String, normalizePaths: Boolean): LinkedHashMap { inputStream = FileInputStream(logPath) val fileHashMap = LinkedHashMap() var spawnExec = getNext() @@ -30,13 +35,17 @@ object ExecLogParser { val digest = fileProto.digest val hash = digest.hash val path = fileProto.path - if (fileHashMap.get(path) != null && fileHashMap.get(path)!!.hash != hash) { + var key = path + if (normalizePaths) { + key = normalizePath(path) + } + if (fileHashMap.get(key) != null && fileHashMap.get(key)!!.hash != hash) { throw Exception( "File hash changed during bazel build. Something is seriously wrong!\n" + - "$path has at least two different hashes: ${fileHashMap[path]} $hash\n" + "$key has at least two different hashes: ${fileHashMap.get(key)!!.hash} $hash\n" ) } - fileHashMap[path] = digest + fileHashMap[key] = digest } spawnExec = getNext() } @@ -44,20 +53,32 @@ object ExecLogParser { } @JvmStatic fun main(arg: Array) { - if (arg.size < 2) { + val argsList = arg.toMutableList() + + var normalizePaths = false + if (argsList.contains("--normalizePaths")) { + normalizePaths = true + argsList.remove("--normalizePaths") + } + + if (argsList.size < 2) { println("This program takes in 2-3 arguments:") println("logPath1 logPath2 [allowlist of filepaths]") throw Exception("Invalid arguments") } - val logPath1 = arg.get(0) - val logPath2 = arg.get(1) - val allowListPath = arg.getOrNull(2) + + // Resolve relative paths to the current working directory. This is a noop if the path is already + // absolute. + val logPath1 = Paths.get(argsList.get(0)).toAbsolutePath().toString() + val logPath2 = Paths.get(argsList.get(1)).toAbsolutePath().toString() + val allowListPath = argsList.getOrNull(2)?.let { Paths.get(it).toAbsolutePath().toString() } var allowList = setOf() if (allowListPath != null) { allowList = File(allowListPath).readLines().map { it.trim() }.toSet() } - val fileHashMap1 = getFileDigests(logPath1) - val fileHashMap2 = getFileDigests(logPath2) + val fileHashMap1 = getFileDigests(logPath1, normalizePaths) + val fileHashMap2 = getFileDigests(logPath2, normalizePaths) + if (fileHashMap1.keys != fileHashMap2.keys) { throw Exception( "Execution logs have different sets of inputs and outputs!\n" +