mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-28 04:07:01 -05:00
Fix included none mod libraries not being reproducible. (#923)
Closes #921
This commit is contained in:
@@ -53,7 +53,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.task.RemapTaskConfiguration;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.ZipReprocessorUtil;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
|
||||
|
||||
public final class IncludedJarFactory {
|
||||
@@ -163,7 +163,7 @@ public final class IncludedJarFactory {
|
||||
|
||||
try {
|
||||
FileUtils.copyFile(input, tempFile);
|
||||
ZipUtils.add(tempFile.toPath(), "fabric.mod.json", generateModForDependency(metadata).getBytes(StandardCharsets.UTF_8));
|
||||
ZipReprocessorUtil.appendZipEntry(tempFile, "fabric.mod.json", generateModForDependency(metadata).getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to add dummy mod while including %s".formatted(input), e);
|
||||
}
|
||||
|
||||
@@ -95,44 +95,80 @@ public class ZipReprocessorUtil {
|
||||
return;
|
||||
}
|
||||
|
||||
try (ZipFile zipFile = new ZipFile(file)) {
|
||||
try (var zipFile = new ZipFile(file)) {
|
||||
ZipEntry[] entries;
|
||||
|
||||
if (reproducibleFileOrder) {
|
||||
entries = zipFile.stream().sorted(Comparator.comparing(ZipEntry::getName, ZipReprocessorUtil::specialOrdering)).toArray(ZipEntry[]::new);
|
||||
entries = zipFile.stream()
|
||||
.sorted(Comparator.comparing(ZipEntry::getName, ZipReprocessorUtil::specialOrdering))
|
||||
.toArray(ZipEntry[]::new);
|
||||
} else {
|
||||
entries = zipFile.stream().toArray(ZipEntry[]::new);
|
||||
entries = zipFile.stream()
|
||||
.toArray(ZipEntry[]::new);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream outZip = new ByteArrayOutputStream(zipFile.size());
|
||||
final var outZip = new ByteArrayOutputStream(entries.length);
|
||||
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(outZip)) {
|
||||
try (var zipOutputStream = new ZipOutputStream(outZip)) {
|
||||
for (ZipEntry entry : entries) {
|
||||
ZipEntry newEntry = entry;
|
||||
|
||||
if (!preserveFileTimestamps) {
|
||||
newEntry = new ZipEntry(entry.getName());
|
||||
newEntry.setTime(CONSTANT_TIME_FOR_ZIP_ENTRIES);
|
||||
newEntry.setLastModifiedTime(FileTime.fromMillis(CONSTANT_TIME_FOR_ZIP_ENTRIES));
|
||||
newEntry.setLastAccessTime(FileTime.fromMillis(CONSTANT_TIME_FOR_ZIP_ENTRIES));
|
||||
setConstantFileTime(newEntry);
|
||||
}
|
||||
|
||||
zipOutputStream.putNextEntry(newEntry);
|
||||
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();
|
||||
copyZipEntry(zipOutputStream, newEntry, zipFile.getInputStream(entry));
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
|
||||
try (var fileOutputStream = new FileOutputStream(file)) {
|
||||
outZip.writeTo(fileOutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void appendZipEntry(File file, String path, byte[] data) throws IOException {
|
||||
try (var zipFile = new ZipFile(file)) {
|
||||
ZipEntry[] entries = zipFile.stream().toArray(ZipEntry[]::new);
|
||||
|
||||
final var outZip = new ByteArrayOutputStream(entries.length);
|
||||
|
||||
try (var zipOutputStream = new ZipOutputStream(outZip)) {
|
||||
// Copy existing entries
|
||||
for (ZipEntry entry : entries) {
|
||||
copyZipEntry(zipOutputStream, entry, zipFile.getInputStream(entry));
|
||||
}
|
||||
|
||||
// Append the new entry
|
||||
var entry = new ZipEntry(path);
|
||||
setConstantFileTime(entry);
|
||||
zipOutputStream.putNextEntry(entry);
|
||||
zipOutputStream.write(data, 0, data.length);
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
try (var fileOutputStream = new FileOutputStream(file)) {
|
||||
outZip.writeTo(fileOutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyZipEntry(ZipOutputStream zipOutputStream, ZipEntry entry, InputStream inputStream) throws IOException {
|
||||
zipOutputStream.putNextEntry(entry);
|
||||
byte[] buf = new byte[1024];
|
||||
int length;
|
||||
|
||||
while ((length = inputStream.read(buf)) > 0) {
|
||||
zipOutputStream.write(buf, 0, length);
|
||||
}
|
||||
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private static void setConstantFileTime(ZipEntry entry) {
|
||||
entry.setTime(ZipReprocessorUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES);
|
||||
entry.setLastModifiedTime(FileTime.fromMillis(ZipReprocessorUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES));
|
||||
entry.setLastAccessTime(FileTime.fromMillis(ZipReprocessorUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ import java.nio.file.Files
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
import net.fabricmc.loom.util.Checksum
|
||||
import net.fabricmc.loom.util.Pair
|
||||
import net.fabricmc.loom.util.ZipReprocessorUtil
|
||||
import net.fabricmc.loom.util.ZipUtils
|
||||
|
||||
class ZipUtilsTest extends Specification {
|
||||
@@ -150,4 +152,24 @@ class ZipUtilsTest extends Specification {
|
||||
then:
|
||||
!result
|
||||
}
|
||||
|
||||
def "append zip entry"() {
|
||||
given:
|
||||
// Create a reproducible input zip
|
||||
def dir = Files.createTempDirectory("loom-zip-test")
|
||||
def zip = Files.createTempFile("loom-zip-test", ".zip")
|
||||
def fileInside = dir.resolve("text.txt")
|
||||
Files.writeString(fileInside, "hello world")
|
||||
ZipUtils.pack(dir, zip)
|
||||
ZipReprocessorUtil.reprocessZip(zip.toFile(), true, false)
|
||||
|
||||
when:
|
||||
// Add an entry to it
|
||||
ZipReprocessorUtil.appendZipEntry(zip.toFile(), "fabric.mod.json", "Some text".getBytes(StandardCharsets.UTF_8))
|
||||
|
||||
then:
|
||||
ZipUtils.unpack(zip, "text.txt") == "hello world".bytes
|
||||
ZipUtils.unpack(zip, "fabric.mod.json") == "Some text".bytes
|
||||
Checksum.sha1Hex(zip) == "232ecda4c770bde8ba618e7a194a4f7b57928dc5"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user