aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-03-06 22:27:48 +0000
committerGravatar Vladimir Moskva <vladmos@google.com>2017-03-07 10:47:52 +0000
commit8527ee53c66dc15ed033c67e55c393b0c3faa78b (patch)
tree649ad90c96fbbe169686eff5ea57334ced97d54a /src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
parent9bb9001d0b5439d1fd2ed7d62ce9d9bbe8d79806 (diff)
AndroidResourceProcessor: sort files before writing zips
walkFileTree can be non-determinisitic, so the zip entries can be listed in a different order: "A file tree is walked depth first, but you cannot make any assumptions about the iteration order that subdirectories are visited." -- PiperOrigin-RevId: 149345145 MOS_MIGRATED_REVID=149345145
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index ec50361bb5..e466b3d357 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -56,6 +56,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
+import com.google.common.collect.Ordering;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@@ -339,6 +340,7 @@ public class AndroidResourceProcessor {
SymbolFileSrcJarBuildingVisitor visitor =
new SymbolFileSrcJarBuildingVisitor(zip, generatedSourcesRoot, staticIds);
Files.walkFileTree(generatedSourcesRoot, visitor);
+ visitor.writeEntries();
}
// Set to the epoch for caching purposes.
Files.setLastModifiedTime(srcJar, FileTime.fromMillis(0L));
@@ -357,6 +359,7 @@ public class AndroidResourceProcessor {
new BufferedOutputStream(Files.newOutputStream(classJar)))) {
ClassJarBuildingVisitor visitor = new ClassJarBuildingVisitor(zip, generatedClassesRoot);
Files.walkFileTree(generatedClassesRoot, visitor);
+ visitor.writeEntries();
visitor.writeManifestContent();
}
// Set to the epoch for caching purposes.
@@ -401,11 +404,13 @@ public class AndroidResourceProcessor {
ZipBuilderVisitor visitor = new ZipBuilderVisitor(zout, resourcesRoot, "res");
visitor.setCompress(compress);
Files.walkFileTree(resourcesRoot, visitor);
+ visitor.writeEntries();
}
if (Files.exists(assetsRoot)) {
ZipBuilderVisitor visitor = new ZipBuilderVisitor(zout, assetsRoot, "assets");
visitor.setCompress(compress);
Files.walkFileTree(assetsRoot, visitor);
+ visitor.writeEntries();
}
}
}
@@ -1279,6 +1284,7 @@ public class AndroidResourceProcessor {
protected final Path root;
private final String directoryPrefix;
private int storageMethod = ZipEntry.STORED;
+ private final Collection<Path> paths = new ArrayList<>();
ZipBuilderVisitor(ZipOutputStream zip, Path root, String directory) {
this.zip = zip;
@@ -1291,6 +1297,17 @@ public class AndroidResourceProcessor {
}
/**
+ * Iterate through collected file paths in a deterministic order and write to the zip.
+ *
+ * @throws IOException if there is an error reading from the source or writing to the zip.
+ */
+ void writeEntries() throws IOException {
+ for (Path path : Ordering.natural().immutableSortedCopy(paths)) {
+ writeFileEntry(path);
+ }
+ }
+
+ /**
* Normalize timestamps for deterministic builds. Stamp .class files to be a bit newer
* than .java files. See:
* {@link com.google.devtools.build.buildjar.jarhelper.JarHelper#normalizedTimestamp(String)}
@@ -1321,9 +1338,13 @@ public class AndroidResourceProcessor {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ paths.add(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ protected void writeFileEntry(Path file) throws IOException {
byte[] content = Files.readAllBytes(file);
addEntry(file, content);
- return FileVisitResult.CONTINUE;
}
}
@@ -1375,7 +1396,7 @@ public class AndroidResourceProcessor {
}
@Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ protected void writeFileEntry(Path file) throws IOException {
if (file.getFileName().endsWith("R.java")) {
byte[] content = Files.readAllBytes(file);
if (staticIds) {
@@ -1385,7 +1406,6 @@ public class AndroidResourceProcessor {
}
addEntry(file, content);
}
- return FileVisitResult.CONTINUE;
}
}
@@ -1399,14 +1419,13 @@ public class AndroidResourceProcessor {
}
@Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ protected void writeFileEntry(Path file) throws IOException {
Path filename = file.getFileName();
String name = filename.toString();
if (name.endsWith(".class")) {
byte[] content = Files.readAllBytes(file);
addEntry(file, content);
}
- return FileVisitResult.CONTINUE;
}
private byte[] manifestContent() throws IOException {