Skip to content

Commit 180f8f3

Browse files
Seed Hashfiles
Allows users to specify a file containing a list of newline separated file paths, this file will be read and the SHA256 value for the content of each file will be used as the seed for all targets Fixes #58
1 parent de74691 commit 180f8f3

File tree

4 files changed

+137
-33
lines changed

4 files changed

+137
-33
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.bazel_diff;
2+
3+
import java.nio.file.Path;
4+
import java.nio.file.Files;
5+
import java.io.IOException;
6+
7+
interface FilesClient {
8+
byte[] readFile(Path path) throws IOException;
9+
}
10+
11+
class FilesClientImp implements FilesClient {
12+
FilesClientImp() {}
13+
14+
@Override
15+
public byte[] readFile(Path path) throws IOException {
16+
if (path.toFile().exists() && path.toFile().canRead()) {
17+
return Files.readAllBytes(path);
18+
}
19+
return new byte[0];
20+
}
21+
}

src/main/java/com/bazel_diff/TargetHashingClient.java

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
11
package com.bazel_diff;
22

3+
import java.io.ByteArrayOutputStream;
34
import java.io.IOException;
45
import java.nio.file.Path;
56
import java.security.MessageDigest;
67
import java.security.NoSuchAlgorithmException;
78
import java.util.*;
89
import java.util.stream.Collectors;
10+
import com.google.common.primitives.Bytes;
911

1012
interface TargetHashingClient {
11-
Map<String, String> hashAllBazelTargets(Set<Path> modifiedFilepaths) throws IOException, NoSuchAlgorithmException;
12-
Map<String, String> hashAllBazelTargetsAndSourcefiles() throws IOException, NoSuchAlgorithmException;
13+
Map<String, String> hashAllBazelTargets(Set<Path> modifiedFilepaths, Set<Path> seedFilepaths) throws IOException, NoSuchAlgorithmException;
14+
Map<String, String> hashAllBazelTargetsAndSourcefiles(Set<Path> seedFilepaths) throws IOException, NoSuchAlgorithmException;
1315
Set<String> getImpactedTargets(Map<String, String> startHashes, Map<String, String> endHashes, String avoidQuery, Boolean hashAllTargets) throws IOException;
1416
}
1517

1618
class TargetHashingClientImpl implements TargetHashingClient {
1719
private BazelClient bazelClient;
20+
private FilesClient files;
1821

19-
TargetHashingClientImpl(BazelClient bazelClient) {
22+
TargetHashingClientImpl(BazelClient bazelClient, FilesClient files) {
2023
this.bazelClient = bazelClient;
24+
this.files = files;
2125
}
2226

2327
@Override
24-
public Map<String, String> hashAllBazelTargets(Set<Path> modifiedFilepaths) throws IOException, NoSuchAlgorithmException {
28+
public Map<String, String> hashAllBazelTargets(Set<Path> modifiedFilepaths, Set<Path> seedFilepaths) throws IOException, NoSuchAlgorithmException {
2529
Set<BazelSourceFileTarget> bazelSourcefileTargets = bazelClient.convertFilepathsToSourceTargets(modifiedFilepaths);
26-
return hashAllTargets(bazelSourcefileTargets);
30+
return hashAllTargets(createSeedForFilepaths(seedFilepaths), bazelSourcefileTargets);
2731
}
2832

2933
@Override
30-
public Map<String, String> hashAllBazelTargetsAndSourcefiles() throws IOException, NoSuchAlgorithmException {
34+
public Map<String, String> hashAllBazelTargetsAndSourcefiles(Set<Path> seedFilepaths) throws IOException, NoSuchAlgorithmException {
3135
Set<BazelSourceFileTarget> bazelSourcefileTargets = bazelClient.queryAllSourcefileTargets();
32-
return hashAllTargets(bazelSourcefileTargets);
36+
return hashAllTargets(createSeedForFilepaths(seedFilepaths), bazelSourcefileTargets);
3337
}
3438

3539
@Override
@@ -56,7 +60,8 @@ private byte[] createDigestForTarget(
5660
BazelTarget target,
5761
Map<String, BazelRule> allRulesMap,
5862
Set<BazelSourceFileTarget> bazelSourcefileTargets,
59-
Map<String, byte[]> ruleHashes
63+
Map<String, byte[]> ruleHashes,
64+
byte[] seedHash
6065
) throws NoSuchAlgorithmException {
6166
BazelRule targetRule = target.getRule();
6267
if (target.hasSourceFile()) {
@@ -67,24 +72,31 @@ private byte[] createDigestForTarget(
6772
if (sourceTargetDigestBytes != null) {
6873
digest.update(sourceTargetDigestBytes);
6974
}
75+
if (seedHash != null) {
76+
digest.update(seedHash);
77+
}
7078
return digest.digest().clone();
7179
}
7280
}
73-
return createDigestForRule(targetRule, allRulesMap, ruleHashes, bazelSourcefileTargets);
81+
return createDigestForRule(targetRule, allRulesMap, ruleHashes, bazelSourcefileTargets, seedHash);
7482
}
7583

7684
private byte[] createDigestForRule(
7785
BazelRule rule,
7886
Map<String, BazelRule> allRulesMap,
7987
Map<String, byte[]> ruleHashes,
80-
Set<BazelSourceFileTarget> bazelSourcefileTargets
88+
Set<BazelSourceFileTarget> bazelSourcefileTargets,
89+
byte[] seedHash
8190
) throws NoSuchAlgorithmException {
8291
byte[] existingByteArray = ruleHashes.get(rule.getName());
8392
if (existingByteArray != null) {
8493
return existingByteArray;
8594
}
8695
MessageDigest digest = MessageDigest.getInstance("SHA-256");
8796
digest.update(rule.getDigest());
97+
if (seedHash != null) {
98+
digest.update(seedHash);
99+
}
88100
for (String ruleInput : rule.getRuleInputList()) {
89101
digest.update(ruleInput.getBytes());
90102
BazelRule inputRule = allRulesMap.get(ruleInput);
@@ -94,7 +106,8 @@ private byte[] createDigestForRule(
94106
inputRule,
95107
allRulesMap,
96108
ruleHashes,
97-
bazelSourcefileTargets
109+
bazelSourcefileTargets,
110+
seedHash
98111
);
99112
if (ruleInputHash != null) {
100113
digest.update(ruleInputHash);
@@ -108,6 +121,17 @@ private byte[] createDigestForRule(
108121
return finalHashValue;
109122
}
110123

124+
private byte[] createSeedForFilepaths(Set<Path> seedFilepaths) throws IOException, NoSuchAlgorithmException {
125+
if (seedFilepaths == null || seedFilepaths.size() == 0) {
126+
return new byte[0];
127+
}
128+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
129+
for (Path path: seedFilepaths) {
130+
digest.update(this.files.readFile(path));
131+
}
132+
return digest.digest().clone();
133+
}
134+
111135
private byte[] getDigestForSourceTargetName(
112136
String sourceTargetName,
113137
Set<BazelSourceFileTarget> bazelSourcefileTargets
@@ -138,7 +162,7 @@ private String getNameForTarget(BazelTarget target) {
138162
return null;
139163
}
140164

141-
private Map<String, String> hashAllTargets(Set<BazelSourceFileTarget> bazelSourcefileTargets) throws IOException, NoSuchAlgorithmException {
165+
private Map<String, String> hashAllTargets(byte[] seedHash, Set<BazelSourceFileTarget> bazelSourcefileTargets) throws IOException, NoSuchAlgorithmException {
142166
List<BazelTarget> allTargets = bazelClient.queryAllTargets();
143167
Map<String, String> targetHashes = new HashMap<>();
144168
Map<String, byte[]> ruleHashes = new HashMap<>();
@@ -159,10 +183,13 @@ private Map<String, String> hashAllTargets(Set<BazelSourceFileTarget> bazelSourc
159183
target,
160184
allRulesMap,
161185
bazelSourcefileTargets,
162-
ruleHashes
186+
ruleHashes,
187+
seedHash
163188
);
164189
if (targetDigest != null) {
165-
targetHashes.put(targetName, convertByteArrayToString(targetDigest));
190+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
191+
outputStream.write(targetDigest);
192+
targetHashes.put(targetName, convertByteArrayToString(outputStream.toByteArray()));
166193
}
167194
}
168195
return targetHashes;

src/main/java/com/bazel_diff/main.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,28 @@ static class Exclusive {
9292
Boolean hashAllSourcefiles;
9393
}
9494

95+
@Option(names = {"-s", "--seed-filepaths"}, description = "A text file containing a newline separated list of filepaths, each of these filepaths will be read and used as a seed for all targets.")
96+
File seedFilepaths;
97+
9598
@Parameters(index = "0", description = "The filepath to write the resulting JSON of dictionary target => SHA-256 values")
9699
File outputPath;
97100

98101
@Override
99102
public Integer call() {
100103
GitClient gitClient = new GitClientImpl(parent.workspacePath);
101104
BazelClient bazelClient = new BazelClientImpl(parent.workspacePath, parent.bazelPath, parent.bazelStartupOptions, parent.bazelCommandOptions, BazelDiff.isVerbose());
102-
TargetHashingClient hashingClient = new TargetHashingClientImpl(bazelClient);
105+
TargetHashingClient hashingClient = new TargetHashingClientImpl(bazelClient, new FilesClientImp());
103106
try {
104107
gitClient.ensureAllChangesAreCommitted();
105108
Set<Path> modifiedFilepathsSet = new HashSet<>();
109+
Set<Path> seedFilepathsSet = new HashSet<>();
110+
if (seedFilepaths != null) {
111+
FileReader fileReader = new FileReader(seedFilepaths);
112+
BufferedReader bufferedReader = new BufferedReader(fileReader);
113+
seedFilepathsSet = bufferedReader.lines()
114+
.map( line -> new File(line).toPath())
115+
.collect(Collectors.toSet());
116+
}
106117
Map<String, String> hashes = new HashMap<>();
107118
if (exclusive != null) {
108119
if (exclusive.modifiedFilepaths != null) {
@@ -112,12 +123,12 @@ public Integer call() {
112123
.lines()
113124
.map( line -> new File(line).toPath())
114125
.collect(Collectors.toSet());
115-
hashes = hashingClient.hashAllBazelTargets(modifiedFilepathsSet);
126+
hashes = hashingClient.hashAllBazelTargets(modifiedFilepathsSet, seedFilepathsSet);
116127
} else if (exclusive.hashAllSourcefiles) {
117-
hashes = hashingClient.hashAllBazelTargetsAndSourcefiles();
128+
hashes = hashingClient.hashAllBazelTargetsAndSourcefiles(seedFilepathsSet);
118129
}
119130
} else {
120-
hashes = hashingClient.hashAllBazelTargets(modifiedFilepathsSet);
131+
hashes = hashingClient.hashAllBazelTargets(modifiedFilepathsSet, seedFilepathsSet);
121132
}
122133
Gson gson = new GsonBuilder().setPrettyPrinting().create();
123134
FileWriter myWriter = new FileWriter(outputPath);
@@ -182,7 +193,7 @@ public Integer call() throws IOException {
182193
}
183194
GitClient gitClient = new GitClientImpl(workspacePath);
184195
BazelClient bazelClient = new BazelClientImpl(workspacePath, bazelPath, bazelStartupOptions, bazelCommandOptions, BazelDiff.isVerbose());
185-
TargetHashingClient hashingClient = new TargetHashingClientImpl(bazelClient);
196+
TargetHashingClient hashingClient = new TargetHashingClientImpl(bazelClient, new FilesClientImp());
186197
try {
187198
gitClient.ensureAllChangesAreCommitted();
188199
} catch (IOException | InterruptedException e) {

0 commit comments

Comments
 (0)