Skip to content

Commit 5b0a9bf

Browse files
authored
Fix named attributes in legacy failing when reading back data from Module Metadata (#225)
1 parent ddc4c21 commit 5b0a9bf

File tree

8 files changed

+138
-68
lines changed

8 files changed

+138
-68
lines changed

src/legacy/java/net/neoforged/moddevgradle/legacyforge/dsl/ObfuscationExtension.java

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Objects;
55
import javax.inject.Inject;
66
import net.neoforged.moddevgradle.legacyforge.internal.MinecraftMappings;
7+
import net.neoforged.moddevgradle.legacyforge.internal.SrgMappingsRule;
78
import net.neoforged.moddevgradle.legacyforge.tasks.RemapJar;
89
import net.neoforged.moddevgradle.legacyforge.tasks.RemapOperation;
910
import org.apache.commons.lang3.StringUtils;
@@ -32,6 +33,9 @@ public abstract class ObfuscationExtension {
3233
private final Configuration installerToolsRuntime;
3334
private final FileCollection extraMixinMappings;
3435

36+
private final MinecraftMappings namedMappings;
37+
private final MinecraftMappings srgMappings;
38+
3539
@Inject
3640
public ObfuscationExtension(Project project,
3741
Configuration autoRenamingToolRuntime,
@@ -41,6 +45,9 @@ public ObfuscationExtension(Project project,
4145
this.autoRenamingToolRuntime = autoRenamingToolRuntime;
4246
this.installerToolsRuntime = installerToolsRuntime;
4347
this.extraMixinMappings = extraMixinMappings;
48+
49+
this.namedMappings = project.getObjects().named(MinecraftMappings.class, MinecraftMappings.NAMED);
50+
this.srgMappings = project.getObjects().named(MinecraftMappings.class, MinecraftMappings.SRG);
4451
}
4552

4653
private <T> Provider<T> assertConfigured(Provider<T> provider) {
@@ -123,7 +130,7 @@ public TaskProvider<RemapJar> reobfuscate(TaskProvider<? extends AbstractArchive
123130
var config = configurations.getByName(configurationName);
124131
// Mark the original configuration as NAMED to be able to disambiguate between it and the reobfuscated jar,
125132
// this is used for example by the JarJar configuration.
126-
config.getAttributes().attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.NAMED);
133+
config.getAttributes().attribute(MinecraftMappings.ATTRIBUTE, namedMappings);
127134

128135
// Now create a reobf configuration
129136
var reobfConfig = configurations.maybeCreate("reobf" + StringUtils.capitalize(configurationName));
@@ -132,7 +139,7 @@ public TaskProvider<RemapJar> reobfuscate(TaskProvider<? extends AbstractArchive
132139
for (var attribute : config.getAttributes().keySet()) {
133140
copyAttribute(project, attribute, config, reobfConfig);
134141
}
135-
reobfConfig.getAttributes().attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG);
142+
reobfConfig.getAttributes().attribute(MinecraftMappings.ATTRIBUTE, srgMappings);
136143
project.getArtifacts().add(reobfConfig.getName(), reobf);
137144

138145
// Publish the reobf configuration instead of the original one to Maven
@@ -156,11 +163,8 @@ private static <T> void copyAttribute(Project project, Attribute<T> attribute, C
156163
public Configuration createRemappingConfiguration(Configuration parent) {
157164
var remappingConfig = project.getConfigurations().create("mod" + StringUtils.capitalize(parent.getName()), spec -> {
158165
spec.setDescription("Configuration for dependencies of " + parent.getName() + " that needs to be remapped");
159-
spec.attributes(attributeContainer -> {
160-
attributeContainer.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG);
161-
});
162166
spec.setCanBeConsumed(false);
163-
spec.setCanBeResolved(false);
167+
spec.setCanBeResolved(true);
164168
spec.setTransitive(false);
165169

166170
// Unfortunately, if we simply try to make the parent extend this config, transformations will not run because the parent doesn't request remapped deps
@@ -169,29 +173,39 @@ public Configuration createRemappingConfiguration(Configuration parent) {
169173
// Additionally, we force dependencies to be non-transitive since we cannot apply the attribute hack to transitive dependencies.
170174
spec.withDependencies(dependencies -> dependencies.forEach(dep -> {
171175
if (dep instanceof ExternalModuleDependency externalModuleDependency) {
172-
project.getDependencies().constraints(constraints -> {
173-
constraints.add(parent.getName(), externalModuleDependency.getGroup() + ":" + externalModuleDependency.getName() + ":" + externalModuleDependency.getVersion(), c -> {
174-
c.attributes(a -> a.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG));
175-
});
176-
});
177176
externalModuleDependency.setTransitive(false);
177+
178+
// This rule ensures that this external module will be enriched with the attribute MAPPINGS=SRG
179+
project.getDependencies().getComponents().withModule(
180+
dep.getGroup() + ":" + dep.getName(), SrgMappingsRule.class, cfg -> {
181+
cfg.params(srgMappings);
182+
});
178183
} else if (dep instanceof FileCollectionDependency fileCollectionDependency) {
179184
project.getDependencies().constraints(constraints -> {
180185
constraints.add(parent.getName(), fileCollectionDependency.getFiles(), c -> {
181-
c.attributes(a -> a.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG));
186+
c.attributes(a -> a.attribute(MinecraftMappings.ATTRIBUTE, namedMappings));
182187
});
183188
});
184189
} else if (dep instanceof ProjectDependency projectDependency) {
185190
project.getDependencies().constraints(constraints -> {
186191
constraints.add(parent.getName(), projectDependency.getDependencyProject(), c -> {
187-
c.attributes(a -> a.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG));
192+
c.attributes(a -> a.attribute(MinecraftMappings.ATTRIBUTE, namedMappings));
188193
});
189194
});
190195
projectDependency.setTransitive(false);
191196
}
192197
}));
193198
});
194-
parent.extendsFrom(remappingConfig);
199+
200+
var remappedDep = project.getDependencyFactory().create(
201+
remappingConfig.getIncoming().artifactView(view -> {
202+
view.attributes(a -> a.attribute(MinecraftMappings.ATTRIBUTE, namedMappings));
203+
}).getFiles());
204+
remappedDep.because("Remapped mods from " + remappingConfig.getName());
205+
206+
parent.getDependencies().add(
207+
remappedDep);
208+
195209
return remappingConfig;
196210
}
197211
}

src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/LegacyForgeModDevPlugin.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.net.URI;
44
import java.util.stream.Stream;
5+
import javax.inject.Inject;
56
import net.neoforged.minecraftdependencies.MinecraftDependenciesPlugin;
67
import net.neoforged.moddevgradle.internal.ArtifactNamingStrategy;
78
import net.neoforged.moddevgradle.internal.Branding;
@@ -23,6 +24,7 @@
2324
import org.gradle.api.Project;
2425
import org.gradle.api.artifacts.ProjectDependency;
2526
import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
27+
import org.gradle.api.model.ObjectFactory;
2628
import org.gradle.api.plugins.JavaLibraryPlugin;
2729
import org.gradle.api.plugins.JavaPlugin;
2830
import org.gradle.api.tasks.SourceSet;
@@ -43,6 +45,15 @@ public class LegacyForgeModDevPlugin implements Plugin<Project> {
4345
public static final String CONFIGURATION_TOOL_ART = "autoRenamingToolRuntime";
4446
public static final String CONFIGURATION_TOOL_INSTALLERTOOLS = "installerToolsRuntime";
4547

48+
private final MinecraftMappings namedMappings;
49+
private final MinecraftMappings srgMappings;
50+
51+
@Inject
52+
public LegacyForgeModDevPlugin(ObjectFactory objectFactory) {
53+
namedMappings = objectFactory.named(MinecraftMappings.class, MinecraftMappings.NAMED);
54+
srgMappings = objectFactory.named(MinecraftMappings.class, MinecraftMappings.SRG);
55+
}
56+
4657
@Override
4758
public void apply(Project project) {
4859
project.getPlugins().apply(JavaLibraryPlugin.class);
@@ -203,36 +214,37 @@ public void enable(Project project, LegacyForgeModdingSettings settings, LegacyF
203214
parameters.getMinecraftDependencies().from(remapDeps);
204215
});
205216
params.getFrom()
206-
.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.NAMED)
217+
.attribute(MinecraftMappings.ATTRIBUTE, srgMappings)
207218
.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE);
208219
params.getTo()
209-
.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG)
220+
.attribute(MinecraftMappings.ATTRIBUTE, namedMappings)
210221
.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE);
211222
});
212223
}
213224

214-
private static void configureDependencyRemapping(Project project, ObfuscationExtension obf) {
225+
private void configureDependencyRemapping(Project project, ObfuscationExtension obf) {
215226
// JarJar cross-project dependencies are packaged into the final jar and should be remapped
216227
// We must however do this without affecting external dependencies since those are usually already in the
217228
// right namespace.
218229
var sourceSets = ExtensionUtils.getSourceSets(project);
219230
sourceSets.all(sourceSet -> {
220231
var configurationName = sourceSet.getTaskName(null, "jarJar");
221-
project.getConfigurations().getByName("jarJar").withDependencies(dependencies -> {
232+
project.getConfigurations().getByName(configurationName).withDependencies(dependencies -> {
222233
dependencies.forEach(dep -> {
223234
if (dep instanceof ProjectDependency projectDependency) {
224235
projectDependency.attributes(a -> {
225-
a.attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.SRG);
236+
a.attribute(MinecraftMappings.ATTRIBUTE, srgMappings);
226237
});
227238
}
228239
});
229240
});
230241
});
231242

232-
project.getDependencies().attributesSchema(schema -> schema.attribute(MinecraftMappings.ATTRIBUTE).getDisambiguationRules().add(MappingsDisambiguationRule.class));
233-
project.getDependencies().getArtifactTypes().named("jar", a -> {
234-
// By default all produced artifacts are NAMED
235-
a.getAttributes().attribute(MinecraftMappings.ATTRIBUTE, MinecraftMappings.NAMED);
243+
project.getDependencies().attributesSchema(schema -> {
244+
var attr = schema.attribute(MinecraftMappings.ATTRIBUTE);
245+
attr.getDisambiguationRules().add(MappingsDisambiguationRule.class, actionConfiguration -> {
246+
actionConfiguration.params(namedMappings);
247+
});
236248
});
237249

238250
obf.createRemappingConfiguration(project.getConfigurations().getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME));

src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/MappingsDisambiguationRule.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
package net.neoforged.moddevgradle.legacyforge.internal;
22

3+
import javax.inject.Inject;
34
import org.gradle.api.attributes.AttributeDisambiguationRule;
45
import org.gradle.api.attributes.MultipleCandidatesDetails;
56

67
/**
78
* This disambiguation rule will prefer NAMED over SRG when both are present.
89
*/
910
class MappingsDisambiguationRule implements AttributeDisambiguationRule<MinecraftMappings> {
11+
private final MinecraftMappings named;
12+
13+
@Inject
14+
MappingsDisambiguationRule(MinecraftMappings named) {
15+
this.named = named;
16+
}
17+
1018
@Override
1119
public void execute(MultipleCandidatesDetails<MinecraftMappings> details) {
1220
var consumerValue = details.getConsumerValue();
1321
if (consumerValue == null) {
14-
if (details.getCandidateValues().contains(MinecraftMappings.NAMED)) {
15-
details.closestMatch(MinecraftMappings.NAMED);
22+
if (details.getCandidateValues().contains(named)) {
23+
details.closestMatch(named);
1624
}
1725
}
1826
}
Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
package net.neoforged.moddevgradle.legacyforge.internal;
22

3-
import java.util.Locale;
43
import org.gradle.api.Named;
54
import org.gradle.api.attributes.Attribute;
65
import org.jetbrains.annotations.ApiStatus;
76

87
@ApiStatus.Internal
9-
public enum MinecraftMappings implements Named {
10-
NAMED,
11-
SRG;
8+
public interface MinecraftMappings extends Named {
9+
String NAMED = "named";
10+
String SRG = "srg";
1211

13-
public static final Attribute<MinecraftMappings> ATTRIBUTE = Attribute.of("net.neoforged.moddevgradle.legacy.minecraft_mappings", MinecraftMappings.class);
14-
15-
@Override
16-
public String getName() {
17-
return name().toLowerCase(Locale.ROOT);
18-
}
12+
Attribute<MinecraftMappings> ATTRIBUTE = Attribute.of("net.neoforged.moddevgradle.legacy.minecraft_mappings", MinecraftMappings.class);
1913
}

src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/RemappingTransform.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.io.IOException;
44
import javax.inject.Inject;
55
import net.neoforged.moddevgradle.legacyforge.tasks.RemapOperation;
6-
import org.gradle.api.artifacts.transform.CacheableTransform;
76
import org.gradle.api.artifacts.transform.InputArtifact;
87
import org.gradle.api.artifacts.transform.InputArtifactDependencies;
98
import org.gradle.api.artifacts.transform.TransformAction;
@@ -20,7 +19,6 @@
2019
import org.gradle.api.tasks.PathSensitivity;
2120
import org.gradle.process.ExecOperations;
2221

23-
@CacheableTransform
2422
abstract class RemappingTransform implements TransformAction<RemappingTransform.Parameters> {
2523
@InputArtifact
2624
@PathSensitive(PathSensitivity.NONE)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package net.neoforged.moddevgradle.legacyforge.internal;
2+
3+
import javax.inject.Inject;
4+
import org.gradle.api.artifacts.ComponentMetadataContext;
5+
import org.gradle.api.artifacts.ComponentMetadataRule;
6+
7+
public class SrgMappingsRule implements ComponentMetadataRule {
8+
private final MinecraftMappings srgMappings;
9+
10+
@Inject
11+
public SrgMappingsRule(MinecraftMappings srgMappings) {
12+
this.srgMappings = srgMappings;
13+
}
14+
15+
@Override
16+
public void execute(ComponentMetadataContext context) {
17+
context.getDetails().allVariants(variant -> {
18+
if (variant.getAttributes().contains(MinecraftMappings.ATTRIBUTE)) {
19+
return;
20+
}
21+
22+
variant.getAttributes().attribute(MinecraftMappings.ATTRIBUTE, srgMappings);
23+
});
24+
}
25+
}

src/test/java/net/neoforged/moddevgradle/AbstractProjectBuilderTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,25 @@ protected final AbstractListAssert<?, List<? extends String>, String, ObjectAsse
2222
}
2323

2424
protected final String describeDependency(Dependency dependency) {
25+
String result;
2526
if (dependency instanceof FileCollectionDependency fileCollectionDependency) {
26-
return fileCollectionDependency.getFiles().getFiles()
27+
result = fileCollectionDependency.getFiles().getFiles()
2728
.stream()
2829
.map(f -> project.getProjectDir().toPath().relativize(f.toPath()).toString().replace('\\', '/'))
2930
.collect(Collectors.joining(";"));
3031
} else if (dependency instanceof ExternalModuleDependency moduleDependency) {
31-
return moduleDependency.getGroup()
32+
result = moduleDependency.getGroup()
3233
+ ":" + moduleDependency.getName()
3334
+ ":" + moduleDependency.getVersion()
3435
+ formatCapabilities(moduleDependency);
3536
} else {
36-
return dependency.toString();
37+
result = dependency.toString();
3738
}
39+
40+
if (dependency.getReason() != null) {
41+
result += " (" + dependency.getReason() + ")";
42+
}
43+
return result;
3844
}
3945

4046
protected final String formatCapabilities(ExternalModuleDependency moduleDependency) {

0 commit comments

Comments
 (0)