From 2c6d4d930f4fd44f2b8c9de9ac124b99f54184ac Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Fri, 30 Dec 2022 13:06:12 +0000 Subject: [PATCH 1/4] Add getClientOnlySourceSetName (#770) --- .../minecraft/MinecraftSourceSets.java | 10 +++++----- .../loom/task/AbstractRemapJarTask.java | 17 ++++++++++++++--- .../net/fabricmc/loom/task/RemapJarTask.java | 5 +---- .../fabricmc/loom/task/RemapSourcesJarTask.java | 5 +---- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java index 1b32fed0..34f1d1eb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java @@ -220,15 +220,15 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin // The client only sources to the combined sources jar. jar.from(clientOnlySourceSet.getAllSource()); }); + + project.getTasks().withType(AbstractRemapJarTask.class, task -> { + // Set the default client only source set name + task.getClientOnlySourceSetName().convention(CLIENT_ONLY_SOURCE_SET_NAME); + }); } @Override public void afterEvaluate(Project project) { } - - public static SourceSet getClientSourceSet(Project project) { - Preconditions.checkArgument(LoomGradleExtension.get(project).areEnvironmentSourceSetsSplit(), "Cannot get client only sourceset as project is not split"); - return SourceSetHelper.getSourceSetByName(CLIENT_ONLY_SOURCE_SET_NAME, project); - } } } diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java index 334ed6e3..3abc7c0a 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractRemapJarTask.java @@ -51,6 +51,8 @@ import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.SourceSet; import org.gradle.build.event.BuildEventsListenerRegistry; import org.gradle.jvm.tasks.Jar; import org.gradle.workers.WorkAction; @@ -64,6 +66,7 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.task.service.JarManifestService; import net.fabricmc.loom.util.ZipReprocessorUtil; import net.fabricmc.loom.util.ZipUtils; +import net.fabricmc.loom.util.gradle.SourceSetHelper; public abstract class AbstractRemapJarTask extends Jar { public static final String MANIFEST_PATH = "META-INF/MANIFEST.MF"; @@ -103,6 +106,10 @@ public abstract class AbstractRemapJarTask extends Jar { @Input public abstract ListProperty getAdditionalClientOnlyEntries(); + @Input + @Optional + public abstract Property getClientOnlySourceSetName(); + private final Provider jarManifestServiceProvider; @Inject @@ -132,7 +139,7 @@ public abstract class AbstractRemapJarTask extends Jar { params.getJarManifestService().set(jarManifestServiceProvider); if (getIncludesClientOnlyClasses().get()) { - final List clientOnlyEntries = new ArrayList<>(getClientOnlyEntries()); + final List clientOnlyEntries = new ArrayList<>(getClientOnlyEntries(getClientSourceSet())); clientOnlyEntries.addAll(getAdditionalClientOnlyEntries().get()); applyClientOnlyManifestAttributes(params, clientOnlyEntries); params.getClientOnlyEntries().set(clientOnlyEntries.stream().filter(s -> s.endsWith(".class")).toList()); @@ -142,8 +149,7 @@ public abstract class AbstractRemapJarTask extends Jar { }); } - @Internal - protected abstract List getClientOnlyEntries(); + protected abstract List getClientOnlyEntries(SourceSet sourceSet); public interface AbstractRemapParams extends WorkParameters { RegularFileProperty getInputFile(); @@ -241,4 +247,9 @@ public abstract class AbstractRemapJarTask extends Jar { protected LoomGradleExtension getLoomExtension() { return LoomGradleExtension.get(getProject()); } + + private SourceSet getClientSourceSet() { + Preconditions.checkArgument(LoomGradleExtension.get(getProject()).areEnvironmentSourceSetsSplit(), "Cannot get client sourceset as project is not split"); + return SourceSetHelper.getSourceSetByName(getClientOnlySourceSetName().get(), getProject()); + } } diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index 8a379417..6c52130b 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -64,7 +64,6 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.build.nesting.IncludedJarFactory; import net.fabricmc.loom.build.nesting.JarNester; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; import net.fabricmc.loom.extension.MixinExtension; import net.fabricmc.loom.task.service.TinyRemapperService; import net.fabricmc.loom.util.Constants; @@ -321,9 +320,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask { } @Override - protected List getClientOnlyEntries() { - final SourceSet clientSourceSet = MinecraftSourceSets.Split.getClientSourceSet(getProject()); - + protected List getClientOnlyEntries(SourceSet clientSourceSet) { final ConfigurableFileCollection output = getProject().getObjects().fileCollection(); output.from(clientSourceSet.getOutput().getClassesDirs()); output.from(clientSourceSet.getOutput().getResourcesDir()); diff --git a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java index 67319696..cca9638e 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java @@ -38,7 +38,6 @@ import org.gradle.api.tasks.TaskAction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets; import net.fabricmc.loom.task.service.SourceRemapperService; import net.fabricmc.loom.util.service.BuildSharedServiceManager; import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper; @@ -62,9 +61,7 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask { } @Override - protected List getClientOnlyEntries() { - final SourceSet clientSourceSet = MinecraftSourceSets.Split.getClientSourceSet(getProject()); - + protected List getClientOnlyEntries(SourceSet clientSourceSet) { return clientSourceSet.getAllSource().getFiles().stream() .map(relativePath(getRootPaths(clientSourceSet.getAllSource().getSrcDirs()))) .toList(); From 69d25b7f602915edcb3d685a444ef4c683a736f7 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Fri, 30 Dec 2022 15:09:30 +0000 Subject: [PATCH 2/4] Include projects in jar processor inputs (#771) * Include projects in jar processor inputs * Add option to disable + tests --- .../processors/SpecContextImpl.java | 62 +++++++++++++++++-- .../net/fabricmc/loom/util/Constants.java | 1 + .../loom/util/gradle/GradleUtils.java | 6 +- .../loom/test/LoomTestConstants.groovy | 2 +- .../net/fabricmc/core/InjectedInterface.java | 6 ++ .../core/src/main/resources/fabric.mod.json | 5 ++ .../java/net/fabricmc/example/ExampleMod.java | 4 ++ 7 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/InjectedInterface.java 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 996fd8d2..1ad69b72 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java @@ -38,24 +38,31 @@ import java.util.function.Function; import java.util.stream.Stream; import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ProjectDependency; +import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.tasks.SourceSet; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.RemapConfigurationSettings; import net.fabricmc.loom.api.processor.SpecContext; +import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.fmj.FabricModJson; import net.fabricmc.loom.util.fmj.FabricModJsonFactory; +import net.fabricmc.loom.util.gradle.GradleUtils; import net.fabricmc.loom.util.gradle.SourceSetHelper; /** * @param modDependencies External mods that are depended on - * @param localMods The main mod being built. In the future this may also include other mods. + * @param localMods Mods found in the current project. + * @param compileRuntimeMods Dependent mods found in both the compile and runtime classpath. */ public record SpecContextImpl(List modDependencies, List localMods, List compileRuntimeMods) implements SpecContext { public static SpecContextImpl create(Project project) { - return new SpecContextImpl(getDependentMods(project), getMods(project), getCompileRuntimeMods(project)); + return new SpecContextImpl(getDependentMods(project), getModsInProject(project), getCompileRuntimeMods(project)); } + // Reruns a list of mods found on both the compile and/or runtime classpaths private static List getDependentMods(Project project) { final LoomGradleExtension extension = LoomGradleExtension.get(project); var mods = new ArrayList(); @@ -72,12 +79,26 @@ public record SpecContextImpl(List modDependencies, List getMods(Project project) { + private static Stream getDependentProjects(Project project) { + final Stream runtimeProjects = getLoomProjectDependencies(project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)); + final Stream compileProjects = getLoomProjectDependencies(project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)); + + return Stream.concat(runtimeProjects, compileProjects) + .distinct(); + } + + // Returns a list of Mods found in the provided project + private static List getModsInProject(Project project) { final LoomGradleExtension extension = LoomGradleExtension.get(project); var sourceSets = new ArrayList(); sourceSets.add(SourceSetHelper.getMainSourceSet(project)); @@ -99,7 +120,19 @@ public record SpecContextImpl(List modDependencies, List getCompileRuntimeMods(Project project) { + var mods = new ArrayList<>(getCompileRuntimeModsFromRemapConfigs(project).toList()); + + for (Project dependentProject : getCompileRuntimeProjectDependencies(project).toList()) { + mods.addAll(getModsInProject(dependentProject)); + } + + return Collections.unmodifiableList(mods); + } + + // Returns a list of jar mods that are found on the compile and runtime remapping configurations + private static Stream getCompileRuntimeModsFromRemapConfigs(Project project) { final LoomGradleExtension extension = LoomGradleExtension.get(project); final Function> resolve = settings -> settings.getSourceConfiguration().get().resolve().stream() @@ -115,8 +148,25 @@ public record SpecContextImpl(List modDependencies, List getCompileRuntimeProjectDependencies(Project project) { + final Stream runtimeProjects = getLoomProjectDependencies(project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)); + final List compileProjects = getLoomProjectDependencies(project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)).toList(); + + return runtimeProjects + .filter(compileProjects::contains); // Use the intersection of the two configurations. + } + + // Returns a list of Loom Projects found in the provided Configuration + private static Stream getLoomProjectDependencies(Configuration configuration) { + return configuration.getAllDependencies() + .withType(ProjectDependency.class) + .stream() + .map(ProjectDependency::getDependencyProject) + .filter(GradleUtils::isLoomProject); } // Sort to ensure stable caching diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index 3eee8cc6..bd5b6d01 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -140,5 +140,6 @@ public class Constants { public static final String MULTI_PROJECT_OPTIMISATION = "fabric.loom.multiProjectOptimisation"; public static final String DONT_REMAP = "fabric.loom.dontRemap"; public static final String DISABLE_REMAPPED_VARIANTS = "fabric.loom.disableRemappedVariants"; + public static final String DISABLE_PROJECT_DEPENDENT_MODS = "fabric.loom.disableProjectDependentMods"; } } diff --git a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java index 6361d235..7fd5d159 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java @@ -48,12 +48,16 @@ public final class GradleUtils { public static void allLoomProjects(Gradle gradle, Consumer consumer) { gradle.allprojects(project -> { - if (project.getPluginManager().hasPlugin("fabric-loom")) { + if (isLoomProject(project)) { consumer.accept(project); } }); } + public static boolean isLoomProject(Project project) { + return project.getPluginManager().hasPlugin("fabric-loom"); + } + public static Provider getBooleanPropertyProvider(Project project, String key) { return project.getProviders().gradleProperty(key).map(string -> { try { diff --git a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy index c05aed3b..4e004e03 100644 --- a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy @@ -27,7 +27,7 @@ package net.fabricmc.loom.test import org.gradle.util.GradleVersion class LoomTestConstants { - private final static String NIGHTLY_VERSION = "8.1-20221210231949+0000" + private final static String NIGHTLY_VERSION = "8.1-20221229234322+0000" private final static boolean NIGHTLY_EXISTS = nightlyExists(NIGHTLY_VERSION) public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion() diff --git a/src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/InjectedInterface.java b/src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/InjectedInterface.java new file mode 100644 index 00000000..be1b0003 --- /dev/null +++ b/src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/InjectedInterface.java @@ -0,0 +1,6 @@ +package net.fabricmc.core; + +public interface InjectedInterface { + default void newMethodThatDidNotExist() { + } +} diff --git a/src/test/resources/projects/multiproject/core/src/main/resources/fabric.mod.json b/src/test/resources/projects/multiproject/core/src/main/resources/fabric.mod.json index 66e9ea9e..bcd09423 100644 --- a/src/test/resources/projects/multiproject/core/src/main/resources/fabric.mod.json +++ b/src/test/resources/projects/multiproject/core/src/main/resources/fabric.mod.json @@ -29,5 +29,10 @@ }, "suggests": { "another-mod": "*" + }, + "custom": { + "loom:injected_interfaces": { + "net/minecraft/class_2248": ["net/fabricmc/core/InjectedInterface"] + } } } diff --git a/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/ExampleMod.java index 2afebd00..6a4f50a9 100644 --- a/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/ExampleMod.java +++ b/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/ExampleMod.java @@ -4,6 +4,7 @@ import net.fabricmc.api.ModInitializer; import net.minecraft.block.BlockState; import techreborn.blocks.cable.CableShapeUtil; import net.minecraft.util.shape.VoxelShape; +import net.minecraft.block.Blocks; public class ExampleMod implements ModInitializer { @Override @@ -18,6 +19,9 @@ public class ExampleMod implements ModInitializer { // Just here to make sure it compiles as named, not to test it runs BlockState state = null; VoxelShape shape = new CableShapeUtil(null).getShape(state); + + // Interface is injected by another project that we are depending on. + Blocks.AIR.newMethodThatDidNotExist(); } } } From 912e54cd7ac3225777808e3060171615f8478139 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Tue, 3 Jan 2023 14:11:16 +0000 Subject: [PATCH 3/4] Disallow insecure protocols for downloads. (#784) --- .../loom/util/download/DownloadBuilder.java | 20 +++++++++++++++++++ .../unit/download/DownloadFileTest.groovy | 9 +++++++++ .../unit/download/DownloadStringTest.groovy | 7 +++++++ .../test/unit/download/DownloadTest.groovy | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/util/download/DownloadBuilder.java b/src/main/java/net/fabricmc/loom/util/download/DownloadBuilder.java index 15242936..0d3949a2 100644 --- a/src/main/java/net/fabricmc/loom/util/download/DownloadBuilder.java +++ b/src/main/java/net/fabricmc/loom/util/download/DownloadBuilder.java @@ -45,6 +45,7 @@ public class DownloadBuilder { private Duration maxAge = Duration.ZERO; private DownloadProgressListener progressListener = DownloadProgressListener.NONE; private int maxRetries = 3; + private boolean allowInsecureProtocol = false; private DownloadBuilder(URI url) { this.url = url; @@ -94,7 +95,16 @@ public class DownloadBuilder { return maxAge(ONE_DAY); } + public DownloadBuilder allowInsecureProtocol() { + this.allowInsecureProtocol = true; + return this; + } + private Download build() { + if (!allowInsecureProtocol && !isSecureUrl(url)) { + throw new IllegalArgumentException("Cannot create download for url (%s) with insecure protocol".formatted(url.toString())); + } + return new Download(this.url, this.expectedHash, this.useEtag, this.forceDownload, this.offline, maxAge, progressListener); } @@ -145,6 +155,16 @@ public class DownloadBuilder { throw new IllegalStateException(); } + // See comment on org.gradle.util.internal.GUtil.isSecureUrl + private static boolean isSecureUrl(URI url) { + if ("127.0.0.1".equals(url.getHost())) { + return true; + } + + final String scheme = url.getScheme(); + return !"http".equalsIgnoreCase(scheme); + } + @FunctionalInterface private interface DownloadSupplier { T get() throws DownloadException; diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadFileTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadFileTest.groovy index 6d7a408b..e3ee8d08 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadFileTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadFileTest.groovy @@ -339,6 +339,15 @@ class DownloadFileTest extends DownloadTest { Files.readAllBytes(output) == data } + def "File: Insecure protocol"() { + setup: + def output = new File(File.createTempDir(), "file").toPath() + when: + def result = Download.create("http://fabricmc.net").downloadPath(output) + then: + thrown IllegalArgumentException + } + // Known def "Download Mojang Mappings"() { setup: diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadStringTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadStringTest.groovy index f28b20b2..319bff8f 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadStringTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadStringTest.groovy @@ -109,4 +109,11 @@ class DownloadStringTest extends DownloadTest { then: result == "Hello World!" } + + def "String: Insecure protocol"() { + when: + def result = Download.create("http://fabricmc.net").downloadString() + then: + thrown IllegalArgumentException + } } diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadTest.groovy index 36074642..b4e3981b 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/download/DownloadTest.groovy @@ -29,7 +29,7 @@ import spock.lang.Shared import spock.lang.Specification abstract class DownloadTest extends Specification { - static final String PATH = "http://localhost:9081" + static final String PATH = "http://127.0.0.1:9081" @Shared Javalin server = Javalin.create { config -> From af21d602e9105367170cc25503d7174e9c5e6caa Mon Sep 17 00:00:00 2001 From: Vladimir Romashchenko <52473614+eaglesemanation@users.noreply.github.com> Date: Tue, 10 Jan 2023 21:07:23 +0300 Subject: [PATCH 4/4] fix: Colored logging in neovim (#795) --- src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java index e1539163..b3550e1d 100644 --- a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java @@ -123,7 +123,7 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { public String name; public String request = "launch"; public String cwd; - public String console = "internalConsole"; + public String console = "integratedTerminal"; public boolean stopOnEntry = false; public String mainClass; public String vmArgs;