From 5d59759a89aa3f817816977e403207cf5065429d Mon Sep 17 00:00:00 2001
From: Juuz <6596629+Juuxel@users.noreply.github.com>
Date: Mon, 3 Nov 2025 16:55:07 +0200
Subject: [PATCH 1/2] AbstractRemapJarTask: Fix manifests not being inherited
(#1421)
* AbstractRemapJarTask: Fix manifests not being inherited
* Copy manifest before applying manifest service
This matches the original ordering of the manifest creation,
and fixes the override functionality in the service.
* Test merging named sections
---
.../loom/task/AbstractRemapJarTask.java | 36 +++++++++++++++++++
.../integration/RemapJarContentsTest.groovy | 4 +++
.../projects/remapJarContents/build.gradle | 10 ++++++
3 files changed, 50 insertions(+)
diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java
index 4bea2333..4ec34c31 100644
--- a/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java
+++ b/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java
@@ -34,6 +34,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.jar.Attributes;
import java.util.jar.Manifest;
import javax.inject.Inject;
@@ -74,6 +75,12 @@ import net.fabricmc.loom.util.gradle.SourceSetHelper;
import net.fabricmc.loom.util.service.ScopedServiceFactory;
public abstract class AbstractRemapJarTask extends Jar {
+ /**
+ * The main input jar to remap.
+ * Other contents can be added to this task, but this jar must always be present.
+ *
+ *
The input file's manifest will be copied into the remapped jar.
+ */
@InputFile
public abstract RegularFileProperty getInputFile();
@@ -143,6 +150,7 @@ public abstract class AbstractRemapJarTask extends Jar {
final WorkQueue workQueue = getWorkerExecutor().noIsolation();
workQueue.submit(workAction, params -> {
+ params.getInputFile().set(getInputFile());
params.getArchiveFile().set(getArchiveFile());
params.getSourceNamespace().set(getSourceNamespace());
@@ -181,6 +189,7 @@ public abstract class AbstractRemapJarTask extends Jar {
protected abstract Provider extends ClientEntriesService.Options> getClientOnlyEntriesOptionsProvider(SourceSet clientSourceSet);
public interface AbstractRemapParams extends WorkParameters {
+ RegularFileProperty getInputFile();
RegularFileProperty getArchiveFile();
Property getSourceNamespace();
@@ -242,11 +251,20 @@ public abstract class AbstractRemapJarTask extends Jar {
}
}
+ // Note: the inputFile parameter is the remapping input file.
+ // The main input jar is available in the parameters, but should not be used
+ // for remapping as it might be missing some files added manually to this task.
protected abstract void execute(Path inputFile) throws IOException;
protected void modifyJarManifest() throws IOException {
int count = ZipUtils.transform(outputFile, Map.of(Constants.Manifest.PATH, bytes -> {
var manifest = new Manifest(new ByteArrayInputStream(bytes));
+ byte[] sourceManifestBytes = ZipUtils.unpackNullable(getParameters().getInputFile().get().getAsFile().toPath(), Constants.Manifest.PATH);
+
+ if (sourceManifestBytes != null) {
+ var sourceManifest = new Manifest(new ByteArrayInputStream(sourceManifestBytes));
+ mergeManifests(manifest, sourceManifest);
+ }
getParameters().getJarManifestService().get().apply(manifest, getParameters().getManifestAttributes().get());
manifest.getMainAttributes().putValue(Constants.Manifest.MAPPING_NAMESPACE, getParameters().getTargetNamespace().get());
@@ -268,6 +286,24 @@ public abstract class AbstractRemapJarTask extends Jar {
ZipReprocessorUtil.reprocessZip(outputFile, isReproducibleFileOrder, isPreserveFileTimestamps, compression);
}
}
+
+ private static void mergeManifests(Manifest target, Manifest source) {
+ mergeAttributes(target.getMainAttributes(), source.getMainAttributes());
+
+ source.getEntries().forEach((name, sourceAttributes) -> {
+ final Attributes targetAttributes = target.getAttributes(name);
+
+ if (targetAttributes != null) {
+ mergeAttributes(targetAttributes, sourceAttributes);
+ } else {
+ target.getEntries().put(name, sourceAttributes);
+ }
+ });
+ }
+
+ private static void mergeAttributes(Attributes target, Attributes source) {
+ source.forEach(target::putIfAbsent);
+ }
}
@Deprecated
diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/RemapJarContentsTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/RemapJarContentsTest.groovy
index fdf556b5..85bb2e46 100644
--- a/src/test/groovy/net/fabricmc/loom/test/integration/RemapJarContentsTest.groovy
+++ b/src/test/groovy/net/fabricmc/loom/test/integration/RemapJarContentsTest.groovy
@@ -51,6 +51,10 @@ class RemapJarContentsTest extends Specification implements GradleProjectTestTra
ZipUtils.contains(gradle.getOutputFile('fabric-example-mod-1.0.0-sources.jar').toPath(), 'test_src_file.txt')
def manifest = readManifest(gradle.getOutputFile('fabric-example-mod-1.0.0.jar'))
manifest.mainAttributes.getValue('Hello-World') == 'test'
+ manifest.mainAttributes.getValue('Inherited-In-Remap-Jar') == '1234'
+ manifest.getAttributes('fabric.mod.json').getValue('Inherited-In-Remap-Jar') == '5678'
+ manifest.getAttributes('modid.mixins.json').getValue('Hello-World') == 'another test'
+ manifest.getAttributes('modid.mixins.json').getValue('Inherited-In-Remap-Jar') == '9'
where:
version << STANDARD_TEST_VERSIONS
diff --git a/src/test/resources/projects/remapJarContents/build.gradle b/src/test/resources/projects/remapJarContents/build.gradle
index cd411be5..69cfe78c 100644
--- a/src/test/resources/projects/remapJarContents/build.gradle
+++ b/src/test/resources/projects/remapJarContents/build.gradle
@@ -78,11 +78,21 @@ publishing {
}
}
+jar {
+ manifest {
+ attributes 'Inherited-In-Remap-Jar': '1234'
+ attributes(['Inherited-In-Remap-Jar': '5678'], 'fabric.mod.json') // category not present in remapJar
+ attributes(['Inherited-In-Remap-Jar': '9'], 'modid.mixins.json') // category present in remapJar
+ attributes 'Hello-World': 'shadowed in remapJar'
+ }
+}
+
remapJar {
from 'test_file.txt'
manifest {
attributes 'Hello-World': 'test'
+ attributes(['Hello-World': 'another test'], 'modid.mixins.json')
}
}
From 43023dc3b885d8c7d1f7be0ce7110179cfd566a8 Mon Sep 17 00:00:00 2001
From: modmuss50
Date: Mon, 3 Nov 2025 15:09:49 +0000
Subject: [PATCH 2/2] Update unpick
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b71ddb67..571ecdc3 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -11,7 +11,7 @@ lorenz-tiny = "4.0.2"
mercury = "0.4.3"
mercury-mixin = "0.2.2"
loom-native = "0.2.0"
-unpick = "3.0.0-beta.9"
+unpick = "3.0.0-beta.13"
# Plugins
spotless = "7.2.1"