in java/io/bazel/rules/closure/webfiles/WebfilesWriter.java [121:169]
public WebfileInfo writeWebfile(WebfileInfo webfile, @WillNotClose InputStream input)
throws IOException {
checkNotNull(input, "input");
String name = WebfilesUtils.getZipEntryName(webfile);
createEntriesForParentDirectories(name);
ZipEntry entry = new ZipEntry(name);
entry.setComment(webfile.getRunpath());
// Build outputs need to be deterministic. Bazel also doesn't care about modified times because
// it uses the file digest to determine if a file is invalidated. So even if we did copy the
// time information from the original file, it still might not be a good idea.
entry.setCreationTime(EPOCH);
entry.setLastModifiedTime(EPOCH);
entry.setLastAccessTime(EPOCH);
if (isAlreadyCompressed(webfile.getWebpath())) {
// When opting out of compression, ZipOutputStream expects us to do ALL THIS
entry.setMethod(ZipEntry.STORED);
if (input instanceof ByteArrayInputStream) {
entry.setSize(input.available());
Hasher hasher = Hashing.crc32().newHasher();
input.mark(-1);
ByteStreams.copy(input, Funnels.asOutputStream(hasher));
input.reset();
entry.setCrc(hasher.hash().padToLong());
} else {
byte[] data = ByteStreams.toByteArray(input);
entry.setSize(data.length);
entry.setCrc(Hashing.crc32().hashBytes(data).padToLong());
input = new ByteArrayInputStream(data);
}
} else {
entry.setMethod(ZipEntry.DEFLATED);
}
HasherInputStream source = new HasherInputStream(input, Hashing.sha256().newHasher());
long offset = channel.position();
zip.putNextEntry(entry);
ByteStreams.copy(source, zip);
zip.closeEntry();
buffer.flush();
WebfileInfo result =
webfile
.toBuilder()
.clearPath() // Now that it's in the zip, we don't need the ctx.action execroot path.
.setInZip(true)
.setOffset(offset)
.setDigest(ByteString.copyFrom(source.hasher.hash().asBytes()))
.build();
webfiles.add(result);
return result;
}