1
1
package com.airbnb.execlog_parser
2
2
3
3
import com.google.devtools.build.lib.exec.Protos.SpawnExec
4
+ import com.google.devtools.build.lib.exec.Protos.Digest
4
5
import java.io.File
5
6
import java.io.FileInputStream
6
7
import java.io.IOException
@@ -20,21 +21,22 @@ object ExecLogParser {
20
21
}
21
22
22
23
@Throws(IOException ::class )
23
- fun getFileHashes (logPath : String ): Map <String ,String > {
24
+ fun getFileDigests (logPath : String ): Map <String , Digest > {
24
25
inputStream = FileInputStream (logPath)
25
- val fileHashMap = mutableMapOf<String , String >()
26
+ val fileHashMap = mutableMapOf<String , Digest >()
26
27
var spawnExec = getNext()
27
28
while (spawnExec != null ) {
28
29
spawnExec.inputsList.union(spawnExec.actualOutputsList).forEach { fileProto ->
29
- val hash = fileProto.digest.hash
30
+ val digest = fileProto.digest
31
+ val hash = digest.hash
30
32
val path = fileProto.path
31
- if (fileHashMap.get(path) != null && fileHashMap.get(path) != hash) {
33
+ if (fileHashMap.get(path) != null && fileHashMap.get(path)!! .hash != hash) {
32
34
throw Exception (
33
35
" File hash changed during bazel build. Something is seriously wrong!\n " +
34
36
" $path has at least two different hashes: ${fileHashMap[path]} $hash \n "
35
37
)
36
38
}
37
- fileHashMap[path] = hash
39
+ fileHashMap[path] = digest
38
40
}
39
41
spawnExec = getNext()
40
42
}
@@ -54,8 +56,8 @@ object ExecLogParser {
54
56
if (allowListPath != null ) {
55
57
allowList = File (allowListPath).readLines().map { it.trim() }.toSet()
56
58
}
57
- val fileHashMap1 = getFileHashes (logPath1)
58
- val fileHashMap2 = getFileHashes (logPath2)
59
+ val fileHashMap1 = getFileDigests (logPath1)
60
+ val fileHashMap2 = getFileDigests (logPath2)
59
61
if (fileHashMap1.keys != fileHashMap2.keys) {
60
62
throw Exception (
61
63
" Execution logs have different sets of inputs and outputs!\n " +
@@ -64,22 +66,22 @@ object ExecLogParser {
64
66
" The second log has these additional inputs/output files: ${fileHashMap2.keys.subtract(fileHashMap1.keys)} \n "
65
67
)
66
68
}
67
- val inputHashDiffs = mutableMapOf<String , Pair <String , String >>()
69
+ val inputDigestDiffs = mutableMapOf<String , Pair <Digest , Digest >>()
68
70
fileHashMap1.keys.forEach { path ->
69
- if (fileHashMap1[path] != fileHashMap2[path]) {
71
+ if (fileHashMap1[path]!! .hash != fileHashMap2[path]!! .hash ) {
70
72
if (allowList.any {
71
73
path.endsWith(it)
72
74
}) {
73
75
return @forEach
74
76
}
75
- inputHashDiffs [path] = Pair (fileHashMap1[path]!! , fileHashMap2[path]!! )
77
+ inputDigestDiffs [path] = Pair (fileHashMap1[path]!! , fileHashMap2[path]!! )
76
78
}
77
79
}
78
- if (inputHashDiffs .isNotEmpty()) {
80
+ if (inputDigestDiffs .isNotEmpty()) {
79
81
println (" Execution logs have unexpected hash diffs, indicating the build is not deterministic" )
80
82
println (" Consider adding the path to the allowlist if its impact is small. Otherwise, please fix" )
81
- println (" input hash diffs :" )
82
- inputHashDiffs .forEach {
83
+ println (" input file digests :" )
84
+ inputDigestDiffs .forEach {
83
85
println (" ${it.key} : ${it.value.first} ${it.value.second} " )
84
86
}
85
87
throw Exception (" Execution logs have different hashes for the same input" )
0 commit comments