Skip to content

Commit 7902b5a

Browse files
authored
Jar patching is reproducible (#89)
1 parent f545ae7 commit 7902b5a

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.objectweb.asm.Opcodes;
3636

3737
import javax.annotation.Nullable;
38+
import java.io.BufferedOutputStream;
3839
import java.io.BufferedReader;
3940
import java.io.ByteArrayInputStream;
4041
import java.io.ByteArrayOutputStream;
@@ -46,15 +47,18 @@
4647
import java.nio.charset.StandardCharsets;
4748
import java.nio.file.Files;
4849
import java.util.ArrayList;
50+
import java.util.Calendar;
4951
import java.util.Collection;
5052
import java.util.Collections;
53+
import java.util.GregorianCalendar;
5154
import java.util.LinkedHashMap;
5255
import java.util.List;
5356
import java.util.Map;
5457
import java.util.Optional;
5558
import java.util.Set;
5659
import java.util.TreeSet;
5760
import java.util.jar.JarEntry;
61+
import java.util.jar.JarFile;
5862
import java.util.jar.JarInputStream;
5963
import java.util.jar.JarOutputStream;
6064
import java.util.jar.Manifest;
@@ -82,6 +86,9 @@ public abstract class ExtraJavaModuleInfoTransform implements TransformAction<Ex
8286
private static final Pattern JAR_SIGNATURE_PATH = Pattern.compile("^META-INF/[^/]+\\.(SF|RSA|DSA|sf|rsa|dsa)$");
8387
private static final String SERVICES_PREFIX = "META-INF/services/";
8488

89+
// See: org.gradle.api.internal.file.archive.ZipCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES
90+
private static final long CONSTANT_TIME_FOR_ZIP_ENTRIES = new GregorianCalendar(1980, Calendar.FEBRUARY, 1, 0, 0, 0).getTimeInMillis();
91+
8592
public interface Parameter extends TransformParameters {
8693
@Input
8794
MapProperty<String, ModuleSpec> getModuleSpecs();
@@ -260,7 +267,7 @@ private void addModuleDescriptor(File originalJar, File moduleJar, ModuleInfo mo
260267
Set<String> packages = new TreeSet<>();
261268
copyAndExtractProviders(inputStream, outputStream, !moduleInfo.getMergedJars().isEmpty(), providers, packages);
262269
mergeJars(moduleInfo, outputStream, providers, packages);
263-
outputStream.putNextEntry(new JarEntry("module-info.class"));
270+
outputStream.putNextEntry(newReproducibleEntry("module-info.class"));
264271
outputStream.write(addModuleInfo(moduleInfo, providers, versionFromFilePath(originalJar.toPath()),
265272
moduleInfo.exportAllPackages ? packages : Collections.emptySet()));
266273
outputStream.closeEntry();
@@ -271,7 +278,14 @@ private void addModuleDescriptor(File originalJar, File moduleJar, ModuleInfo mo
271278
}
272279

273280
private JarOutputStream newJarOutputStream(OutputStream out, @Nullable Manifest manifest) throws IOException {
274-
return manifest == null ? new JarOutputStream(out) : new JarOutputStream(out, manifest);
281+
JarOutputStream jar = new JarOutputStream(out);
282+
if (manifest != null) {
283+
ZipEntry e = newReproducibleEntry(JarFile.MANIFEST_NAME);
284+
jar.putNextEntry(e);
285+
manifest.write(new BufferedOutputStream(jar));
286+
jar.closeEntry();
287+
}
288+
return jar;
275289
}
276290

277291
private void copyAndExtractProviders(JarInputStream inputStream, JarOutputStream outputStream, boolean willMergeJars, Map<String, List<String>> providers, Set<String> packages) throws IOException {
@@ -450,8 +464,7 @@ private void mergeJars(ModuleSpec moduleSpec, JarOutputStream outputStream, Map<
450464

451465
private void mergeServiceProviderFiles(JarOutputStream outputStream, Map<String, List<String>> providers) throws IOException {
452466
for (Map.Entry<String, List<String>> provider : providers.entrySet()) {
453-
JarEntry jarEntry = new JarEntry(SERVICES_PREFIX + provider.getKey());
454-
outputStream.putNextEntry(jarEntry);
467+
outputStream.putNextEntry(newReproducibleEntry(SERVICES_PREFIX + provider.getKey()));
455468
for (String implementation : provider.getValue()) {
456469
outputStream.write(implementation.getBytes());
457470
outputStream.write("\n".getBytes());
@@ -460,6 +473,12 @@ private void mergeServiceProviderFiles(JarOutputStream outputStream, Map<String,
460473
}
461474
}
462475

476+
private JarEntry newReproducibleEntry(String name) {
477+
JarEntry jarEntry = new JarEntry(name);
478+
jarEntry.setTime(CONSTANT_TIME_FOR_ZIP_ENTRIES);
479+
return jarEntry;
480+
}
481+
463482
private byte[] readAllBytes(InputStream inputStream) throws IOException {
464483
final int bufLen = 4 * 0x400;
465484
byte[] buf = new byte[bufLen];

0 commit comments

Comments
 (0)