Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.0.0
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ bazel-bin
bazel-out
bazel-testlogs
bazel-execlog-parser
bazel-exec-log-differ
41 changes: 31 additions & 10 deletions src/main/java/com/airbnb/execlog_parser/ExecLogParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -20,8 +21,12 @@ object ExecLogParser {
return SpawnExec.parseDelimitedFrom(inputStream)
}

fun normalizePath(path: String): String {
return path.replace(Regex("^bazel-out/.*?/"), "<bazel-out>/")
}

@Throws(IOException::class)
fun getFileDigests(logPath: String): LinkedHashMap<String, Digest> {
fun getFileDigests(logPath: String, normalizePaths: Boolean): LinkedHashMap<String, Digest> {
inputStream = FileInputStream(logPath)
val fileHashMap = LinkedHashMap<String, Digest>()
var spawnExec = getNext()
Expand All @@ -30,34 +35,50 @@ 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()
}
return fileHashMap
}

@JvmStatic fun main(arg: Array<String>) {
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<String>()
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" +
Expand Down