From 7e5053b0c501f786d8ca2cc7afa5b24ed7e90f1f Mon Sep 17 00:00:00 2001 From: Cool_Mineman <62723322+CoolMineman@users.noreply.github.com> Date: Mon, 21 Dec 2020 13:47:08 -0600 Subject: [PATCH] Respect reproducibleFileOrder and preserveFileTimestamps (#304) * Respect reproducibleFileOrder and preserveFileTimestamps * Also Respect On Sources Jars * java 8 * checkstyle * Please Rerun Actions --- .../net/fabricmc/loom/task/RemapJarTask.java | 14 +--- .../loom/task/RemapSourcesJarTask.java | 14 +++- .../loom/util/ModCompileRemapper.java | 2 +- .../fabricmc/loom/util/SourceRemapper.java | 8 +- .../loom/util/ZipReprocessorUtil.java | 79 +++++++++++++++++++ 5 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index dca964c..af0e503 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -48,6 +48,7 @@ import net.fabricmc.loom.util.GradleSupport; import net.fabricmc.loom.util.MixinRefmapHelper; import net.fabricmc.loom.util.NestedJars; import net.fabricmc.loom.util.TinyRemapperMappingsHelper; +import net.fabricmc.loom.util.ZipReprocessorUtil; import net.fabricmc.loom.util.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.util.JarRemapper; import net.fabricmc.stitch.util.Pair; @@ -151,16 +152,9 @@ public class RemapJarTask extends Jar { } } - /*try { - if (modJar.exists()) { - Files.move(modJar, modJarUnmappedCopy); - extension.addUnmappedMod(modJarUnmappedCopy); - } - - Files.move(modJarOutput, modJar); - } catch (IOException e) { - throw new RuntimeException(e); - }*/ + if (isReproducibleFileOrder() || isPreserveFileTimestamps()) { + ZipReprocessorUtil.reprocessZip(output.toFile(), isReproducibleFileOrder(), isPreserveFileTimestamps()); + } } public void scheduleRemap() throws Throwable { diff --git a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java index e518ad5..2d388fb 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java @@ -26,6 +26,8 @@ package net.fabricmc.loom.task; import java.io.File; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.provider.Property; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.Internal; @@ -33,19 +35,29 @@ import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskAction; import net.fabricmc.loom.util.SourceRemapper; +import net.fabricmc.loom.util.ZipReprocessorUtil; public class RemapSourcesJarTask extends AbstractLoomTask { private Object input; private Object output; private String direction = "intermediary"; private SourceRemapper sourceRemapper = null; + private final Property archivePreserveFileTimestamps; + private final Property archiveReproducibleFileOrder; + + public RemapSourcesJarTask() { + ObjectFactory objectFactory = getProject().getObjects(); + archivePreserveFileTimestamps = objectFactory.property(Boolean.class); + archiveReproducibleFileOrder = objectFactory.property(Boolean.class); + } @TaskAction public void remap() throws Exception { if (sourceRemapper == null) { SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); + ZipReprocessorUtil.reprocessZip(getOutput(), archivePreserveFileTimestamps.getOrElse(true), archiveReproducibleFileOrder.getOrElse(false)); } else { - sourceRemapper.scheduleRemapSources(getInput(), getOutput()); + sourceRemapper.scheduleRemapSources(getInput(), getOutput(), archivePreserveFileTimestamps.getOrElse(true), archiveReproducibleFileOrder.getOrElse(false)); } } diff --git a/src/main/java/net/fabricmc/loom/util/ModCompileRemapper.java b/src/main/java/net/fabricmc/loom/util/ModCompileRemapper.java index aa02c6d..4652f7c 100644 --- a/src/main/java/net/fabricmc/loom/util/ModCompileRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/ModCompileRemapper.java @@ -164,7 +164,7 @@ public class ModCompileRemapper { if (!remappedSources.exists() || sources.lastModified() <= 0 || sources.lastModified() > remappedSources.lastModified() || refreshDeps) { try { - sourceRemapper.scheduleRemapSources(sources, remappedSources); + sourceRemapper.scheduleRemapSources(sources, remappedSources, false, true); // Depenedency sources are used in ide only so don't need to be reproducable // Set the remapped sources creation date to match the sources if we're likely succeeded in making it remappedSources.setLastModified(sources.lastModified()); diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 387990f..36420d7 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -62,15 +62,21 @@ public class SourceRemapper { public static void remapSources(Project project, File input, File output, boolean named) throws Exception { SourceRemapper sourceRemapper = new SourceRemapper(project, named); - sourceRemapper.scheduleRemapSources(input, output); + sourceRemapper.scheduleRemapSources(input, output, false, true); sourceRemapper.remapAll(); } + @Deprecated public void scheduleRemapSources(File source, File destination) throws Exception { + scheduleRemapSources(source, destination, false, true); // Not reproducable by default, old behavior + } + + public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) throws Exception { remapTasks.add((logger) -> { try { logger.progress("remapping sources - " + source.getName()); remapSourcesInner(source, destination); + ZipReprocessorUtil.reprocessZip(destination, reproducibleFileOrder, preserveFileTimestamps); } catch (Exception e) { throw new RuntimeException("Failed to remap sources for " + source, e); } diff --git a/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java b/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java new file mode 100644 index 0000000..662acf8 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java @@ -0,0 +1,79 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +public class ZipReprocessorUtil { + private ZipReprocessorUtil() { } + + public static void reprocessZip(File file, boolean reproducibleFileOrder, boolean preserveFileTimestamps) throws IOException { + if (!reproducibleFileOrder && preserveFileTimestamps) { + return; + } + + try (ZipFile zipFile = new ZipFile(file)) { + ZipEntry[] entries; + + if (reproducibleFileOrder) { + entries = zipFile.stream().sorted((a, b) -> a.getName().compareTo(b.getName())).toArray(ZipEntry[]::new); + } else { + entries = zipFile.stream().toArray(ZipEntry[]::new); + } + + ByteArrayOutputStream outZip = new ByteArrayOutputStream(zipFile.size()); + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(outZip)) { + for (ZipEntry entry : entries) { + if (!preserveFileTimestamps) { + entry.setTime(0); + } + + zipOutputStream.putNextEntry(entry); + InputStream inputStream = zipFile.getInputStream(entry); + byte[] buf = new byte[1024]; + int length; + + while ((length = inputStream.read(buf)) > 0) { + zipOutputStream.write(buf, 0, length); + } + + zipOutputStream.closeEntry(); + } + } + + try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { + outZip.writeTo(fileOutputStream); + } + } + } +}