From 103db759f617673553749d0e250da432b9c72bb6 Mon Sep 17 00:00:00 2001 From: modmuss Date: Wed, 1 Oct 2025 14:23:05 +0100 Subject: [PATCH] Fix SpecContext always resolving mod dependencies with the runtime attribute. (#1378) Likely fixes #1334 --- .../processors/SpecContextImpl.java | 20 ++++++++++++------- .../processors/SpecContextProjectView.java | 17 +++++++++++++--- .../loom/test/unit/SpecContextTest.groovy | 11 +++++----- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java index 421b37c4..0585746c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java @@ -97,7 +97,7 @@ public record SpecContextImpl( } } - return sorted(AsyncCache.joinList(futures)); + return distinctSorted(AsyncCache.joinList(futures)); } private static Stream getDependentProjects(SpecContextProjectView projectView) { @@ -129,6 +129,7 @@ public record SpecContextImpl( private static List getCompileRuntimeModsFromRemapConfigs(SpecContextProjectView projectView, AsyncCache> fmjCache) { // A set of mod ids from all remap configurations that are considered for dependency transforms. final Set runtimeModIds = getModIds( + SpecContextProjectView.ArtifactUsage.RUNTIME, projectView, fmjCache, projectView.extension().getRuntimeRemapConfigurations().stream() @@ -138,6 +139,7 @@ public record SpecContextImpl( // A set of mod ids that are found on one or more remap configurations that target the common source set. // Null when split source sets are not enabled, meaning all mods are common. final Set commonRuntimeModIds = projectView.extension().areEnvironmentSourceSetsSplit() ? getModIds( + SpecContextProjectView.ArtifactUsage.RUNTIME, projectView, fmjCache, projectView.extension().getRuntimeRemapConfigurations().stream() @@ -146,6 +148,7 @@ public record SpecContextImpl( : null; Stream compileMods = getMods( + SpecContextProjectView.ArtifactUsage.COMPILE, projectView, fmjCache, projectView.extension().getCompileRemapConfigurations().stream() @@ -161,14 +164,14 @@ public record SpecContextImpl( .toList(); } - private static Stream getMods(SpecContextProjectView projectView, AsyncCache> fmjCache, Stream stream) { - return stream.flatMap(projectView.resolveArtifacts(true)) + private static Stream getMods(SpecContextProjectView.ArtifactUsage artifactUsage, SpecContextProjectView projectView, AsyncCache> fmjCache, Stream stream) { + return stream.flatMap(projectView.resolveArtifacts(artifactUsage)) .map(modFromZip(fmjCache)) .filter(Objects::nonNull); } - private static Set getModIds(SpecContextProjectView projectView, AsyncCache> fmjCache, Stream stream) { - return getMods(projectView, fmjCache, stream) + private static Set getModIds(SpecContextProjectView.ArtifactUsage artifactUsage, SpecContextProjectView projectView, AsyncCache> fmjCache, Stream stream) { + return getMods(artifactUsage, projectView, fmjCache, stream) .map(FabricModJson::getId) .collect(Collectors.toSet()); } @@ -198,8 +201,11 @@ public record SpecContextImpl( } // Sort to ensure stable caching - private static List sorted(List mods) { - return mods.stream().sorted(Comparator.comparing(FabricModJson::getId)).toList(); + private static List distinctSorted(List mods) { + return mods.stream() + .distinct() + .sorted(Comparator.comparing(FabricModJson::getId)) + .toList(); } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextProjectView.java b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextProjectView.java index c8686a20..ee12e40f 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextProjectView.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextProjectView.java @@ -49,12 +49,23 @@ public interface SpecContextProjectView { // Returns a list of Loom Projects found in the specified Configuration Stream getLoomProjectDependencies(String name); - Function> resolveArtifacts(boolean runtime); + Function> resolveArtifacts(ArtifactUsage artifactUsage); List getMods(); boolean disableProjectDependantMods(); + enum ArtifactUsage { + RUNTIME(Usage.JAVA_RUNTIME), + COMPILE(Usage.JAVA_API); + + private final String gradleUsage; + + ArtifactUsage(String gradleUsage) { + this.gradleUsage = gradleUsage; + } + } + record Impl(Project project, LoomGradleExtension extension) implements SpecContextProjectView { @Override public Stream getLoomProjectDependencies(String name) { @@ -67,8 +78,8 @@ public interface SpecContextProjectView { } @Override - public Function> resolveArtifacts(boolean runtime) { - final Usage usage = project.getObjects().named(Usage.class, runtime ? Usage.JAVA_RUNTIME : Usage.JAVA_API); + public Function> resolveArtifacts(ArtifactUsage artifactUsage) { + final Usage usage = project.getObjects().named(Usage.class, artifactUsage.gradleUsage); return settings -> { final Configuration configuration = settings.getSourceConfiguration().get().copyRecursive(); diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/SpecContextTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/SpecContextTest.groovy index 3a07991d..ac966241 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/SpecContextTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/SpecContextTest.groovy @@ -73,8 +73,8 @@ class SpecContextTest extends Specification { when(projectView.extension()).thenReturn(extension) when(extension.getRemapConfigurations()).thenReturn(remapConfigurations) - when(projectView.resolveArtifacts(true)).thenReturn(resolve(runtimeArtifacts)) - when(projectView.resolveArtifacts(false)).thenReturn(resolve(apiArtifacts)) + when(projectView.resolveArtifacts(SpecContextProjectView.ArtifactUsage.RUNTIME)).thenReturn(resolve(runtimeArtifacts)) + when(projectView.resolveArtifacts(SpecContextProjectView.ArtifactUsage.COMPILE)).thenReturn(resolve(apiArtifacts)) implementation = createConfigurationSettings("implementation") runtimeOnly = createConfigurationSettings("runtimeOnly") @@ -165,7 +165,6 @@ class SpecContextTest extends Specification { specContext.allMods().size() == 1 } - // TODO I believe this test is testing broken behaviour def "compile only runtime only dependency"() { setup: def test1 = mod("test1") @@ -179,11 +178,11 @@ class SpecContextTest extends Specification { def specContext = SpecContextImpl.create(projectView) then: - specContext.modDependencies().size() == 2 + specContext.modDependencies().size() == 1 specContext.localMods().size() == 0 - specContext.modDependenciesCompileRuntime().size() == 0 + specContext.modDependenciesCompileRuntime().size() == 1 specContext.modDependenciesCompileRuntimeClient().size() == 0 - specContext.allMods().size() == 2 + specContext.allMods().size() == 1 } private void dependencies(Map> files) {