From b7eba8b093eebfcfa26e5978ad48c951ff43ee68 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Wed, 3 Mar 2021 21:20:37 +0000 Subject: [PATCH 01/24] Start 0.7 dev cycle --- build.gradle | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index e5e456c8..53ed1319 100644 --- a/build.gradle +++ b/build.gradle @@ -14,12 +14,10 @@ targetCompatibility = 1.8 group = 'net.fabricmc' archivesBaseName = project.name -def baseVersion = '0.6' +def baseVersion = '0.7' -def build = 'local' def ENV = System.getenv() if (ENV.BUILD_NUMBER) { - build = "release #${ENV.BUILD_NUMBER}" version = baseVersion + '.' + ENV.BUILD_NUMBER } else { version = baseVersion + '.local' @@ -85,7 +83,7 @@ dependencies { jar { manifest { - attributes 'Implementation-Version': project.version + ' Build(' + build + ')' + attributes 'Implementation-Version': project.version } } From d02055eb2323f2dfd26794424ef5e52f5e5e9894 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Wed, 3 Mar 2021 21:22:10 +0000 Subject: [PATCH 02/24] Fix custom sourceset not being correctly set for runconfig tasks (#357) --- .../loom/configuration/ide/RunConfig.java | 2 ++ .../fabricmc/loom/task/AbstractRunTask.java | 28 +++---------------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java index 3cabb337..2fc79906 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java @@ -57,6 +57,7 @@ public class RunConfig { public String runDir; public String vmArgs; public String programArgs; + public SourceSet sourceSet; public Element genRuns(Element doc) { Element root = this.addXml(doc, "component", ImmutableMap.of("name", "ProjectRunConfigurationManager")); @@ -197,6 +198,7 @@ public class RunConfig { runConfig.ideaModuleName = getIdeaModuleName(project, sourceSet); runConfig.runDirIdeaUrl = "file://$PROJECT_DIR$/" + runDir; runConfig.runDir = runDir; + runConfig.sourceSet = sourceSet; // Custom parameters for (String progArg : settings.getProgramArgs()) { diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java index b944f7aa..8df8e808 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java @@ -32,31 +32,23 @@ import java.util.List; import java.util.function.Function; import org.gradle.api.Project; -import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.tasks.JavaExec; -import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.ide.RunConfig; public abstract class AbstractRunTask extends JavaExec { - private final Function configProvider; - private RunConfig config; + private final RunConfig config; - public AbstractRunTask(Function config) { + public AbstractRunTask(Function configProvider) { super(); setGroup("fabric"); - this.configProvider = config; + this.config = configProvider.apply(getProject()); - setClasspath(getProject().getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)); - classpath(this.getProject().getExtensions().getByType(LoomGradleExtension.class).getUnmappedModCollection()); + setClasspath(config.sourceSet.getRuntimeClasspath()); } @Override public void exec() { - if (config == null) { - config = configProvider.apply(getProject()); - } - List argsSplit = new ArrayList<>(); String[] args = config.programArgs.split(" "); int partPos = -1; @@ -93,10 +85,6 @@ public abstract class AbstractRunTask extends JavaExec { @Override public void setWorkingDir(File dir) { - if (config == null) { - config = configProvider.apply(getProject()); - } - if (!dir.exists()) { dir.mkdirs(); } @@ -106,19 +94,11 @@ public abstract class AbstractRunTask extends JavaExec { @Override public String getMain() { - if (config == null) { - config = configProvider.apply(getProject()); - } - return config.mainClass; } @Override public List getJvmArgs() { - if (config == null) { - config = configProvider.apply(getProject()); - } - List superArgs = super.getJvmArgs(); List args = new ArrayList<>(superArgs != null ? superArgs : Collections.emptyList()); args.addAll(Arrays.asList(config.vmArgs.split(" "))); From 679026ef31d619409187a564bc0623891f5979e6 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Thu, 4 Mar 2021 23:50:02 +0000 Subject: [PATCH 03/24] Minor cleanup/optimisations to downloading, should help a little bit more with asset downloading. Closes #359 --- .../providers/MinecraftProvider.java | 4 +- .../mappings/MojangMappingsDependency.java | 10 ++--- .../assets/MinecraftAssetsProvider.java | 44 ++++++++++--------- .../net/fabricmc/loom/util/DownloadUtil.java | 3 +- .../loom/util/HashedDownloadUtil.java | 25 ++++++----- 5 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java index e25b8ca5..508e8c3e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java @@ -102,8 +102,8 @@ public class MinecraftProvider extends DependencyProvider { try { mergeJars(getProject().getLogger()); } catch (ZipError e) { - DownloadUtil.delete(minecraftClientJar); - DownloadUtil.delete(minecraftServerJar); + HashedDownloadUtil.delete(minecraftClientJar); + HashedDownloadUtil.delete(minecraftServerJar); getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e); throw new RuntimeException(); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java index 96c4c307..62879458 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java @@ -56,7 +56,7 @@ import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; -import net.fabricmc.loom.util.DownloadUtil; +import net.fabricmc.loom.util.HashedDownloadUtil; import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.mapping.tree.TinyMappingFactory; @@ -127,11 +127,11 @@ public class MojangMappingsDependency implements SelfResolvingDependency { throw new RuntimeException("Failed to find official mojang mappings for " + getVersion()); } - String clientMappingsUrl = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS).getUrl(); - String serverMappingsUrl = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS).getUrl(); + MinecraftVersionMeta.Download clientMappingsDownload = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS); + MinecraftVersionMeta.Download serverMappingsDownload = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS); - DownloadUtil.downloadIfChanged(new URL(clientMappingsUrl), clientMappings.toFile(), project.getLogger()); - DownloadUtil.downloadIfChanged(new URL(serverMappingsUrl), serverMappings.toFile(), project.getLogger()); + HashedDownloadUtil.downloadIfInvalid(new URL(clientMappingsDownload.getUrl()), clientMappings.toFile(), clientMappingsDownload.getSha1(), project.getLogger(), false); + HashedDownloadUtil.downloadIfInvalid(new URL(serverMappingsDownload.getUrl()), serverMappings.toFile(), clientMappingsDownload.getSha1(), project.getLogger(), false); MappingSet mappings = MappingSet.create(); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java index 64722c60..97e8503c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java @@ -105,35 +105,39 @@ public class MinecraftAssetsProvider { } } else { executor.execute(() -> { - ProgressLogger progressLogger; - - if (loggers.isEmpty()) { - //Create a new logger if we need one - progressLogger = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); - progressLogger.start("Downloading assets...", "assets"); - } else { - // use a free logger if we can - progressLogger = loggers.pop(); - } - - String assetName = entry.getKey(); - int end = assetName.lastIndexOf("/") + 1; + final String[] assetName = {entry.getKey()}; + int end = assetName[0].lastIndexOf("/") + 1; if (end > 0) { - assetName = assetName.substring(end); + assetName[0] = assetName[0].substring(end); } - project.getLogger().debug(":downloading asset " + assetName); - progressLogger.progress(String.format("%-30.30s", assetName) + " - " + sha1); + project.getLogger().debug("validating asset " + assetName[0]); + + final ProgressLogger[] progressLogger = new ProgressLogger[1]; try { - HashedDownloadUtil.downloadIfInvalid(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, sha1, project.getLogger(), true); + HashedDownloadUtil.downloadIfInvalid(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, sha1, project.getLogger(), true, () -> { + if (loggers.isEmpty()) { + //Create a new logger if we need one + progressLogger[0] = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); + progressLogger[0].start("Downloading assets...", "assets"); + } else { + // use a free logger if we can + progressLogger[0] = loggers.pop(); + } + + project.getLogger().debug("downloading asset " + assetName[0]); + progressLogger[0].progress(String.format("%-30.30s", assetName[0]) + " - " + sha1); + }); } catch (IOException e) { - throw new RuntimeException("Failed to download: " + assetName, e); + throw new RuntimeException("Failed to download: " + assetName[0], e); } - //Give this logger back - loggers.add(progressLogger); + if (progressLogger[0] != null) { + //Give this logger back if we used it + loggers.add(progressLogger[0]); + } }); } } diff --git a/src/main/java/net/fabricmc/loom/util/DownloadUtil.java b/src/main/java/net/fabricmc/loom/util/DownloadUtil.java index 9bb2b7e2..90131b4c 100644 --- a/src/main/java/net/fabricmc/loom/util/DownloadUtil.java +++ b/src/main/java/net/fabricmc/loom/util/DownloadUtil.java @@ -89,6 +89,7 @@ public class DownloadUtil { if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) { //Didn't get what we expected + delete(to); throw new IOException(connection.getResponseMessage() + " for " + from); } @@ -111,7 +112,7 @@ public class DownloadUtil { try { // Try download to the output FileUtils.copyInputStreamToFile(connection.getInputStream(), to); } catch (IOException e) { - to.delete(); // Probably isn't good if it fails to copy/save + delete(to); // Probably isn't good if it fails to copy/save throw e; } diff --git a/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java b/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java index da294b8e..86cf80a3 100644 --- a/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java +++ b/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java @@ -25,6 +25,7 @@ package net.fabricmc.loom.util; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -41,19 +42,23 @@ import net.fabricmc.loom.LoomGradlePlugin; public class HashedDownloadUtil { public static void downloadIfInvalid(URL from, File to, String expectedHash, Logger logger, boolean quiet) throws IOException { + downloadIfInvalid(from, to, expectedHash, logger, quiet, () -> { }); + } + + public static void downloadIfInvalid(URL from, File to, String expectedHash, Logger logger, boolean quiet, Runnable startDownload) throws IOException { if (LoomGradlePlugin.refreshDeps) { delete(to); } - if (to.exists()) { - String sha1 = getSha1(to, logger); + String sha1 = getSha1(to, logger); - if (expectedHash.equals(sha1)) { - // The hash in the sha1 file matches - return; - } + if (expectedHash.equals(sha1)) { + // The hash in the sha1 file matches + return; } + startDownload.run(); + HttpURLConnection connection = (HttpURLConnection) from.openConnection(); connection.setRequestProperty("Accept-Encoding", "gzip"); connection.connect(); @@ -62,6 +67,7 @@ public class HashedDownloadUtil { if ((code < 200 || code > 299) && code != HttpURLConnection.HTTP_NOT_MODIFIED) { //Didn't get what we expected + delete(to); throw new IOException(connection.getResponseMessage() + " for " + from); } @@ -96,12 +102,11 @@ public class HashedDownloadUtil { private static String getSha1(File to, Logger logger) { File sha1File = getSha1File(to); - if (!sha1File.exists()) { - return null; - } - try { return Files.asCharSource(sha1File, StandardCharsets.UTF_8).read(); + } catch (FileNotFoundException ignored) { + // Quicker to catch this than do an exists check before. + return null; } catch (IOException e) { logger.warn("Error reading sha1 file '{}'.", sha1File); return null; From 87f3743b2423b59e40ca5a74e8641affffa57499 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 6 Mar 2021 11:40:07 +0000 Subject: [PATCH 04/24] Rewrite tests to be easier to write and maintain (#361) --- .github/workflows/test-push.yml | 55 ++++- build.gradle | 39 +++- .../fabricmc/loom/AccessWidenerTest.groovy | 56 +++++ .../net/fabricmc/loom/BuildUtils.groovy | 209 ------------------ .../net/fabricmc/loom/DecompileTest.groovy | 54 +++++ .../loom/EmptyBuildFunctionalTest.groovy | 51 ----- .../EmptyBuildMojangFunctionalTest.groovy | 50 ----- .../net/fabricmc/loom/KotlinTest.groovy | 50 +++++ .../fabricmc/loom/LegacyProjectTest.groovy | 53 +++++ .../loom/MixinBuildFunctionalTest.groovy | 69 ------ .../loom/MojangMappingsProjectTest.groovy | 50 +++++ .../loom/ReproducibleBuildTest.groovy | 70 ++++++ .../loom/SimpleBuildFunctionalTest.groovy | 62 ------ .../fabricmc/loom/SimpleProjectTest.groovy | 63 ++++++ .../loom/util/ArchiveAssertionsTrait.groovy | 41 ++++ .../loom/util/ProjectTestTrait.groovy | 97 ++++++++ .../accesswidener/expected.accesswidener | 7 + .../projects/accesswidener/build.gradle | 96 ++++++++ .../projects/accesswidener/gradle.properties | 17 ++ .../projects/accesswidener/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleMod.java | 14 ++ .../fabricmc/example/mixin/ExampleMixin.java | 15 ++ .../src/main/resources/fabric.mod.json | 37 ++++ .../src/main/resources/modid.accesswidener | 7 + .../src/main/resources/modid.mixins.json | 14 ++ .../projects/kotlin/build.gradle.kts | 20 ++ .../resources/projects/kotlin/settings.gradle | 2 + .../fabricmc/language/kotlin/TestModClass.kt | 15 ++ .../kotlin/src/main/resources/fabric.mod.json | 33 +++ .../resources/projects/legacy/build.gradle | 45 ++++ .../projects/legacy/gradle.properties | 17 ++ .../resources/projects/legacy/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleMod.java | 14 ++ .../fabricmc/example/mixin/ExampleMixin.java | 15 ++ .../legacy/src/main/resources/fabric.mod.json | 36 +++ .../src/main/resources/modid.mixins.json | 14 ++ .../projects/mojangMappings/build.gradle | 92 ++++++++ .../projects/mojangMappings/gradle.properties | 17 ++ .../projects/mojangMappings/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleMod.java | 14 ++ .../src/main/resources/fabric.mod.json | 33 +++ .../projects/reproducible/build.gradle | 51 +++++ .../projects/reproducible/gradle.properties | 17 ++ .../projects/reproducible/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleMod.java | 14 ++ .../fabricmc/example/mixin/ExampleMixin.java | 15 ++ .../src/main/resources/fabric.mod.json | 36 +++ .../src/main/resources/modid.mixins.json | 14 ++ .../resources/projects/simple/build.gradle | 92 ++++++++ .../projects/simple/gradle.properties | 17 ++ .../resources/projects/simple/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleMod.java | 14 ++ .../fabricmc/example/mixin/ExampleMixin.java | 15 ++ .../simple/src/main/resources/fabric.mod.json | 36 +++ .../src/main/resources/modid.mixins.json | 14 ++ 55 files changed, 1536 insertions(+), 452 deletions(-) create mode 100644 src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy delete mode 100644 src/test/groovy/net/fabricmc/loom/BuildUtils.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/DecompileTest.groovy delete mode 100644 src/test/groovy/net/fabricmc/loom/EmptyBuildFunctionalTest.groovy delete mode 100644 src/test/groovy/net/fabricmc/loom/EmptyBuildMojangFunctionalTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/KotlinTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy delete mode 100644 src/test/groovy/net/fabricmc/loom/MixinBuildFunctionalTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy delete mode 100644 src/test/groovy/net/fabricmc/loom/SimpleBuildFunctionalTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy create mode 100644 src/test/resources/accesswidener/expected.accesswidener create mode 100644 src/test/resources/projects/accesswidener/build.gradle create mode 100644 src/test/resources/projects/accesswidener/gradle.properties create mode 100644 src/test/resources/projects/accesswidener/settings.gradle create mode 100644 src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java create mode 100644 src/test/resources/projects/accesswidener/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/accesswidener/src/main/resources/modid.accesswidener create mode 100644 src/test/resources/projects/accesswidener/src/main/resources/modid.mixins.json create mode 100644 src/test/resources/projects/kotlin/build.gradle.kts create mode 100644 src/test/resources/projects/kotlin/settings.gradle create mode 100644 src/test/resources/projects/kotlin/src/main/kotlin/net/fabricmc/language/kotlin/TestModClass.kt create mode 100644 src/test/resources/projects/kotlin/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/legacy/build.gradle create mode 100644 src/test/resources/projects/legacy/gradle.properties create mode 100644 src/test/resources/projects/legacy/settings.gradle create mode 100644 src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java create mode 100644 src/test/resources/projects/legacy/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/legacy/src/main/resources/modid.mixins.json create mode 100644 src/test/resources/projects/mojangMappings/build.gradle create mode 100644 src/test/resources/projects/mojangMappings/gradle.properties create mode 100644 src/test/resources/projects/mojangMappings/settings.gradle create mode 100644 src/test/resources/projects/mojangMappings/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/mojangMappings/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/reproducible/build.gradle create mode 100644 src/test/resources/projects/reproducible/gradle.properties create mode 100644 src/test/resources/projects/reproducible/settings.gradle create mode 100644 src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java create mode 100644 src/test/resources/projects/reproducible/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/reproducible/src/main/resources/modid.mixins.json create mode 100644 src/test/resources/projects/simple/build.gradle create mode 100644 src/test/resources/projects/simple/gradle.properties create mode 100644 src/test/resources/projects/simple/settings.gradle create mode 100644 src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/simple/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java create mode 100644 src/test/resources/projects/simple/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/simple/src/main/resources/modid.mixins.json diff --git a/.github/workflows/test-push.yml b/.github/workflows/test-push.yml index 36749b6f..05c43f99 100644 --- a/.github/workflows/test-push.yml +++ b/.github/workflows/test-push.yml @@ -1,10 +1,11 @@ name: Run Tests on: [push, pull_request] jobs: - gradle: + build: strategy: + fail-fast: false matrix: - gradle: [4.9, 4.10.2, 6.8.2] + gradle: [4.9, 4.10.2, 6.8.3] java: [jdk8, jdk11, jdk15] exclude: # Dont run older gradle versions on newer java - java: jdk15 @@ -20,18 +21,52 @@ jobs: image: gradle:${{ matrix.gradle }}-${{ matrix.java }} options: --user root steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: gradle/wrapper-validation-action@v1 - - run: gradle build check test --stacktrace + - run: gradle build check -x test --stacktrace + + # This job is used to feed the test matrix of next job to allow the tests to run in parallel + prepare_test_matrix: + # Lets wait to ensure it builds before going running tests + needs: build - gradle_pre_release: runs-on: ubuntu-20.04 container: - image: openjdk:8-jdk + image: gradle:6.8.3-jdk15 options: --user root + steps: - - uses: actions/checkout@v1 - - run: ./gradlew wrapper --gradle-version=7.0-milestone-1 - - run: ./gradlew build check test --stacktrace --warning-mode fail + - uses: actions/checkout@v2 + - run: gradle writeActionsTestMatrix --stacktrace + - + id: set-matrix + run: echo "::set-output name=matrix::$(cat build/test_matrix.json)" + + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + + run_tests: + needs: prepare_test_matrix + + strategy: + fail-fast: false + matrix: + java: [jdk8, jdk11, jdk15] + test: ${{ fromJson(needs.prepare_test_matrix.outputs.matrix) }} + + runs-on: ubuntu-20.04 + container: + image: gradle:6.8.3-${{ matrix.java }} + options: --user root + + steps: + - uses: actions/checkout@v2 + - run: gradle test --tests *${{ matrix.test }} --stacktrace env: - TEST_WARNING_MODE: fail \ No newline at end of file + TEST_WARNING_MODE: fail + + - uses: actions/upload-artifact@v2 + if: ${{ always() }} + with: + name: ${{ matrix.test }} (${{ matrix.java }}) Results + path: build/reports/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 53ed1319..0ef0a87b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ plugins { id 'eclipse' id 'groovy' id 'checkstyle' + id 'jacoco' id "org.cadixdev.licenser" version "0.5.0" } @@ -78,7 +79,6 @@ dependencies { } compileOnly 'org.jetbrains:annotations:20.1.0' - } jar { @@ -100,7 +100,9 @@ task javadocJar(type: Jar, dependsOn: javadoc) { license { header rootProject.file("HEADER") include "**/*.java" + include "**/*.groovy" exclude '**/loom/util/DownloadUtil.java' + exclude '**/projects' } checkstyle { @@ -117,6 +119,20 @@ gradlePlugin { } } +jacoco { + toolVersion = "0.8.6" +} + +// Run to get test coverage. +jacocoTestReport { + dependsOn test + reports { + xml.enabled false + csv.enabled false + html.destination file("${buildDir}/jacocoHtml") + } +} + import org.w3c.dom.Document import org.w3c.dom.Element import org.w3c.dom.Node @@ -178,4 +194,25 @@ publishing { } } } +} + +// A task to output a json file with a list of all the test to run +task writeActionsTestMatrix() { + doLast { + def testMatrix = [] + file('src/test/groovy/net/fabricmc/loom').eachFile { + if (it.name.endsWith("Test.groovy")) { + if (it.text.contains("@Ignore")) { + // A quick hack to disable currently broken tests. + return + } + + testMatrix.add(it.name.replace(".groovy", "")) + } + } + def json = groovy.json.JsonOutput.toJson(testMatrix) + def output = file("build/test_matrix.json") + output.parentFile.mkdir() + output.text = json + } } \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy new file mode 100644 index 00000000..a1449001 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy @@ -0,0 +1,56 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ArchiveAssertionsTrait +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class AccessWidenerTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { + @Override + String name() { + "accesswidener" + } + + @Unroll + def "accesswidener (gradle #gradle)"() { + when: + def result = create("build", gradle) + then: + result.task(":build").outcome == SUCCESS + getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected() + where: + gradle | _ + '6.8.3' | _ + '7.0-milestone-2' | _ + } + + String expected() { + new File("src/test/resources/accesswidener/expected.accesswidener").text + } +} diff --git a/src/test/groovy/net/fabricmc/loom/BuildUtils.groovy b/src/test/groovy/net/fabricmc/loom/BuildUtils.groovy deleted file mode 100644 index 58fe3cfd..00000000 --- a/src/test/groovy/net/fabricmc/loom/BuildUtils.groovy +++ /dev/null @@ -1,209 +0,0 @@ -package net.fabricmc.loom - -/** - * Created by Mitchell Skaggs on 6/12/2019. - */ -static String genBuildFile(String mappingsDep = "\"net.fabricmc:yarn:\${project.yarn_mappings}\"") { - """ -plugins { - id 'fabric-loom' - id 'maven-publish' -} -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 - -archivesBaseName = project.archives_base_name -version = project.mod_version -group = project.maven_group - - -minecraft { -} - -dependencies { - //to change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:\${project.minecraft_version}" - mappings ${mappingsDep} - modImplementation "net.fabricmc:fabric-loader:\${project.loader_version}" - - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:\${project.fabric_version}" - - // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. - // You may need to force-disable transitiveness on them. -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -// ensure that the encoding is set to UTF-8, no matter what the system default is -// this fixes some edge cases with special characters not displaying correctly -// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html -tasks.withType(JavaCompile) { - options.encoding = "UTF-8" -} - -// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task -// if it is present. -// If you remove this task, sources will not be generated. -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = "sources" - from sourceSets.main.allSource -} - -jar { - from "LICENSE" -} - -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - // add all the jars that should be included when publishing to maven - artifact(jar) { - builtBy remapJar - } - artifact(sourcesJar) { - builtBy remapSourcesJar - } - } - } - - // select the repositories you want to publish to - repositories { - // uncomment to publish to the local maven - // mavenLocal() - } -} -""" -} - -static String genPropsFile(String mcVersion, String yarnVersion, String loaderVersion, String fabricVersion, boolean caching = true, boolean parallel = true) { - """ -org.gradle.caching=$caching -org.gradle.parallel=$parallel - -# Fabric Properties -# check these on https://fabricmc.net/use -minecraft_version=$mcVersion -yarn_mappings=$yarnVersion -loader_version=$loaderVersion - -# Mod Properties -mod_version = 1.0.0 -maven_group = net.fabricmc -archives_base_name = fabric-example-mod - -# Dependencies -# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric -fabric_version=$fabricVersion -""" -} - -static String genSettingsFile(String name) { - """ -rootProject.name = '$name' -""" -} - -static String genModJsonFile() { - """ -{ - "schemaVersion": 1, - "id": "modid", - "version": "\${version}", - - "name": "Example Mod", - "description": "This is an example description! Tell everyone what your mod is about!", - "authors": [ - "Me!" - ], - "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" - }, - - "license": "CC0-1.0", - - "environment": "*", - "entrypoints": { - "main": [ - "net.fabricmc.example.ExampleMod" - ] - }, - "mixins": [ - "modid.mixins.json" - ], - - "depends": { - "fabricloader": ">=0.4.0", - "fabric": "*" - }, - "suggests": { - "flamingo": "*" - } -} -""" -} - -static String genModJavaFile() { - """ -package net.fabricmc.example; - -import net.fabricmc.api.ModInitializer; - -public class ExampleMod implements ModInitializer { - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - System.out.println("Hello Fabric world!"); - } -} -""" -} - -static String genModMixinsJsonFile() { - """ -{ - "required": true, - "package": "net.fabricmc.example.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - ], - "client": [ - "ExampleMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} -""" -} - -static String genModMixinsJavaFile() { - """ -package net.fabricmc.example.mixin; - -import net.minecraft.client.MinecraftClient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftClient.class) -public class ExampleMixin { - @Inject(at = @At("HEAD"), method = "init()V") - private void init(CallbackInfo info) { - System.out.println("This line is printed by an example mod mixin!"); - } -} -""" -} diff --git a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy b/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy new file mode 100644 index 00000000..b30f90a1 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy @@ -0,0 +1,54 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Ignore +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +@Ignore // TODO this fails due to the plugin classpath being setup differently. We need to explore other ways to do this. +class DecompileTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "simple" + } + + @Unroll + def "#decompiler decompile"() { + when: + def result = create(task) + + then: + result.task(":${task}").outcome == SUCCESS + + where: + decompiler | task + 'fernflower' | "genSources" + 'cfr' | "genSourcesWithExperimentalCfr" + } +} diff --git a/src/test/groovy/net/fabricmc/loom/EmptyBuildFunctionalTest.groovy b/src/test/groovy/net/fabricmc/loom/EmptyBuildFunctionalTest.groovy deleted file mode 100644 index 996ab656..00000000 --- a/src/test/groovy/net/fabricmc/loom/EmptyBuildFunctionalTest.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package net.fabricmc.loom - -import org.gradle.testkit.runner.GradleRunner -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import spock.lang.Specification -import spock.lang.Unroll - -import static net.fabricmc.loom.BuildUtils.* -import static org.gradle.testkit.runner.TaskOutcome.SUCCESS - -/** - * Created by Mitchell Skaggs on 6/10/2019. - */ -class EmptyBuildFunctionalTest extends Specification { - @Rule - TemporaryFolder testProjectDir = new TemporaryFolder() - File settingsFile - File buildFile - File propsFile - - def setup() { - settingsFile = testProjectDir.newFile('settings.gradle') - buildFile = testProjectDir.newFile('build.gradle') - propsFile = testProjectDir.newFile('gradle.properties') - } - - @Unroll - def "empty build succeeds using Minecraft #mcVersion"() { - given: - settingsFile << genSettingsFile("empty-build-functional-test") - propsFile << genPropsFile(mcVersion, yarnVersion, loaderVersion, fabricVersion) - buildFile << genBuildFile() - - when: - def result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments('build',"--stacktrace", "--warning-mode", System.getenv().TEST_WARNING_MODE ?: 'all') - .withPluginClasspath() - .forwardOutput() - .build() - - then: - result.task(":build").outcome == SUCCESS - - where: - mcVersion | yarnVersion | loaderVersion | fabricVersion - '1.14' | '1.14+build.21' | '0.4.8+build.155' | '0.3.0+build.183' - '1.16.2' | '1.16.2+build.26:v2' | '0.9.2+build.206' | '0.19.0+build.398-1.16' - } -} diff --git a/src/test/groovy/net/fabricmc/loom/EmptyBuildMojangFunctionalTest.groovy b/src/test/groovy/net/fabricmc/loom/EmptyBuildMojangFunctionalTest.groovy deleted file mode 100644 index d360ba6f..00000000 --- a/src/test/groovy/net/fabricmc/loom/EmptyBuildMojangFunctionalTest.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package net.fabricmc.loom - -import org.gradle.testkit.runner.GradleRunner -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import spock.lang.Specification -import spock.lang.Unroll - -import static net.fabricmc.loom.BuildUtils.* -import static org.gradle.testkit.runner.TaskOutcome.SUCCESS - -/** - * Created by Mitchell Skaggs on 6/10/2019. - */ -class EmptyBuildMojangFunctionalTest extends Specification { - @Rule - TemporaryFolder testProjectDir = new TemporaryFolder() - File settingsFile - File buildFile - File propsFile - - def setup() { - settingsFile = testProjectDir.newFile('settings.gradle') - buildFile = testProjectDir.newFile('build.gradle') - propsFile = testProjectDir.newFile('gradle.properties') - } - - @Unroll - def "empty build succeeds using Minecraft #mcVersion"() { - given: - settingsFile << genSettingsFile("empty-build-functional-test") - propsFile << genPropsFile(mcVersion, "nope", loaderVersion, fabricVersion) - buildFile << genBuildFile("minecraft.officialMojangMappings()") - - when: - def result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments('build',"--stacktrace", "--warning-mode", System.getenv().TEST_WARNING_MODE ?: 'all') - .withPluginClasspath() - .forwardOutput() - .build() - - then: - result.task(":build").outcome == SUCCESS - - where: - mcVersion | loaderVersion | fabricVersion - '1.16.2' | '0.9.2+build.206' | '0.19.0+build.398-1.16' - } -} diff --git a/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy b/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy new file mode 100644 index 00000000..380dffda --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy @@ -0,0 +1,50 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class KotlinTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "kotlin" + } + + @Unroll + def "kotlin build (gradle #gradle)"() { + when: + def result = create("build", gradle) + then: + result.task(":build").outcome == SUCCESS + where: + gradle | _ + '6.8.3' | _ + '7.0-milestone-2' | _ + } +} diff --git a/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy new file mode 100644 index 00000000..aac95fe8 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy @@ -0,0 +1,53 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +// This test uses gradle 4.9 and 1.14.4 v1 mappings +class LegacyProjectTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "legacy" + } + + @Unroll + def "build"() { + when: + def result = create("build", "4.9") + then: + result.task(":build").outcome == SUCCESS + } + + @Override + String warningMode() { + // Gradle 4.9 doesnt support fail, and well this is a legacy test so deprecations are expected + 'all' + } +} diff --git a/src/test/groovy/net/fabricmc/loom/MixinBuildFunctionalTest.groovy b/src/test/groovy/net/fabricmc/loom/MixinBuildFunctionalTest.groovy deleted file mode 100644 index b40a2ba7..00000000 --- a/src/test/groovy/net/fabricmc/loom/MixinBuildFunctionalTest.groovy +++ /dev/null @@ -1,69 +0,0 @@ -package net.fabricmc.loom - -import org.gradle.testkit.runner.GradleRunner -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import spock.lang.Ignore -import spock.lang.Specification -import spock.lang.Unroll - -import static net.fabricmc.loom.BuildUtils.* -import static org.gradle.testkit.runner.TaskOutcome.SUCCESS - -/** - * Created by Mitchell Skaggs on 6/10/2019. - */ -class MixinBuildFunctionalTest extends Specification { - @Rule - TemporaryFolder testProjectDir = new TemporaryFolder() - File settingsFile - File buildFile - File propsFile - File modJsonFile - File modJavaFile - File modMixinsJsonFile - File modMixinsJavaFile - - def setup() { - settingsFile = testProjectDir.newFile('settings.gradle') - buildFile = testProjectDir.newFile('build.gradle') - propsFile = testProjectDir.newFile('gradle.properties') - - testProjectDir.newFolder("src", "main", "resources") - modJsonFile = testProjectDir.newFile('src/main/resources/fabric.mod.json') - modMixinsJsonFile = testProjectDir.newFile('src/main/resources/modid.mixins.json') - - testProjectDir.newFolder("src", "main", "java", "net", "fabricmc", "example") - modJavaFile = testProjectDir.newFile("src/main/java/net/fabricmc/example/ExampleMod.java") - - testProjectDir.newFolder("src", "main", "java", "net", "fabricmc", "example", "mixin") - modMixinsJavaFile = testProjectDir.newFile("src/main/java/net/fabricmc/example/mixin/ExampleMixin.java") - } - - @Unroll - def "mixin build succeeds using Minecraft #mcVersion"() { - given: - settingsFile << genSettingsFile("mixin-build-functional-test") - propsFile << genPropsFile(mcVersion, yarnVersion, loaderVersion, fabricVersion) - buildFile << genBuildFile() - modJsonFile << genModJsonFile() - modJavaFile << genModJavaFile() - modMixinsJsonFile << genModMixinsJsonFile() - modMixinsJavaFile << genModMixinsJavaFile() - - when: - def result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments('build','--stacktrace', "--warning-mode", System.getenv().TEST_WARNING_MODE ?: 'all') - .withPluginClasspath() - .forwardOutput() - .build() - - then: - result.task(":build").outcome == SUCCESS - - where: - mcVersion | yarnVersion | loaderVersion | fabricVersion - '1.14' | '1.14+build.21' | '0.4.8+build.155' | '0.3.0+build.184' - } -} diff --git a/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy new file mode 100644 index 00000000..dd8a9808 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy @@ -0,0 +1,50 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class MojangMappingsProjectTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "mojangMappings" + } + + @Unroll + def "build (gradle #gradle)"() { + when: + def result = create("build", gradle) + then: + result.task(":build").outcome == SUCCESS + where: + gradle | _ + '6.8.3' | _ + '7.0-milestone-2' | _ + } +} diff --git a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy new file mode 100644 index 00000000..b33f8949 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy @@ -0,0 +1,70 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Ignore +import spock.lang.Specification +import spock.lang.Unroll + +import java.security.DigestInputStream +import java.security.MessageDigest + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +@Ignore //TODO this is currently failing! +class ReproducibleBuildTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "reproducible" + } + + @Unroll + def "build (gradle #gradle)"() { + when: + def result = create("build", gradle) + then: + result.task(":build").outcome == SUCCESS + getOutputHash("fabric-example-mod-1.0.0.jar") == modHash + getOutputHash("fabric-example-mod-1.0.0-sources.jar") == sourceHash + where: + gradle | modHash | sourceHash + '6.8.3' | "e1beb19574f3446800e0a5e289121365" | "123" + '7.0-milestone-2' | "9759775e1f5440a18667c41cf1961908" | "123" + } + + String getOutputHash(String name) { + generateMD5(getOutputFile(name)) + } + + String generateMD5(File file) { + file.withInputStream { + new DigestInputStream(it, MessageDigest.getInstance('MD5')).withStream { + it.eachByte {} + it.messageDigest.digest().encodeHex() as String + } + } + } +} diff --git a/src/test/groovy/net/fabricmc/loom/SimpleBuildFunctionalTest.groovy b/src/test/groovy/net/fabricmc/loom/SimpleBuildFunctionalTest.groovy deleted file mode 100644 index 756a3faa..00000000 --- a/src/test/groovy/net/fabricmc/loom/SimpleBuildFunctionalTest.groovy +++ /dev/null @@ -1,62 +0,0 @@ -package net.fabricmc.loom - -import org.gradle.testkit.runner.GradleRunner -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import spock.lang.Specification -import spock.lang.Unroll - -import static net.fabricmc.loom.BuildUtils.* -import static org.gradle.testkit.runner.TaskOutcome.SUCCESS - -/** - * Created by Mitchell Skaggs on 6/10/2019. - */ -class SimpleBuildFunctionalTest extends Specification { - @Rule - TemporaryFolder testProjectDir = new TemporaryFolder() - File settingsFile - File buildFile - File propsFile - File modJsonFile - File modExampleFile - - def setup() { - settingsFile = testProjectDir.newFile('settings.gradle') - buildFile = testProjectDir.newFile('build.gradle') - propsFile = testProjectDir.newFile('gradle.properties') - - testProjectDir.newFolder("src", "main", "resources") - modJsonFile = testProjectDir.newFile('src/main/resources/fabric.mod.json') - - testProjectDir.newFolder("src", "main", "java", "net", "fabricmc", "example") - modExampleFile = testProjectDir.newFile("src/main/java/net/fabricmc/example/ExampleMod.java") - } - - @Unroll - def "simple build succeeds using Minecraft #mcVersion"() { - given: - settingsFile << genSettingsFile("simple-build-functional-test") - propsFile << genPropsFile(mcVersion, yarnVersion, loaderVersion, fabricVersion) - buildFile << genBuildFile() - modJsonFile << genModJsonFile() - modExampleFile << genModJavaFile() - - when: - def result = GradleRunner.create() - .withProjectDir(testProjectDir.root) - .withArguments('build',"--stacktrace", "--warning-mode", System.getenv().TEST_WARNING_MODE ?: 'all') - .withPluginClasspath() - .forwardOutput() - .withDebug(true) - .build() - - then: - result.task(":build").outcome == SUCCESS - - where: - mcVersion | yarnVersion | loaderVersion | fabricVersion - '19w45a' | '19w45a+build.2:v2' | '0.6.2+build.166' | '0.4.9+build.258-1.15' - '1.14' | '1.14+build.21' | '0.4.8+build.155' | '0.3.0+build.184' - } -} diff --git a/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy new file mode 100644 index 00000000..6954b88d --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy @@ -0,0 +1,63 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class SimpleProjectTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "simple" + } + + @Unroll + def "build (gradle #gradle)"() { + when: + def result = create("build", gradle) + then: + result.task(":build").outcome == SUCCESS + where: + gradle | _ + '6.8.3' | _ + '7.0-milestone-2' | _ + } + + @Unroll + def "#ide config generation"() { + when: + def result = create(ide) + then: + result.task(":${ide}").outcome == SUCCESS + where: + ide | _ + 'idea' | _ + 'eclipse' | _ + 'vscode' | _ + } +} diff --git a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy new file mode 100644 index 00000000..4225864e --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy @@ -0,0 +1,41 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util + +import org.zeroturnaround.zip.ZipUtil + +trait ArchiveAssertionsTrait extends ProjectTestTrait { + String getArchiveEntry(String name, String entry) { + def file = getOutputFile(name) + + def bytes = ZipUtil.unpackEntry(file, entry) + + if (bytes == null) { + throw new FileNotFoundException("Could not find ${entry} in ${name}") + } + + new String(bytes as byte[]) + } +} \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy new file mode 100644 index 00000000..7dfcac50 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -0,0 +1,97 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util + +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner +import spock.lang.Shared + +trait ProjectTestTrait { + static File gradleHome = File.createTempDir() + + File testProjectDir = File.createTempDir() + + abstract String name() + + @SuppressWarnings('unused') + def setup() { + def baseProjectDir = new File("src/test/resources/projects/" + name()) + + if (!baseProjectDir.exists()) { + throw new FileNotFoundException("Failed to find project directory at:" + baseProjectDir.absolutePath) + } + + baseProjectDir.eachFileRecurse {file -> + if (file.isDirectory()) { + return + } + + def path = file.path.replace(baseProjectDir.path, "") + + File tempFile = new File(testProjectDir, path) + tempFile.parentFile.mkdirs() + tempFile << file.text + } + + // Disable the CI checks to ensure nothing is skipped + System.setProperty("fabric.loom.ci", "false") + } + + @SuppressWarnings('unused') + def cleanupSpec() { + testProjectDir.deleteDir() + gradleHome.deleteDir() + } + + BuildResult create(String task, String gradleVersion = "6.8.3") { + GradleRunner.create() + .withProjectDir(testProjectDir) + .withArguments(task, "--stacktrace", "--warning-mode", warningMode(), "--gradle-user-home", gradleHomeDirectory(gradleVersion)) + .withPluginClasspath() + .withGradleVersion(gradleVersion) + .forwardOutput() + .withDebug(true) + .build() + } + + String warningMode() { + System.getenv().TEST_WARNING_MODE ?: 'all' + } + + String gradleHomeDirectory(String gradleVersion) { + // Each gradle version gets its own dir to run on, to ensure that a full run is done. + new File(gradleHome, gradleVersion).absolutePath + } + + File getOutputFile(String name) { + def file = new File(testProjectDir, "build/libs/" + name) + + if (!file.exists()) { + throw new FileNotFoundException("Could not find ${name} at ${file.absolutePath}") + } + + return file + } +} \ No newline at end of file diff --git a/src/test/resources/accesswidener/expected.accesswidener b/src/test/resources/accesswidener/expected.accesswidener new file mode 100644 index 00000000..80c2d801 --- /dev/null +++ b/src/test/resources/accesswidener/expected.accesswidener @@ -0,0 +1,7 @@ +accessWidener v1 intermediary +accessible class net/minecraft/class_1928$class_5199 +accessible class net/minecraft/class_1928$class_4314 +extendable class net/minecraft/class_1928$class_4314 +accessible class net/minecraft/class_5235$class_5238 +accessible method net/minecraft/class_1928$class_4314 (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;Lnet/minecraft/class_1928$class_5199;)V +extendable method net/minecraft/class_1928$class_4314 (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;Lnet/minecraft/class_1928$class_5199;)V diff --git a/src/test/resources/projects/accesswidener/build.gradle b/src/test/resources/projects/accesswidener/build.gradle new file mode 100644 index 00000000..42e0b4ec --- /dev/null +++ b/src/test/resources/projects/accesswidener/build.gradle @@ -0,0 +1,96 @@ +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +loom { + accessWidener = file("src/main/resources/modid.accesswidener") +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. + // You may need to force-disable transitiveness on them. +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + // ensure that the encoding is set to UTF-8, no matter what the system default is + // this fixes some edge cases with special characters not displaying correctly + // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html + // If Javadoc is generated, this must be specified in that task too. + it.options.encoding = "UTF-8" + + // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too + // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used. + // We'll use that if it's available, but otherwise we'll use the older option. + def targetVersion = 8 + if (JavaVersion.current().isJava9Compatible()) { + it.options.release = targetVersion + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/src/test/resources/projects/accesswidener/gradle.properties b/src/test/resources/projects/accesswidener/gradle.properties new file mode 100644 index 00000000..2e85dfd8 --- /dev/null +++ b/src/test/resources/projects/accesswidener/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.5 + yarn_mappings=1.16.5+build.5 + loader_version=0.11.2 + +# Mod Properties + mod_version = 1.0.0 + maven_group = com.example + archives_base_name = fabric-example-mod + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.31.0+1.16 diff --git a/src/test/resources/projects/accesswidener/settings.gradle b/src/test/resources/projects/accesswidener/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/accesswidener/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/ExampleMod.java new file mode 100644 index 00000000..e5ed082e --- /dev/null +++ b/src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java new file mode 100644 index 00000000..83ee1a89 --- /dev/null +++ b/src/test/resources/projects/accesswidener/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java @@ -0,0 +1,15 @@ +package net.fabricmc.example.mixin; + +import net.minecraft.client.gui.screen.TitleScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public class ExampleMixin { + @Inject(at = @At("HEAD"), method = "init()V") + private void init(CallbackInfo info) { + System.out.println("This line is printed by an example mod mixin!"); + } +} diff --git a/src/test/resources/projects/accesswidener/src/main/resources/fabric.mod.json b/src/test/resources/projects/accesswidener/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..27a8bdf7 --- /dev/null +++ b/src/test/resources/projects/accesswidener/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + }, + "mixins": [ + "modid.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + }, + "accessWidener" : "modid.accesswidener" +} diff --git a/src/test/resources/projects/accesswidener/src/main/resources/modid.accesswidener b/src/test/resources/projects/accesswidener/src/main/resources/modid.accesswidener new file mode 100644 index 00000000..9f81b7f8 --- /dev/null +++ b/src/test/resources/projects/accesswidener/src/main/resources/modid.accesswidener @@ -0,0 +1,7 @@ +accessWidener v1 named + +accessible method net/minecraft/world/GameRules$Type (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;Lnet/minecraft/world/GameRules$Acceptor;)V +extendable method net/minecraft/world/GameRules$Type (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;Lnet/minecraft/world/GameRules$Acceptor;)V + +accessible class net/minecraft/world/GameRules$Acceptor +accessible class net/minecraft/client/gui/screen/world/EditGameRulesScreen$RuleWidgetFactory diff --git a/src/test/resources/projects/accesswidener/src/main/resources/modid.mixins.json b/src/test/resources/projects/accesswidener/src/main/resources/modid.mixins.json new file mode 100644 index 00000000..21fe73a4 --- /dev/null +++ b/src/test/resources/projects/accesswidener/src/main/resources/modid.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.fabricmc.example.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "ExampleMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/test/resources/projects/kotlin/build.gradle.kts b/src/test/resources/projects/kotlin/build.gradle.kts new file mode 100644 index 00000000..5330c341 --- /dev/null +++ b/src/test/resources/projects/kotlin/build.gradle.kts @@ -0,0 +1,20 @@ +import java.util.Properties + +plugins { + kotlin("jvm") version "1.4.31" + id("fabric-loom") +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +version = "0.0.1" + +dependencies { + minecraft(group = "com.mojang", name = "minecraft", version = "1.16.5") + mappings(group = "net.fabricmc", name = "yarn", version = "1.16.5+build.5", classifier = "v2") + modImplementation("net.fabricmc:fabric-loader:0.11.2") + modImplementation(group = "net.fabricmc", name = "fabric-language-kotlin", version = "1.5.0+kotlin.1.4.31") +} \ No newline at end of file diff --git a/src/test/resources/projects/kotlin/settings.gradle b/src/test/resources/projects/kotlin/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/kotlin/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/kotlin/src/main/kotlin/net/fabricmc/language/kotlin/TestModClass.kt b/src/test/resources/projects/kotlin/src/main/kotlin/net/fabricmc/language/kotlin/TestModClass.kt new file mode 100644 index 00000000..5213187f --- /dev/null +++ b/src/test/resources/projects/kotlin/src/main/kotlin/net/fabricmc/language/kotlin/TestModClass.kt @@ -0,0 +1,15 @@ +package net.fabricmc.language.kotlin + +import net.fabricmc.api.ModInitializer +import org.apache.logging.log4j.LogManager + +class TestModClass : ModInitializer { + + val logger = LogManager.getFormatterLogger("KotlinLanguageTest") + + override fun onInitialize() { + logger.info("**************************") + logger.info("Hello from Kotlin TestModClass") + logger.info("**************************") + } +} \ No newline at end of file diff --git a/src/test/resources/projects/kotlin/src/main/resources/fabric.mod.json b/src/test/resources/projects/kotlin/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..5618f96e --- /dev/null +++ b/src/test/resources/projects/kotlin/src/main/resources/fabric.mod.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.language.kotlin.TestModClass" + ] + }, + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/legacy/build.gradle b/src/test/resources/projects/legacy/build.gradle new file mode 100644 index 00000000..92e5147d --- /dev/null +++ b/src/test/resources/projects/legacy/build.gradle @@ -0,0 +1,45 @@ +plugins { + id 'fabric-loom' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +} + +processResources { + inputs.property "version", project.version + + from(sourceSets.main.resources.srcDirs) { + include "fabric.mod.json" + expand "version": project.version + } + + from(sourceSets.main.resources.srcDirs) { + exclude "fabric.mod.json" + } +} + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } +} diff --git a/src/test/resources/projects/legacy/gradle.properties b/src/test/resources/projects/legacy/gradle.properties new file mode 100644 index 00000000..440dabe5 --- /dev/null +++ b/src/test/resources/projects/legacy/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.14.4 + yarn_mappings=1.14.4+build.18 + loader_version=0.11.2 + +# Mod Properties + mod_version = 1.0.0 + maven_group = com.example + archives_base_name = fabric-example-mod + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.28.5+1.14 diff --git a/src/test/resources/projects/legacy/settings.gradle b/src/test/resources/projects/legacy/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/legacy/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/ExampleMod.java new file mode 100644 index 00000000..e5ed082e --- /dev/null +++ b/src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java new file mode 100644 index 00000000..481e10e4 --- /dev/null +++ b/src/test/resources/projects/legacy/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java @@ -0,0 +1,15 @@ +package net.fabricmc.example.mixin; + +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class ExampleMixin { + @Inject(at = @At("HEAD"), method = "init()V") + private void init(CallbackInfo info) { + System.out.println("This line is printed by an example mod mixin!"); + } +} \ No newline at end of file diff --git a/src/test/resources/projects/legacy/src/main/resources/fabric.mod.json b/src/test/resources/projects/legacy/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..9c6ccfa9 --- /dev/null +++ b/src/test/resources/projects/legacy/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + }, + "mixins": [ + "modid.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/legacy/src/main/resources/modid.mixins.json b/src/test/resources/projects/legacy/src/main/resources/modid.mixins.json new file mode 100644 index 00000000..21fe73a4 --- /dev/null +++ b/src/test/resources/projects/legacy/src/main/resources/modid.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.fabricmc.example.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "ExampleMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/test/resources/projects/mojangMappings/build.gradle b/src/test/resources/projects/mojangMappings/build.gradle new file mode 100644 index 00000000..193627e9 --- /dev/null +++ b/src/test/resources/projects/mojangMappings/build.gradle @@ -0,0 +1,92 @@ +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings loom.officialMojangMappings() + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. + // You may need to force-disable transitiveness on them. +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + // ensure that the encoding is set to UTF-8, no matter what the system default is + // this fixes some edge cases with special characters not displaying correctly + // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html + // If Javadoc is generated, this must be specified in that task too. + it.options.encoding = "UTF-8" + + // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too + // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used. + // We'll use that if it's available, but otherwise we'll use the older option. + def targetVersion = 8 + if (JavaVersion.current().isJava9Compatible()) { + it.options.release = targetVersion + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/src/test/resources/projects/mojangMappings/gradle.properties b/src/test/resources/projects/mojangMappings/gradle.properties new file mode 100644 index 00000000..2e85dfd8 --- /dev/null +++ b/src/test/resources/projects/mojangMappings/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.5 + yarn_mappings=1.16.5+build.5 + loader_version=0.11.2 + +# Mod Properties + mod_version = 1.0.0 + maven_group = com.example + archives_base_name = fabric-example-mod + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.31.0+1.16 diff --git a/src/test/resources/projects/mojangMappings/settings.gradle b/src/test/resources/projects/mojangMappings/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/mojangMappings/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/mojangMappings/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/mojangMappings/src/main/java/net/fabricmc/example/ExampleMod.java new file mode 100644 index 00000000..e5ed082e --- /dev/null +++ b/src/test/resources/projects/mojangMappings/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/mojangMappings/src/main/resources/fabric.mod.json b/src/test/resources/projects/mojangMappings/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..f8af34f7 --- /dev/null +++ b/src/test/resources/projects/mojangMappings/src/main/resources/fabric.mod.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + }, + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/reproducible/build.gradle b/src/test/resources/projects/reproducible/build.gradle new file mode 100644 index 00000000..0fb0dc6f --- /dev/null +++ b/src/test/resources/projects/reproducible/build.gradle @@ -0,0 +1,51 @@ +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" + + def targetVersion = 8 + if (JavaVersion.current().isJava9Compatible()) { + it.options.release = targetVersion + } +} + +java { + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } +} + +// Make Jars Reproducible +tasks.withType(AbstractArchiveTask) { + preserveFileTimestamps = false + reproducibleFileOrder = true +} \ No newline at end of file diff --git a/src/test/resources/projects/reproducible/gradle.properties b/src/test/resources/projects/reproducible/gradle.properties new file mode 100644 index 00000000..2e85dfd8 --- /dev/null +++ b/src/test/resources/projects/reproducible/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.5 + yarn_mappings=1.16.5+build.5 + loader_version=0.11.2 + +# Mod Properties + mod_version = 1.0.0 + maven_group = com.example + archives_base_name = fabric-example-mod + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.31.0+1.16 diff --git a/src/test/resources/projects/reproducible/settings.gradle b/src/test/resources/projects/reproducible/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/reproducible/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/ExampleMod.java new file mode 100644 index 00000000..e5ed082e --- /dev/null +++ b/src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java new file mode 100644 index 00000000..83ee1a89 --- /dev/null +++ b/src/test/resources/projects/reproducible/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java @@ -0,0 +1,15 @@ +package net.fabricmc.example.mixin; + +import net.minecraft.client.gui.screen.TitleScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public class ExampleMixin { + @Inject(at = @At("HEAD"), method = "init()V") + private void init(CallbackInfo info) { + System.out.println("This line is printed by an example mod mixin!"); + } +} diff --git a/src/test/resources/projects/reproducible/src/main/resources/fabric.mod.json b/src/test/resources/projects/reproducible/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..9c6ccfa9 --- /dev/null +++ b/src/test/resources/projects/reproducible/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + }, + "mixins": [ + "modid.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/reproducible/src/main/resources/modid.mixins.json b/src/test/resources/projects/reproducible/src/main/resources/modid.mixins.json new file mode 100644 index 00000000..21fe73a4 --- /dev/null +++ b/src/test/resources/projects/reproducible/src/main/resources/modid.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.fabricmc.example.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "ExampleMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/test/resources/projects/simple/build.gradle b/src/test/resources/projects/simple/build.gradle new file mode 100644 index 00000000..771502c4 --- /dev/null +++ b/src/test/resources/projects/simple/build.gradle @@ -0,0 +1,92 @@ +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. + // You may need to force-disable transitiveness on them. +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + // ensure that the encoding is set to UTF-8, no matter what the system default is + // this fixes some edge cases with special characters not displaying correctly + // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html + // If Javadoc is generated, this must be specified in that task too. + it.options.encoding = "UTF-8" + + // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too + // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used. + // We'll use that if it's available, but otherwise we'll use the older option. + def targetVersion = 8 + if (JavaVersion.current().isJava9Compatible()) { + it.options.release = targetVersion + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/src/test/resources/projects/simple/gradle.properties b/src/test/resources/projects/simple/gradle.properties new file mode 100644 index 00000000..2e85dfd8 --- /dev/null +++ b/src/test/resources/projects/simple/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.5 + yarn_mappings=1.16.5+build.5 + loader_version=0.11.2 + +# Mod Properties + mod_version = 1.0.0 + maven_group = com.example + archives_base_name = fabric-example-mod + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.31.0+1.16 diff --git a/src/test/resources/projects/simple/settings.gradle b/src/test/resources/projects/simple/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/simple/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java new file mode 100644 index 00000000..e5ed082e --- /dev/null +++ b/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java new file mode 100644 index 00000000..83ee1a89 --- /dev/null +++ b/src/test/resources/projects/simple/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java @@ -0,0 +1,15 @@ +package net.fabricmc.example.mixin; + +import net.minecraft.client.gui.screen.TitleScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public class ExampleMixin { + @Inject(at = @At("HEAD"), method = "init()V") + private void init(CallbackInfo info) { + System.out.println("This line is printed by an example mod mixin!"); + } +} diff --git a/src/test/resources/projects/simple/src/main/resources/fabric.mod.json b/src/test/resources/projects/simple/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..9c6ccfa9 --- /dev/null +++ b/src/test/resources/projects/simple/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + }, + "mixins": [ + "modid.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/simple/src/main/resources/modid.mixins.json b/src/test/resources/projects/simple/src/main/resources/modid.mixins.json new file mode 100644 index 00000000..21fe73a4 --- /dev/null +++ b/src/test/resources/projects/simple/src/main/resources/modid.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.fabricmc.example.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "ExampleMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} From 92efb9aa73291c09d250a234dcfd07a4ac7b3220 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 6 Mar 2021 13:18:55 +0000 Subject: [PATCH 05/24] Fix ReproducibleBuildTest --- .../loom/ReproducibleBuildTest.groovy | 20 +++++++------------ .../loom/util/ProjectTestTrait.groovy | 7 +++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy index b33f8949..3025b036 100644 --- a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy @@ -24,17 +24,15 @@ package net.fabricmc.loom +import com.google.common.hash.HashCode +import com.google.common.hash.Hashing +import com.google.common.io.Files import net.fabricmc.loom.util.ProjectTestTrait -import spock.lang.Ignore import spock.lang.Specification import spock.lang.Unroll -import java.security.DigestInputStream -import java.security.MessageDigest - import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -@Ignore //TODO this is currently failing! class ReproducibleBuildTest extends Specification implements ProjectTestTrait { @Override String name() { @@ -51,8 +49,8 @@ class ReproducibleBuildTest extends Specification implements ProjectTestTrait { getOutputHash("fabric-example-mod-1.0.0-sources.jar") == sourceHash where: gradle | modHash | sourceHash - '6.8.3' | "e1beb19574f3446800e0a5e289121365" | "123" - '7.0-milestone-2' | "9759775e1f5440a18667c41cf1961908" | "123" + '6.8.3' | "ccd6aaff1b06df01e4dd8c08625b82c9" | "8bd590dc03b7dd0de3a4a7aeb431d4e8" + '7.0-milestone-2' | "ccd6aaff1b06df01e4dd8c08625b82c9" | "8bd590dc03b7dd0de3a4a7aeb431d4e8" } String getOutputHash(String name) { @@ -60,11 +58,7 @@ class ReproducibleBuildTest extends Specification implements ProjectTestTrait { } String generateMD5(File file) { - file.withInputStream { - new DigestInputStream(it, MessageDigest.getInstance('MD5')).withStream { - it.eachByte {} - it.messageDigest.digest().encodeHex() as String - } - } + HashCode hash = Files.asByteSource(file).hash(Hashing.md5()) + return hash.asBytes().encodeHex() as String } } diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index 7dfcac50..c543ece8 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -59,6 +59,13 @@ trait ProjectTestTrait { System.setProperty("fabric.loom.ci", "false") } + @SuppressWarnings('unused') + def cleanup() { + // Clean after each test + new File(testProjectDir, "build").deleteDir() + new File(testProjectDir, ".gradle").deleteDir() + } + @SuppressWarnings('unused') def cleanupSpec() { testProjectDir.deleteDir() From 5171c9bbdec5ac2f96d81fe6f6a80941a80ac6b8 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 6 Mar 2021 14:07:37 +0000 Subject: [PATCH 06/24] Try and fix fernflower forking for the final time. Hopefully helps with #355 --- .../fernflower/AbstractFernFlowerDecompiler.java | 2 +- .../decompilers/fernflower/ForkingJavaExec.java | 12 +++--------- .../net/fabricmc/loom/DecompileTest.groovy | 16 ++++++++-------- .../net/fabricmc/loom/LegacyProjectTest.groovy | 6 ------ .../fabricmc/loom/util/ProjectTestTrait.groovy | 8 ++++++-- .../resources/projects/decompile/build.gradle | 9 +++++++++ 6 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 src/test/resources/projects/decompile/build.gradle diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java index 61dbaf07..ecc13866 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java @@ -100,7 +100,7 @@ public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler { progressGroup.started(); ExecResult result = ForkingJavaExec.javaexec( - project.getRootProject().getPlugins().hasPlugin("fabric-loom") ? project.getRootProject() : project, + project, spec -> { spec.setMain(fernFlowerExecutor().getName()); spec.jvmArgs("-Xms200m", "-Xmx3G"); diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java index 8b5f5f60..b62784fb 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java @@ -24,11 +24,10 @@ package net.fabricmc.loom.decompilers.fernflower; +import java.net.URLClassLoader; + import org.gradle.api.Action; import org.gradle.api.Project; -import org.gradle.api.artifacts.ConfigurationContainer; -import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.file.FileCollection; import org.gradle.process.ExecResult; import org.gradle.process.JavaExecSpec; @@ -40,13 +39,8 @@ import org.gradle.process.JavaExecSpec; */ public class ForkingJavaExec { public static ExecResult javaexec(Project project, Action action) { - ConfigurationContainer configurations = project.getBuildscript().getConfigurations(); - DependencyHandler handler = project.getDependencies(); - FileCollection classpath = configurations.getByName("classpath")// - .plus(configurations.detachedConfiguration(handler.localGroovy())); - return project.javaexec(spec -> { - spec.classpath(classpath); + spec.classpath((Object[]) ((URLClassLoader) ForkingJavaExec.class.getClassLoader()).getURLs()); action.execute(spec); }); } diff --git a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy b/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy index b30f90a1..c0e5ea6d 100644 --- a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy @@ -25,30 +25,30 @@ package net.fabricmc.loom import net.fabricmc.loom.util.ProjectTestTrait -import spock.lang.Ignore import spock.lang.Specification import spock.lang.Unroll import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -@Ignore // TODO this fails due to the plugin classpath being setup differently. We need to explore other ways to do this. class DecompileTest extends Specification implements ProjectTestTrait { @Override String name() { - "simple" + "decompile" } @Unroll - def "#decompiler decompile"() { + def "#decompiler gradle #gradle"() { when: - def result = create(task) + def result = create(task, gradle) then: result.task(":${task}").outcome == SUCCESS where: - decompiler | task - 'fernflower' | "genSources" - 'cfr' | "genSourcesWithExperimentalCfr" + decompiler | task | gradle + 'fernflower' | "genSources" | "6.8.3" + 'fernflower' | "genSources" | "4.9" + 'fernflower' | "genSources" | "7.0-milestone-2" + 'cfr' | "genSourcesWithExperimentalCfr" | "6.8.3" } } diff --git a/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy index aac95fe8..8d837a69 100644 --- a/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy @@ -44,10 +44,4 @@ class LegacyProjectTest extends Specification implements ProjectTestTrait { then: result.task(":build").outcome == SUCCESS } - - @Override - String warningMode() { - // Gradle 4.9 doesnt support fail, and well this is a legacy test so deprecations are expected - 'all' - } } diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index c543ece8..b47622e1 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -75,7 +75,7 @@ trait ProjectTestTrait { BuildResult create(String task, String gradleVersion = "6.8.3") { GradleRunner.create() .withProjectDir(testProjectDir) - .withArguments(task, "--stacktrace", "--warning-mode", warningMode(), "--gradle-user-home", gradleHomeDirectory(gradleVersion)) + .withArguments(task, "--stacktrace", "--warning-mode", warningMode(gradleVersion), "--gradle-user-home", gradleHomeDirectory(gradleVersion)) .withPluginClasspath() .withGradleVersion(gradleVersion) .forwardOutput() @@ -83,7 +83,11 @@ trait ProjectTestTrait { .build() } - String warningMode() { + String warningMode(String gradleVersion) { + if (gradleVersion == "4.9") { + return "all" + } + System.getenv().TEST_WARNING_MODE ?: 'all' } diff --git a/src/test/resources/projects/decompile/build.gradle b/src/test/resources/projects/decompile/build.gradle new file mode 100644 index 00000000..daa90b14 --- /dev/null +++ b/src/test/resources/projects/decompile/build.gradle @@ -0,0 +1,9 @@ +plugins { + id 'fabric-loom' +} + +dependencies { + minecraft "com.mojang:minecraft:1.16.5" + mappings "net.fabricmc:yarn:1.16.5+build.5:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.2" +} From 378b8850c651e57b6209591657e7e161f044ad8c Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 6 Mar 2021 15:57:58 +0000 Subject: [PATCH 07/24] Increase heapsize for tests --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 0ef0a87b..5664a2f4 100644 --- a/build.gradle +++ b/build.gradle @@ -133,6 +133,10 @@ jacocoTestReport { } } +test { + maxHeapSize = "4096m" +} + import org.w3c.dom.Document import org.w3c.dom.Element import org.w3c.dom.Node From d1c40827612e1b309f03ba8ef84cb634fa7a7b9a Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 6 Mar 2021 17:36:12 +0000 Subject: [PATCH 08/24] Fix tests on windows --- src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy | 2 +- src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy index a1449001..37e6cf9c 100644 --- a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy @@ -43,7 +43,7 @@ class AccessWidenerTest extends Specification implements ProjectTestTrait, Archi def result = create("build", gradle) then: result.task(":build").outcome == SUCCESS - getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected() + getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r','') where: gradle | _ '6.8.3' | _ diff --git a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy index 3025b036..cb1343ba 100644 --- a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy @@ -28,11 +28,13 @@ import com.google.common.hash.HashCode import com.google.common.hash.Hashing import com.google.common.io.Files import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.IgnoreIf import spock.lang.Specification import spock.lang.Unroll import static org.gradle.testkit.runner.TaskOutcome.SUCCESS +@IgnoreIf({ os.windows }) // Linux and mac create the same files, im unsure why windows is different. Let me know if you have any ideas? class ReproducibleBuildTest extends Specification implements ProjectTestTrait { @Override String name() { From e9c7c21ede178875e8ea86f7d6f06a53965785f4 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 6 Mar 2021 23:31:09 +0000 Subject: [PATCH 09/24] Add basic MultiProjectTest and a basic RunConfigTest This should cover most of the main things now. --- .../net/fabricmc/loom/MultiProjectTest.groovy | 66 +++++++++++++++++++ .../net/fabricmc/loom/RunConfigTest.groovy | 54 +++++++++++++++ .../loom/util/ArchiveAssertionsTrait.groovy | 9 ++- .../loom/util/ProjectTestTrait.groovy | 4 +- .../projects/multiproject/build.gradle | 63 ++++++++++++++++++ .../projects/multiproject/core/build.gradle | 1 + .../java/net/fabricmc/core/ExampleMod.java | 14 ++++ .../core/src/main/resources/fabric.mod.json | 33 ++++++++++ .../multiproject/example/build.gradle | 5 ++ .../java/net/fabricmc/example/ExampleMod.java | 14 ++++ .../fabricmc/example/mixin/ExampleMixin.java | 15 +++++ .../src/main/resources/fabric.mod.json | 36 ++++++++++ .../src/main/resources/modid.mixins.json | 14 ++++ .../projects/multiproject/gradle.properties | 17 +++++ .../projects/multiproject/settings.gradle | 4 ++ .../projects/runconfigs/build.gradle | 33 ++++++++++ .../projects/runconfigs/gradle.properties | 1 + .../projects/runconfigs/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleMod.java | 13 ++++ .../src/main/resources/fabric.mod.json | 11 ++++ 20 files changed, 405 insertions(+), 4 deletions(-) create mode 100644 src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy create mode 100644 src/test/resources/projects/multiproject/build.gradle create mode 100644 src/test/resources/projects/multiproject/core/build.gradle create mode 100644 src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/ExampleMod.java create mode 100644 src/test/resources/projects/multiproject/core/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/multiproject/example/build.gradle create mode 100644 src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java create mode 100644 src/test/resources/projects/multiproject/example/src/main/resources/fabric.mod.json create mode 100644 src/test/resources/projects/multiproject/example/src/main/resources/modid.mixins.json create mode 100644 src/test/resources/projects/multiproject/gradle.properties create mode 100644 src/test/resources/projects/multiproject/settings.gradle create mode 100644 src/test/resources/projects/runconfigs/build.gradle create mode 100644 src/test/resources/projects/runconfigs/gradle.properties create mode 100644 src/test/resources/projects/runconfigs/settings.gradle create mode 100644 src/test/resources/projects/runconfigs/src/main/java/net/fabricmc/example/ExampleMod.java create mode 100644 src/test/resources/projects/runconfigs/src/main/resources/fabric.mod.json diff --git a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy new file mode 100644 index 00000000..3716affe --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy @@ -0,0 +1,66 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ArchiveAssertionsTrait +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class MultiProjectTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { + @Override + String name() { + "multiproject" + } + + @Unroll + def "build (gradle #gradle)"() { + when: + def result = create("build", gradle) + then: + result.task(":build").outcome == SUCCESS + result.task(":core:build").outcome == SUCCESS + result.task(":example:build").outcome == SUCCESS + + result.task(":remapAllJars").outcome == SUCCESS + result.task(":remapAllSources").outcome == SUCCESS + + hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/example-1.0.0.jar") + hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/core-1.0.0.jar") + hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar") + + where: + gradle | _ + '6.8.3' | _ + '7.0-milestone-2' | _ + } + + @Override + String warningMode(String gradleVersion) { + "none" // TODO fix this! + } +} diff --git a/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy b/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy new file mode 100644 index 00000000..e76369cc --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy @@ -0,0 +1,54 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +// This test runs a mod that exits on mod init +class RunConfigTest extends Specification implements ProjectTestTrait { + @Override + String name() { + "runconfigs" + } + + @Unroll + def "#task"() { + when: + def result = create(task) + then: + result.task(":${task}").outcome == SUCCESS + where: + task | _ + 'runClient' | _ + 'runServer' | _ + 'runTestmodClient' | _ + 'runTestmodServer' | _ + 'runAutoTestServer' | _ + } +} diff --git a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy index 4225864e..88d4df11 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy @@ -27,8 +27,8 @@ package net.fabricmc.loom.util import org.zeroturnaround.zip.ZipUtil trait ArchiveAssertionsTrait extends ProjectTestTrait { - String getArchiveEntry(String name, String entry) { - def file = getOutputFile(name) + String getArchiveEntry(String name, String entry, String project = "") { + def file = getOutputFile(name, project) def bytes = ZipUtil.unpackEntry(file, entry) @@ -38,4 +38,9 @@ trait ArchiveAssertionsTrait extends ProjectTestTrait { new String(bytes as byte[]) } + + boolean hasArchiveEntry(String name, String entry, String project = "") { + def file = getOutputFile(name, project) + ZipUtil.unpackEntry(file, entry) != null + } } \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index b47622e1..7530ff15 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -96,8 +96,8 @@ trait ProjectTestTrait { new File(gradleHome, gradleVersion).absolutePath } - File getOutputFile(String name) { - def file = new File(testProjectDir, "build/libs/" + name) + File getOutputFile(String name, String project = "") { + def file = new File(testProjectDir, "${project}build/libs/${name}") if (!file.exists()) { throw new FileNotFoundException("Could not find ${name} at ${file.absolutePath}") diff --git a/src/test/resources/projects/multiproject/build.gradle b/src/test/resources/projects/multiproject/build.gradle new file mode 100644 index 00000000..46fab3ed --- /dev/null +++ b/src/test/resources/projects/multiproject/build.gradle @@ -0,0 +1,63 @@ +plugins { + id "java" + id "java-library" + id 'fabric-loom' apply false +} + +allprojects { + apply plugin: "fabric-loom" + + version = "1.0.0" + + tasks.withType(JavaCompile).configureEach { + def targetVersion = 8 + if (JavaVersion.current().isJava9Compatible()) { + it.options.release = targetVersion + } else { + sourceCompatibility = JavaVersion.toVersion(targetVersion) + targetCompatibility = JavaVersion.toVersion(targetVersion) + } + + it.options.encoding = "UTF-8" + } + + dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:1.16.5" + mappings "net.fabricmc:yarn:1.16.5+build.5:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.2" + + modImplementation "net.fabricmc.fabric-api:fabric-api:0.31.0+1.16" + + } + + configurations { + dev + } + + jar { + archiveClassifier.set "dev" + } + + loom { + shareCaches = true + } + + java { + withSourcesJar() + } + +} + +dependencies { + afterEvaluate { + subprojects.each { + include project("${it.name}:") + } + } + + include fabricApi.module("fabric-api-base", "0.31.0+1.16") +} + +archivesBaseName = "multiproject" +version = "1.0.0" \ No newline at end of file diff --git a/src/test/resources/projects/multiproject/core/build.gradle b/src/test/resources/projects/multiproject/core/build.gradle new file mode 100644 index 00000000..8a09f64b --- /dev/null +++ b/src/test/resources/projects/multiproject/core/build.gradle @@ -0,0 +1 @@ +archivesBaseName = "core" \ No newline at end of file diff --git a/src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/ExampleMod.java b/src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/ExampleMod.java new file mode 100644 index 00000000..7090d282 --- /dev/null +++ b/src/test/resources/projects/multiproject/core/src/main/java/net/fabricmc/core/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.core; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} 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 new file mode 100644 index 00000000..66e9ea9e --- /dev/null +++ b/src/test/resources/projects/multiproject/core/src/main/resources/fabric.mod.json @@ -0,0 +1,33 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.core.ExampleMod" + ] + }, + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/multiproject/example/build.gradle b/src/test/resources/projects/multiproject/example/build.gradle new file mode 100644 index 00000000..c40184a8 --- /dev/null +++ b/src/test/resources/projects/multiproject/example/build.gradle @@ -0,0 +1,5 @@ +archivesBaseName = "example" + +dependencies { + implementation project(path: ":core", configuration: "dev") +} \ No newline at end of file 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 new file mode 100644 index 00000000..e5ed082e --- /dev/null +++ b/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,14 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java new file mode 100644 index 00000000..83ee1a89 --- /dev/null +++ b/src/test/resources/projects/multiproject/example/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java @@ -0,0 +1,15 @@ +package net.fabricmc.example.mixin; + +import net.minecraft.client.gui.screen.TitleScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public class ExampleMixin { + @Inject(at = @At("HEAD"), method = "init()V") + private void init(CallbackInfo info) { + System.out.println("This line is printed by an example mod mixin!"); + } +} diff --git a/src/test/resources/projects/multiproject/example/src/main/resources/fabric.mod.json b/src/test/resources/projects/multiproject/example/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..9c6ccfa9 --- /dev/null +++ b/src/test/resources/projects/multiproject/example/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "${version}", + + "name": "Example Mod", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "CC0-1.0", + + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + }, + "mixins": [ + "modid.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/src/test/resources/projects/multiproject/example/src/main/resources/modid.mixins.json b/src/test/resources/projects/multiproject/example/src/main/resources/modid.mixins.json new file mode 100644 index 00000000..21fe73a4 --- /dev/null +++ b/src/test/resources/projects/multiproject/example/src/main/resources/modid.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.fabricmc.example.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "ExampleMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/test/resources/projects/multiproject/gradle.properties b/src/test/resources/projects/multiproject/gradle.properties new file mode 100644 index 00000000..2e85dfd8 --- /dev/null +++ b/src/test/resources/projects/multiproject/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.5 + yarn_mappings=1.16.5+build.5 + loader_version=0.11.2 + +# Mod Properties + mod_version = 1.0.0 + maven_group = com.example + archives_base_name = fabric-example-mod + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.31.0+1.16 diff --git a/src/test/resources/projects/multiproject/settings.gradle b/src/test/resources/projects/multiproject/settings.gradle new file mode 100644 index 00000000..df4ff932 --- /dev/null +++ b/src/test/resources/projects/multiproject/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = "fabric-example-mod" + +include 'core' +include 'example' \ No newline at end of file diff --git a/src/test/resources/projects/runconfigs/build.gradle b/src/test/resources/projects/runconfigs/build.gradle new file mode 100644 index 00000000..dbdd21e5 --- /dev/null +++ b/src/test/resources/projects/runconfigs/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'fabric-loom' +} + +loom { + runs { + testmodClient { + client() + ideConfigGenerated project.rootProject == project + name = "Testmod Client" + source sourceSets.main + } + testmodServer { + server() + ideConfigGenerated project.rootProject == project + name = "Testmod Server" + source sourceSets.main + } + autoTestServer { + inherit testmodServer + vmArg "-Dfabric.autoTest" + } + } +} + +archivesBaseName = "fabric-example-mod" +version = "1.0.0" + +dependencies { + minecraft "com.mojang:minecraft:1.16.5" + mappings "net.fabricmc:yarn:1.16.5+build.5:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.2" +} \ No newline at end of file diff --git a/src/test/resources/projects/runconfigs/gradle.properties b/src/test/resources/projects/runconfigs/gradle.properties new file mode 100644 index 00000000..7d28631b --- /dev/null +++ b/src/test/resources/projects/runconfigs/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1G \ No newline at end of file diff --git a/src/test/resources/projects/runconfigs/settings.gradle b/src/test/resources/projects/runconfigs/settings.gradle new file mode 100644 index 00000000..c162c363 --- /dev/null +++ b/src/test/resources/projects/runconfigs/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/runconfigs/src/main/java/net/fabricmc/example/ExampleMod.java b/src/test/resources/projects/runconfigs/src/main/java/net/fabricmc/example/ExampleMod.java new file mode 100644 index 00000000..21928e56 --- /dev/null +++ b/src/test/resources/projects/runconfigs/src/main/java/net/fabricmc/example/ExampleMod.java @@ -0,0 +1,13 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + System.out.println("Hello Fabric world!"); + + // Quit now, we dont need to load the whole game to know the run configs are works + System.exit(0); + } +} diff --git a/src/test/resources/projects/runconfigs/src/main/resources/fabric.mod.json b/src/test/resources/projects/runconfigs/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..58bdf984 --- /dev/null +++ b/src/test/resources/projects/runconfigs/src/main/resources/fabric.mod.json @@ -0,0 +1,11 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "1.0.0", + "environment": "*", + "entrypoints": { + "main": [ + "net.fabricmc.example.ExampleMod" + ] + } +} From 7231b9e053a91e584d5a41591347fe8e2082913f Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Fri, 12 Mar 2021 22:16:24 +0000 Subject: [PATCH 10/24] Mod Remapping Refactor. (#362) Improved gradle 7 support General cleanup --- .../loom/build/nesting/JarNester.java | 95 ++++++++ .../nesting/MergedNestedJarProvider.java | 46 ++++ .../NestedDependencyProvider.java} | 214 ++++++++---------- .../build/nesting/NestedJarPathProvider.java | 67 ++++++ .../loom/build/nesting/NestedJarProvider.java | 40 ++++ .../configuration/CompileConfiguration.java | 159 ++----------- .../configuration/MavenConfiguration.java | 57 +++++ .../configuration/RemapConfiguration.java | 159 +++++++++++++ .../net/fabricmc/loom/task/RemapJarTask.java | 153 ++++++------- .../java/net/fabricmc/loom/util/ModUtils.java | 42 ++++ .../net/fabricmc/loom/MultiProjectTest.groovy | 5 - .../loom/util/ProjectTestTrait.groovy | 2 +- .../src/main/resources/fabric.mod.json | 6 + 13 files changed, 689 insertions(+), 356 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/build/nesting/JarNester.java create mode 100644 src/main/java/net/fabricmc/loom/build/nesting/MergedNestedJarProvider.java rename src/main/java/net/fabricmc/loom/build/{NestedJars.java => nesting/NestedDependencyProvider.java} (66%) create mode 100644 src/main/java/net/fabricmc/loom/build/nesting/NestedJarPathProvider.java create mode 100644 src/main/java/net/fabricmc/loom/build/nesting/NestedJarProvider.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/MavenConfiguration.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java create mode 100644 src/main/java/net/fabricmc/loom/util/ModUtils.java create mode 100644 src/test/resources/projects/multiproject/src/main/resources/fabric.mod.json diff --git a/src/main/java/net/fabricmc/loom/build/nesting/JarNester.java b/src/main/java/net/fabricmc/loom/build/nesting/JarNester.java new file mode 100644 index 00000000..6330b612 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/build/nesting/JarNester.java @@ -0,0 +1,95 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.build.nesting; + +import java.io.File; +import java.util.Collection; +import java.util.zip.ZipEntry; + +import com.google.common.base.Preconditions; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.gradle.api.logging.Logger; +import org.zeroturnaround.zip.FileSource; +import org.zeroturnaround.zip.ZipEntrySource; +import org.zeroturnaround.zip.ZipUtil; +import org.zeroturnaround.zip.transform.StringZipEntryTransformer; +import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; + +import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.util.ModUtils; + +public class JarNester { + public static void nestJars(Collection jars, File modJar, Logger logger) { + if (jars.isEmpty()) { + logger.debug("Nothing to nest into " + modJar.getName()); + return; + } + + Preconditions.checkArgument(ModUtils.isMod(modJar), "Cannot nest jars into none mod jar " + modJar.getName()); + + ZipUtil.addEntries(modJar, jars.stream().map(file -> new FileSource("META-INF/jars/" + file.getName(), file)).toArray(ZipEntrySource[]::new)); + + boolean didNest = ZipUtil.transformEntries(modJar, single(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { + @Override + protected String transform(ZipEntry zipEntry, String input) { + JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class); + JsonArray nestedJars = json.getAsJsonArray("jars"); + + if (nestedJars == null || !json.has("jars")) { + nestedJars = new JsonArray(); + } + + for (File file : jars) { + String nestedJarPath = "META-INF/jars/" + file.getName(); + + for (JsonElement nestedJar : nestedJars) { + JsonObject jsonObject = nestedJar.getAsJsonObject(); + + if (jsonObject.has("file") && jsonObject.get("file").getAsString().equals(nestedJarPath)) { + throw new IllegalStateException("Cannot nest 2 jars at the same path: " + nestedJarPath); + } + } + + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("file", nestedJarPath); + nestedJars.add(jsonObject); + + logger.debug("Nested " + nestedJarPath + " into " + modJar.getName()); + } + + json.add("jars", nestedJars); + + return LoomGradlePlugin.GSON.toJson(json); + } + }))); + Preconditions.checkArgument(didNest, "Failed to nest jars into " + modJar.getName()); + } + + private static ZipEntryTransformerEntry[] single(ZipEntryTransformerEntry element) { + return new ZipEntryTransformerEntry[]{element}; + } +} diff --git a/src/main/java/net/fabricmc/loom/build/nesting/MergedNestedJarProvider.java b/src/main/java/net/fabricmc/loom/build/nesting/MergedNestedJarProvider.java new file mode 100644 index 00000000..566002d4 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/build/nesting/MergedNestedJarProvider.java @@ -0,0 +1,46 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.build.nesting; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.stream.Collectors; + +public class MergedNestedJarProvider implements NestedJarProvider { + private final NestedJarProvider[] parents; + + public MergedNestedJarProvider(NestedJarProvider... parents) { + this.parents = parents; + } + + @Override + public Collection provide() { + return Arrays.stream(parents) + .map(NestedJarProvider::provide) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/net/fabricmc/loom/build/NestedJars.java b/src/main/java/net/fabricmc/loom/build/nesting/NestedDependencyProvider.java similarity index 66% rename from src/main/java/net/fabricmc/loom/build/NestedJars.java rename to src/main/java/net/fabricmc/loom/build/nesting/NestedDependencyProvider.java index c88c4487..dbca51ed 100644 --- a/src/main/java/net/fabricmc/loom/build/NestedJars.java +++ b/src/main/java/net/fabricmc/loom/build/nesting/NestedDependencyProvider.java @@ -22,22 +22,18 @@ * SOFTWARE. */ -package net.fabricmc.loom.build; +package net.fabricmc.loom.build.nesting; import java.io.File; import java.io.IOException; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import org.apache.commons.io.FileUtils; import org.gradle.api.Project; @@ -50,121 +46,30 @@ import org.gradle.api.artifacts.ResolvedArtifact; import org.gradle.api.artifacts.ResolvedConfiguration; import org.gradle.api.artifacts.ResolvedDependency; import org.gradle.api.tasks.bundling.AbstractArchiveTask; -import org.zeroturnaround.zip.FileSource; -import org.zeroturnaround.zip.ZipEntrySource; import org.zeroturnaround.zip.ZipUtil; -import org.zeroturnaround.zip.transform.StringZipEntryTransformer; -import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.task.RemapJarTask; import net.fabricmc.loom.util.Constants; -public class NestedJars { - public static boolean addNestedJars(Project project, Path modJarPath) { - List containedJars = getContainedJars(project); +public final class NestedDependencyProvider implements NestedJarProvider { + final Project project; + final List> files; - if (containedJars.isEmpty()) { - return false; - } - - File modJar = modJarPath.toFile(); - - ZipUtil.addOrReplaceEntries(modJar, containedJars.stream().map(file -> new FileSource("META-INF/jars/" + file.getName(), file)).toArray(ZipEntrySource[]::new)); - - return ZipUtil.transformEntries(modJar, single(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { - @Override - protected String transform(ZipEntry zipEntry, String input) { - JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class); - JsonArray nestedJars = json.getAsJsonArray("jars"); - - if (nestedJars == null || !json.has("jars")) { - nestedJars = new JsonArray(); - } - - for (File file : containedJars) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("file", "META-INF/jars/" + file.getName()); - nestedJars.add(jsonObject); - } - - json.add("jars", nestedJars); - - return LoomGradlePlugin.GSON.toJson(json); - } - }))); + private NestedDependencyProvider(Project project, List> files) { + this.project = project; + this.files = files; } - private static List getContainedJars(Project project) { - List fileList = new ArrayList<>(); + public static NestedDependencyProvider createNestedDependencyProviderFromConfiguration(Project project, Configuration configuration) { + List> fileList = new ArrayList<>(); + Set visited = new HashSet<>(); - Configuration configuration = project.getConfigurations().getByName(Constants.Configurations.INCLUDE); - ResolvedConfiguration resolvedConfiguration = configuration.getResolvedConfiguration(); - Set dependencies = resolvedConfiguration.getFirstLevelModuleDependencies(); + fileList.addAll(populateProjectDependencies(configuration, visited)); + fileList.addAll(populateResolvedDependencies(configuration, visited)); - // Bit ugly doing this, id guess there is a better way but this works. - Set projectDeps = new HashSet<>(); - - for (Dependency dependency : configuration.getDependencies()) { - if (dependency instanceof ProjectDependency) { - ProjectDependency projectDependency = (ProjectDependency) dependency; - Project dependencyProject = projectDependency.getDependencyProject(); - - projectDeps.add(dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion()); - - // TODO change this to allow just normal jar tasks, so a project can have a none loom sub project - Collection remapJarTasks = dependencyProject.getTasksByName("remapJar", false); - Collection jarTasks = dependencyProject.getTasksByName("jar", false); - - for (Task task : remapJarTasks.isEmpty() ? jarTasks : remapJarTasks) { - if (task instanceof RemapJarTask) { - fileList.addAll(prepareForNesting( - Collections.singleton(((RemapJarTask) task).getArchivePath()), - projectDependency, - new ProjectDependencyMetaExtractor(), - project - )); - } else if (task instanceof AbstractArchiveTask) { - fileList.addAll(prepareForNesting( - Collections.singleton(((AbstractArchiveTask) task).getArchivePath()), - projectDependency, - new ProjectDependencyMetaExtractor(), - project - )); - } - } - } - } - - for (ResolvedDependency dependency : dependencies) { - if (projectDeps.contains(dependency.getModuleGroup() + ":" + dependency.getModuleName() + ":" + dependency.getModuleVersion())) { - continue; - } else { - fileList.addAll(prepareForNesting( - dependency - .getModuleArtifacts() - .stream() - .map(ResolvedArtifact::getFile) - .collect(Collectors.toSet()), - dependency, - new ResolvedDependencyMetaExtractor(), - project - )); - } - } - - for (File file : fileList) { - if (!file.exists()) { - throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath()); - } - - if (file.isDirectory() || !file.getName().endsWith(".jar")) { - throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath()); - } - } - - return fileList; + return new NestedDependencyProvider(project, fileList); } // Looks for any deps that require a sub project to be built first @@ -190,11 +95,69 @@ public class NestedJars { return remapTasks; } - //This is a good place to do pre-nesting operations, such as adding a fabric.mod.json to a library - private static List prepareForNesting(Set files, D dependency, DependencyMetaExtractor metaExtractor, Project project) { + private static List> populateProjectDependencies(Configuration configuration, Set visited) { + List> fileList = new ArrayList<>(); + + for (Dependency dependency : configuration.getDependencies()) { + if (dependency instanceof ProjectDependency) { + ProjectDependency projectDependency = (ProjectDependency) dependency; + Project dependencyProject = projectDependency.getDependencyProject(); + + visited.add(dependency.getGroup() + ":" + dependency.getName() + ":" + dependency.getVersion()); + + // TODO change this to allow just normal jar tasks, so a project can have a none loom sub project + Collection remapJarTasks = dependencyProject.getTasksByName("remapJar", false); + Collection jarTasks = dependencyProject.getTasksByName("jar", false); + + for (Task task : remapJarTasks.isEmpty() ? jarTasks : remapJarTasks) { + if (task instanceof RemapJarTask) { + File file = ((RemapJarTask) task).getArchivePath(); + fileList.add(new DependencyInfo<>(projectDependency, new ProjectDependencyMetaExtractor(), file)); + } else if (task instanceof AbstractArchiveTask) { + File file = ((AbstractArchiveTask) task).getArchivePath(); + fileList.add(new DependencyInfo<>(projectDependency, new ProjectDependencyMetaExtractor(), file)); + } + } + } + } + + return fileList; + } + + private static List> populateResolvedDependencies(Configuration configuration, Set visited) { + ResolvedConfiguration resolvedConfiguration = configuration.getResolvedConfiguration(); + Set dependencies = resolvedConfiguration.getFirstLevelModuleDependencies(); + + List> fileList = new ArrayList<>(); + + for (ResolvedDependency dependency : dependencies) { + if (visited.contains(dependency.getModuleGroup() + ":" + dependency.getModuleName() + ":" + dependency.getModuleVersion())) { + continue; + } + + List files = dependency + .getModuleArtifacts() + .stream() + .map(ResolvedArtifact::getFile) + .collect(Collectors.toList()); + + for (File file : files) { + fileList.add(new DependencyInfo<>(dependency, new ResolvedDependencyMetaExtractor(), file)); + } + } + + return fileList; + } + + @Override + public List provide() { List fileList = new ArrayList<>(); - for (File file : files) { + for (DependencyInfo metaFile : files) { + metaFile.validateInputs(); + + File file = metaFile.file; + //A lib that doesnt have a mod.json, we turn it into a fake mod if (!ZipUtil.containsEntry(file, "fabric.mod.json")) { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); @@ -216,7 +179,7 @@ public class NestedJars { throw new RuntimeException("Failed to copy file", e); } - ZipUtil.addEntry(tempFile, "fabric.mod.json", getMod(dependency, metaExtractor).getBytes()); + ZipUtil.addEntry(tempFile, "fabric.mod.json", generateModForDependency(metaFile).getBytes()); fileList.add(tempFile); } else { // Default copy the jar right in @@ -228,7 +191,10 @@ public class NestedJars { } // Generates a barebones mod for a dependency - private static String getMod(D dependency, DependencyMetaExtractor metaExtractor) { + private static String generateModForDependency(DependencyInfo info) { + DependencyMetaExtractor metaExtractor = info.metaExtractor; + D dependency = info.dependency; + JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("schemaVersion", 1); jsonObject.addProperty("id", (metaExtractor.group(dependency) + "_" + metaExtractor.name(dependency)).replaceAll("\\.", "_").toLowerCase(Locale.ENGLISH)); @@ -242,8 +208,26 @@ public class NestedJars { return LoomGradlePlugin.GSON.toJson(jsonObject); } - private static ZipEntryTransformerEntry[] single(ZipEntryTransformerEntry element) { - return new ZipEntryTransformerEntry[]{element}; + private static class DependencyInfo { + final D dependency; + final DependencyMetaExtractor metaExtractor; + final File file; + + DependencyInfo(D dependency, DependencyMetaExtractor metaExtractor, File file) { + this.dependency = dependency; + this.metaExtractor = metaExtractor; + this.file = file; + } + + public void validateInputs() { + if (!file.exists()) { + throw new RuntimeException("Failed to include nested jars, as it could not be found @ " + file.getAbsolutePath()); + } + + if (file.isDirectory() || !file.getName().endsWith(".jar")) { + throw new RuntimeException("Failed to include nested jars, as file was not a jar: " + file.getAbsolutePath()); + } + } } private interface DependencyMetaExtractor { diff --git a/src/main/java/net/fabricmc/loom/build/nesting/NestedJarPathProvider.java b/src/main/java/net/fabricmc/loom/build/nesting/NestedJarPathProvider.java new file mode 100644 index 00000000..badb2656 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/build/nesting/NestedJarPathProvider.java @@ -0,0 +1,67 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.build.nesting; + +import java.io.File; +import java.util.Collection; +import java.util.Set; + +import com.google.common.base.Preconditions; +import org.gradle.api.Project; + +import net.fabricmc.loom.util.ModUtils; + +public final class NestedJarPathProvider implements NestedJarProvider { + private final Set nestedPaths; + private Set files = null; + public NestedJarPathProvider(Set nestedPaths) { + this.nestedPaths = nestedPaths; + } + + private Set resolve(Project project) { + return project.files(nestedPaths).getFiles(); + } + + @Override + public void prepare(Project project) { + if (files == null) { + files = resolve(project); + } + } + + @Override + public Collection provide() { + validateFiles(); + return files; + } + + private void validateFiles() { + for (File file : files) { + Preconditions.checkArgument(file.getName().endsWith(".jar"), String.format("Tried to nest %s but it is not a jar", file.getAbsolutePath())); + Preconditions.checkArgument(file.exists(), String.format("Tried to nest jar %s but it does not exist", file.getAbsolutePath())); + Preconditions.checkArgument(ModUtils.isMod(file), String.format("Cannot use nest none mod jar %s", file.getAbsolutePath())); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/build/nesting/NestedJarProvider.java b/src/main/java/net/fabricmc/loom/build/nesting/NestedJarProvider.java new file mode 100644 index 00000000..3ddbae31 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/build/nesting/NestedJarProvider.java @@ -0,0 +1,40 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.build.nesting; + +import java.io.File; +import java.util.Collection; + +import org.gradle.api.Project; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +public interface NestedJarProvider { + // provide all the files to be included, they should already be resolved but can be transformed here + Collection provide(); + + // Setup the files ready to be provided + default void prepare(Project project) { } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 4fd1a0ad..e6e7787e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -24,13 +24,8 @@ package net.fabricmc.loom.configuration; -import java.io.IOException; - import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.UnknownTaskException; import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSet; @@ -38,8 +33,6 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask; import org.gradle.api.tasks.javadoc.Javadoc; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.build.JarRemapper; -import net.fabricmc.loom.build.NestedJars; import net.fabricmc.loom.build.mixin.JavaApInvoker; import net.fabricmc.loom.build.mixin.KaptApInvoker; import net.fabricmc.loom.build.mixin.ScalaApInvoker; @@ -47,16 +40,8 @@ import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs; import net.fabricmc.loom.configuration.providers.LaunchProvider; import net.fabricmc.loom.configuration.providers.MinecraftProvider; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; -import net.fabricmc.loom.task.AbstractLoomTask; -import net.fabricmc.loom.task.RemapAllSourcesTask; -import net.fabricmc.loom.task.RemapJarTask; -import net.fabricmc.loom.task.RemapSourcesJarTask; import net.fabricmc.loom.util.Constants; -import net.fabricmc.loom.util.SourceRemapper; -/** - * Add Minecraft dependencies to compile time. - */ public final class CompileConfiguration { private CompileConfiguration() { } @@ -110,53 +95,18 @@ public final class CompileConfiguration { extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project); } - /** - * Permit to add a Maven repository to a target project. - * - * @param target The target project - * @param name The name of the repository - * @param url The URL of the repository - * @return An object containing the name and the URL of the repository that can be modified later - */ - public static MavenArtifactRepository addMavenRepo(Project target, final String name, final String url) { - return target.getRepositories().maven(repo -> { - repo.setName(name); - repo.setUrl(url); - }); - } - - public static void configureCompile(Project project) { - JavaPluginConvention javaModule = (JavaPluginConvention) project.getConvention().getPlugins().get("java"); + public static void configureCompile(Project p) { + JavaPluginConvention javaModule = (JavaPluginConvention) p.getConvention().getPlugins().get("java"); SourceSet main = javaModule.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); - Javadoc javadoc = (Javadoc) project.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); + Javadoc javadoc = (Javadoc) p.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); - project.afterEvaluate(project1 -> { - LoomGradleExtension extension = project1.getExtensions().getByType(LoomGradleExtension.class); + p.afterEvaluate(project -> { + LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - project1.getRepositories().flatDir(flatDirectoryArtifactRepository -> { - flatDirectoryArtifactRepository.dir(extension.getRootProjectBuildCache()); - flatDirectoryArtifactRepository.setName("UserLocalCacheFiles"); - }); - - project1.getRepositories().maven(mavenArtifactRepository -> { - mavenArtifactRepository.setUrl(extension.getRemappedModCache()); - mavenArtifactRepository.setName("UserLocalRemappedMods"); - }); - - project1.getRepositories().maven(mavenArtifactRepository -> { - mavenArtifactRepository.setName("Fabric"); - mavenArtifactRepository.setUrl("https://maven.fabricmc.net/"); - }); - - project1.getRepositories().maven(mavenArtifactRepository -> { - mavenArtifactRepository.setName("Mojang"); - mavenArtifactRepository.setUrl("https://libraries.minecraft.net/"); - }); - - project1.getRepositories().mavenCentral(); + MavenConfiguration.setup(project); LoomDependencyManager dependencyManager = new LoomDependencyManager(); extension.setDependencyManager(dependencyManager); @@ -165,100 +115,19 @@ public final class CompileConfiguration { dependencyManager.addProvider(new MappingsProvider(project)); dependencyManager.addProvider(new LaunchProvider(project)); - dependencyManager.handleDependencies(project1); + dependencyManager.handleDependencies(project); - project1.getTasks().getByName("idea").finalizedBy(project1.getTasks().getByName("genIdeaWorkspace")); - project1.getTasks().getByName("eclipse").finalizedBy(project1.getTasks().getByName("genEclipseRuns")); - project1.getTasks().getByName("cleanEclipse").finalizedBy(project1.getTasks().getByName("cleanEclipseRuns")); + project.getTasks().getByName("idea").finalizedBy(project.getTasks().getByName("genIdeaWorkspace")); + project.getTasks().getByName("eclipse").finalizedBy(project.getTasks().getByName("genEclipseRuns")); + project.getTasks().getByName("cleanEclipse").finalizedBy(project.getTasks().getByName("cleanEclipseRuns")); - SetupIntelijRunConfigs.setup(project1); + SetupIntelijRunConfigs.setup(project); // Enables the default mod remapper if (extension.remapMod) { - AbstractArchiveTask jarTask = (AbstractArchiveTask) project1.getTasks().getByName("jar"); - RemapJarTask remapJarTask = (RemapJarTask) project1.getTasks().findByName("remapJar"); - - assert remapJarTask != null; - - if (!remapJarTask.getInput().isPresent()) { - jarTask.setClassifier("dev"); - remapJarTask.setClassifier(""); - remapJarTask.getInput().set(jarTask.getArchivePath()); - } - - extension.getUnmappedModCollection().from(jarTask); - remapJarTask.getAddNestedDependencies().set(true); - remapJarTask.getRemapAccessWidener().set(true); - - project1.getArtifacts().add("archives", remapJarTask); - remapJarTask.dependsOn(jarTask); - project1.getTasks().getByName("build").dependsOn(remapJarTask); - - project.getTasks().withType(RemapJarTask.class).forEach(task -> { - if (task.getAddNestedDependencies().getOrElse(false)) { - NestedJars.getRequiredTasks(project1).forEach(task::dependsOn); - } - }); - - SourceRemapper remapper = null; - Task parentTask = project1.getTasks().getByName("build"); - - if (extension.isShareCaches()) { - Project rootProject = project.getRootProject(); - - if (extension.isRootProject()) { - SourceRemapper sourceRemapper = new SourceRemapper(rootProject, false); - JarRemapper jarRemapper = new JarRemapper(); - - remapJarTask.jarRemapper = jarRemapper; - - rootProject.getTasks().register("remapAllSources", RemapAllSourcesTask.class, task -> { - task.sourceRemapper = sourceRemapper; - task.doLast(t -> sourceRemapper.remapAll()); - }); - - parentTask = rootProject.getTasks().getByName("remapAllSources"); - - rootProject.getTasks().register("remapAllJars", AbstractLoomTask.class, task -> { - task.doLast(t -> { - try { - jarRemapper.remap(); - } catch (IOException e) { - throw new RuntimeException("Failed to remap jars", e); - } - }); - }); - } else { - parentTask = rootProject.getTasks().getByName("remapAllSources"); - remapper = ((RemapAllSourcesTask) parentTask).sourceRemapper; - - remapJarTask.jarRemapper = ((RemapJarTask) rootProject.getTasks().getByName("remapJar")).jarRemapper; - - project1.getTasks().getByName("build").dependsOn(parentTask); - project1.getTasks().getByName("build").dependsOn(rootProject.getTasks().getByName("remapAllJars")); - rootProject.getTasks().getByName("remapAllJars").dependsOn(project1.getTasks().getByName("remapJar")); - } - } - - try { - AbstractArchiveTask sourcesTask = (AbstractArchiveTask) project1.getTasks().getByName("sourcesJar"); - - RemapSourcesJarTask remapSourcesJarTask = (RemapSourcesJarTask) project1.getTasks().findByName("remapSourcesJar"); - remapSourcesJarTask.setInput(sourcesTask.getArchivePath()); - remapSourcesJarTask.setOutput(sourcesTask.getArchivePath()); - remapSourcesJarTask.doLast(task -> project1.getArtifacts().add("archives", remapSourcesJarTask.getOutput())); - remapSourcesJarTask.dependsOn(project1.getTasks().getByName("sourcesJar")); - - if (extension.isShareCaches()) { - remapSourcesJarTask.setSourceRemapper(remapper); - } - - parentTask.dependsOn(remapSourcesJarTask); - } catch (UnknownTaskException ignored) { - // pass - } + RemapConfiguration.setupDefaultRemap(project); } else { - AbstractArchiveTask jarTask = (AbstractArchiveTask) project1.getTasks().getByName("jar"); + AbstractArchiveTask jarTask = (AbstractArchiveTask) project.getTasks().getByName("jar"); extension.getUnmappedModCollection().from(jarTask); } @@ -281,7 +150,7 @@ public final class CompileConfiguration { } }); - if (project.getPluginManager().hasPlugin("org.jetbrains.kotlin.kapt")) { + if (p.getPluginManager().hasPlugin("org.jetbrains.kotlin.kapt")) { // If loom is applied after kapt, then kapt will use the AP arguments too early for loom to pass the arguments we need for mixin. throw new IllegalArgumentException("fabric-loom must be applied BEFORE kapt in the plugins { } block."); } diff --git a/src/main/java/net/fabricmc/loom/configuration/MavenConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/MavenConfiguration.java new file mode 100644 index 00000000..2fb2ae7c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/MavenConfiguration.java @@ -0,0 +1,57 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration; + +import org.gradle.api.Project; + +import net.fabricmc.loom.LoomGradleExtension; + +public class MavenConfiguration { + public static void setup(Project project) { + LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + + project.getRepositories().flatDir(repo -> { + repo.setName("UserLocalCacheFiles"); + repo.dir(extension.getRootProjectBuildCache()); + }); + + project.getRepositories().maven(repo -> { + repo.setName("UserLocalRemappedMods"); + repo.setUrl(extension.getRemappedModCache()); + }); + + project.getRepositories().maven(repo -> { + repo.setName("Fabric"); + repo.setUrl("https://maven.fabricmc.net/"); + }); + + project.getRepositories().maven(repo -> { + repo.setName("Mojang"); + repo.setUrl("https://libraries.minecraft.net/"); + }); + + project.getRepositories().mavenCentral(); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java new file mode 100644 index 00000000..7534c27b --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/RemapConfiguration.java @@ -0,0 +1,159 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration; + +import java.io.IOException; + +import com.google.common.base.Preconditions; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.UnknownTaskException; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.bundling.AbstractArchiveTask; +import org.jetbrains.annotations.ApiStatus; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.build.JarRemapper; +import net.fabricmc.loom.build.nesting.NestedDependencyProvider; +import net.fabricmc.loom.task.AbstractLoomTask; +import net.fabricmc.loom.task.RemapAllSourcesTask; +import net.fabricmc.loom.task.RemapJarTask; +import net.fabricmc.loom.task.RemapSourcesJarTask; +import net.fabricmc.loom.util.SourceRemapper; + +public class RemapConfiguration { + private static final String DEFAULT_JAR_TASK_NAME = JavaPlugin.JAR_TASK_NAME; + private static final String DEFAULT_SOURCES_JAR_TASK_NAME = "sourcesJar"; + private static final String DEFAULT_REMAP_JAR_TASK_NAME = "remapJar"; + private static final String DEFAULT_REMAP_SOURCES_JAR_TASK_NAME = "remapSourcesJar"; + private static final String DEFAULT_REMAP_ALL_JARS_TASK_NAME = "remapAllJars"; + private static final String DEFAULT_REMAP_ALL_SOURCES_TASK_NAME = "remapAllSources"; + + public static void setupDefaultRemap(Project project) { + setupRemap(project, true, DEFAULT_JAR_TASK_NAME, DEFAULT_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_JAR_TASK_NAME, DEFAULT_REMAP_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_ALL_JARS_TASK_NAME, DEFAULT_REMAP_ALL_SOURCES_TASK_NAME); + } + + @ApiStatus.Experimental // This is only an api if you squint really hard, expect it to explode every 5 mins. If you must call in afterEvaluate on all projects + public static void setupRemap(Project project, String jarTaskName, String sourcesJarTaskName, String remapJarTaskName, String remapSourcesJarTaskName, String remapAllJarsTaskName, String remapAllSourcesTaskName) { + setupRemap(project, false, jarTaskName, sourcesJarTaskName, remapJarTaskName, remapSourcesJarTaskName, remapAllJarsTaskName, remapAllSourcesTaskName); + } + + // isDefaultRemap is set to true for the standard remap task, some defaults are left out when this is false. + private static void setupRemap(Project project, boolean isDefaultRemap, String jarTaskName, String sourcesJarTaskName, String remapJarTaskName, String remapSourcesJarTaskName, String remapAllJarsTaskName, String remapAllSourcesTaskName) { + LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + AbstractArchiveTask jarTask = (AbstractArchiveTask) project.getTasks().getByName(jarTaskName); + RemapJarTask remapJarTask = (RemapJarTask) project.getTasks().findByName(remapJarTaskName); + + assert remapJarTask != null; + + if (!remapJarTask.getInput().isPresent() && isDefaultRemap) { + jarTask.setClassifier("dev"); + remapJarTask.setClassifier(""); + remapJarTask.getInput().set(jarTask.getArchivePath()); + } + + if (isDefaultRemap) { + extension.getUnmappedModCollection().from(jarTask); + remapJarTask.getAddNestedDependencies().set(true); + remapJarTask.getRemapAccessWidener().set(true); + + project.getArtifacts().add("archives", remapJarTask); + } + + remapJarTask.dependsOn(jarTask); + project.getTasks().getByName("build").dependsOn(remapJarTask); + + // TODO this might be wrong? + project.getTasks().withType(RemapJarTask.class).forEach(task -> { + if (task.getAddNestedDependencies().getOrElse(false)) { + NestedDependencyProvider.getRequiredTasks(project).forEach(task::dependsOn); + } + }); + + SourceRemapper remapper = null; + // TODO what is this for? + Task parentTask = project.getTasks().getByName("build"); + + if (extension.isShareCaches()) { + Project rootProject = project.getRootProject(); + + if (extension.isRootProject()) { + SourceRemapper sourceRemapper = new SourceRemapper(rootProject, false); + JarRemapper jarRemapper = new JarRemapper(); + + remapJarTask.jarRemapper = jarRemapper; + + rootProject.getTasks().register(remapAllSourcesTaskName, RemapAllSourcesTask.class, task -> { + task.sourceRemapper = sourceRemapper; + task.doLast(t -> sourceRemapper.remapAll()); + }); + + parentTask = rootProject.getTasks().getByName(remapAllSourcesTaskName); + + rootProject.getTasks().register(remapAllJarsTaskName, AbstractLoomTask.class, task -> { + task.doLast(t -> { + try { + jarRemapper.remap(); + } catch (IOException e) { + throw new RuntimeException("Failed to remap jars", e); + } + }); + }); + } else { + parentTask = rootProject.getTasks().getByName(remapAllSourcesTaskName); + remapper = ((RemapAllSourcesTask) parentTask).sourceRemapper; + Preconditions.checkNotNull(remapper); + + remapJarTask.jarRemapper = ((RemapJarTask) rootProject.getTasks().getByName(remapJarTaskName)).jarRemapper; + + project.getTasks().getByName("build").dependsOn(parentTask); + project.getTasks().getByName("build").dependsOn(rootProject.getTasks().getByName(remapAllJarsTaskName)); + rootProject.getTasks().getByName(remapAllJarsTaskName).dependsOn(project.getTasks().getByName(remapJarTaskName)); + } + } + + try { + AbstractArchiveTask sourcesTask = (AbstractArchiveTask) project.getTasks().getByName(sourcesJarTaskName); + + RemapSourcesJarTask remapSourcesJarTask = (RemapSourcesJarTask) project.getTasks().findByName(remapSourcesJarTaskName); + Preconditions.checkNotNull(remapSourcesJarTask, "Could not find " + remapSourcesJarTaskName + " in " + project.getName()); + remapSourcesJarTask.setInput(sourcesTask.getArchivePath()); + remapSourcesJarTask.setOutput(sourcesTask.getArchivePath()); + remapSourcesJarTask.dependsOn(project.getTasks().getByName(sourcesJarTaskName)); + + if (isDefaultRemap) { + remapSourcesJarTask.doLast(task -> project.getArtifacts().add("archives", remapSourcesJarTask.getOutput())); + } + + if (extension.isShareCaches()) { + remapSourcesJarTask.setSourceRemapper(remapper); + } + + parentTask.dependsOn(remapSourcesJarTask); + } catch (UnknownTaskException ignored) { + // pass + } + } +} diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index 10d52579..2c0a3d6a 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -30,11 +30,15 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import com.google.common.base.Preconditions; import org.gradle.api.Action; import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.FileCollection; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.provider.Property; @@ -42,49 +46,64 @@ import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.TaskAction; import org.gradle.jvm.tasks.Jar; +import org.jetbrains.annotations.ApiStatus; import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.build.JarRemapper; import net.fabricmc.loom.build.MixinRefmapHelper; -import net.fabricmc.loom.build.NestedJars; +import net.fabricmc.loom.build.nesting.NestedJarPathProvider; +import net.fabricmc.loom.build.nesting.JarNester; +import net.fabricmc.loom.build.nesting.MergedNestedJarProvider; +import net.fabricmc.loom.build.nesting.NestedDependencyProvider; +import net.fabricmc.loom.build.nesting.NestedJarProvider; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; +import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.TinyRemapperMappingsHelper; -import net.fabricmc.loom.util.ZipReprocessorUtil; import net.fabricmc.loom.util.gradle.GradleSupport; import net.fabricmc.stitch.util.Pair; -import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyUtils; public class RemapJarTask extends Jar { private final RegularFileProperty input; private final Property addNestedDependencies; + private final Property addDefaultNestedDependencies; private final Property remapAccessWidener; private final List> remapOptions = new ArrayList<>(); public JarRemapper jarRemapper; private FileCollection classpath; + private final Set nestedPaths = new LinkedHashSet<>(); public RemapJarTask() { super(); input = GradleSupport.getfileProperty(getProject()); addNestedDependencies = getProject().getObjects().property(Boolean.class); + addDefaultNestedDependencies = getProject().getObjects().property(Boolean.class); remapAccessWidener = getProject().getObjects().property(Boolean.class); // false by default, I have no idea why I have to do it for this property and not the other one remapAccessWidener.set(false); + addDefaultNestedDependencies.set(true); } @TaskAction public void doTask() throws Throwable { + boolean singleRemap = false; + if (jarRemapper == null) { - doSingleRemap(); - } else { - scheduleRemap(); + singleRemap = true; + jarRemapper = new JarRemapper(); + } + + scheduleRemap(singleRemap || getProject().getExtensions().getByType(LoomGradleExtension.class).isRootProject()); + + if (singleRemap) { + jarRemapper.remap(); } } - public void doSingleRemap() throws Throwable { + public void scheduleRemap(boolean isMainRemapTask) throws Throwable { Project project = getProject(); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); Path input = this.getInput().getAsFile().get().toPath(); @@ -99,86 +118,7 @@ public class RemapJarTask extends Jar { String fromM = "named"; String toM = "intermediary"; - Path[] classpath = getRemapClasspath(); - - TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper(); - - remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM, false)); - - for (File mixinMapFile : extension.getAllMixinMappings()) { - if (mixinMapFile.exists()) { - remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapFile.toPath(), fromM, toM)); - } - } - - // Apply any requested options to tiny remapper - for (Action remapOption : this.remapOptions) { - remapOption.execute(remapperBuilder); - } - - project.getLogger().info(":remapping " + input.getFileName()); - - StringBuilder rc = new StringBuilder("Remap classpath: "); - - for (Path p : classpath) { - rc.append("\n - ").append(p.toString()); - } - - project.getLogger().debug(rc.toString()); - - TinyRemapper remapper = remapperBuilder.build(); - - try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { - outputConsumer.addNonClassFiles(input); - remapper.readClassPath(classpath); - remapper.readInputs(input); - remapper.apply(outputConsumer); - } catch (Exception e) { - remapper.finish(); - throw new RuntimeException("Failed to remap " + input + " to " + output, e); - } - - if (getRemapAccessWidener().getOrElse(false) && extension.accessWidener != null) { - extension.getJarProcessorManager().getByType(AccessWidenerJarProcessor.class).remapAccessWidener(output, remapper.getRemapper()); - } - - remapper.finish(); - - if (!Files.exists(output)) { - throw new RuntimeException("Failed to remap " + input + " to " + output + " - file missing!"); - } - - if (MixinRefmapHelper.addRefmapName(extension.getRefmapName(), output)) { - project.getLogger().debug("Transformed mixin reference maps in output JAR!"); - } - - if (getAddNestedDependencies().getOrElse(false)) { - if (NestedJars.addNestedJars(project, output)) { - project.getLogger().debug("Added nested jar paths to mod json"); - } - } - - if (isReproducibleFileOrder() || isPreserveFileTimestamps()) { - ZipReprocessorUtil.reprocessZip(output.toFile(), isReproducibleFileOrder(), isPreserveFileTimestamps()); - } - } - - public void scheduleRemap() throws Throwable { - Project project = getProject(); - LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - Path input = this.getInput().getAsFile().get().toPath(); - Path output = this.getArchivePath().toPath(); - - if (!Files.exists(input)) { - throw new FileNotFoundException(input.toString()); - } - - MappingsProvider mappingsProvider = extension.getMappingsProvider(); - - String fromM = "named"; - String toM = "intermediary"; - - if (extension.isRootProject()) { + if (isMainRemapTask) { jarRemapper.addToClasspath(getRemapClasspath()); jarRemapper.addMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM, false)); @@ -193,6 +133,9 @@ public class RemapJarTask extends Jar { // Add remap options to the jar remapper jarRemapper.addOptions(this.remapOptions); + NestedJarProvider nestedJarProvider = getNestedJarProvider(); + nestedJarProvider.prepare(getProject()); + jarRemapper.scheduleRemap(input, output) .supplyAccessWidener((remapData, remapper) -> { if (getRemapAccessWidener().getOrElse(false) && extension.accessWidener != null) { @@ -223,9 +166,7 @@ public class RemapJarTask extends Jar { } if (getAddNestedDependencies().getOrElse(false)) { - if (NestedJars.addNestedJars(project, output)) { - project.getLogger().debug("Added nested jar paths to mod json"); - } + JarNester.nestJars(nestedJarProvider.provide(), output.toFile(), project.getLogger()); } if (accessWidener != null) { @@ -235,6 +176,25 @@ public class RemapJarTask extends Jar { }); } + private NestedJarProvider getNestedJarProvider() { + Configuration includeConfiguration = getProject().getConfigurations().getByName(Constants.Configurations.INCLUDE); + + if (!addDefaultNestedDependencies.getOrElse(true)) { + return new NestedJarPathProvider(nestedPaths); + } + + NestedJarProvider baseProvider = NestedDependencyProvider.createNestedDependencyProviderFromConfiguration(getProject(), includeConfiguration); + + if (nestedPaths.isEmpty()) { + return baseProvider; + } + + return new MergedNestedJarProvider( + baseProvider, + new NestedJarPathProvider(nestedPaths) + ); + } + private Path[] getRemapClasspath() { FileCollection files = this.classpath; @@ -258,6 +218,11 @@ public class RemapJarTask extends Jar { return addNestedDependencies; } + @Input + public Property getAddDefaultNestedDependencies() { + return addDefaultNestedDependencies; + } + @Input public Property getRemapAccessWidener() { return remapAccessWidener; @@ -276,4 +241,12 @@ public class RemapJarTask extends Jar { return this; } + + @ApiStatus.Experimental // This only allows mod jars, proceed with care when trying to pass in configurations with projects, or something that depends on a task. + public RemapJarTask include(Object... paths) { + Collections.addAll(nestedPaths, paths); + this.addNestedDependencies.set(true); + + return this; + } } diff --git a/src/main/java/net/fabricmc/loom/util/ModUtils.java b/src/main/java/net/fabricmc/loom/util/ModUtils.java new file mode 100644 index 00000000..1dfc43b2 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/ModUtils.java @@ -0,0 +1,42 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util; + +import java.io.File; +import java.io.IOException; +import java.util.zip.ZipFile; + +public final class ModUtils { + private ModUtils() { + } + + public static boolean isMod(File input) { + try (ZipFile zipFile = new ZipFile(input)) { + return zipFile.getEntry("fabric.mod.json") != null; + } catch (IOException e) { + return false; + } + } +} diff --git a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy index 3716affe..26381351 100644 --- a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy @@ -58,9 +58,4 @@ class MultiProjectTest extends Specification implements ProjectTestTrait, Archiv '6.8.3' | _ '7.0-milestone-2' | _ } - - @Override - String warningMode(String gradleVersion) { - "none" // TODO fix this! - } } diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index 7530ff15..ecde3932 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -88,7 +88,7 @@ trait ProjectTestTrait { return "all" } - System.getenv().TEST_WARNING_MODE ?: 'all' + 'fail' } String gradleHomeDirectory(String gradleVersion) { diff --git a/src/test/resources/projects/multiproject/src/main/resources/fabric.mod.json b/src/test/resources/projects/multiproject/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..38e811de --- /dev/null +++ b/src/test/resources/projects/multiproject/src/main/resources/fabric.mod.json @@ -0,0 +1,6 @@ +{ + "schemaVersion": 1, + "id": "modid", + "version": "1.0.0", + "name": "Example Mod" +} From e6ac2afc7b5eab82be0266774dc95e834d10d013 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Mon, 15 Mar 2021 23:31:18 +0000 Subject: [PATCH 11/24] Ensure outputs are reproducable across all OS's. (#363) --- .github/workflows/test-push.yml | 27 ++++++++++++++- build.gradle | 5 +++ .../assets/MinecraftAssetsProvider.java | 6 ++-- .../net/fabricmc/loom/task/RemapJarTask.java | 9 +++++ .../loom/task/RemapSourcesJarTask.java | 33 ++++++++++++------- .../fabricmc/loom/util/OperatingSystem.java | 4 +++ .../fabricmc/loom/util/SourceRemapper.java | 9 ++--- .../loom/util/ZipReprocessorUtil.java | 20 +++++++++-- .../loom/ReproducibleBuildTest.groovy | 8 ++--- .../loom/util/ProjectTestTrait.groovy | 1 - .../projects/reproducible/build.gradle | 6 +++- .../projects/reproducible/gradle.properties | 4 --- 12 files changed, 97 insertions(+), 35 deletions(-) diff --git a/.github/workflows/test-push.yml b/.github/workflows/test-push.yml index 05c43f99..5b1aa687 100644 --- a/.github/workflows/test-push.yml +++ b/.github/workflows/test-push.yml @@ -66,7 +66,32 @@ jobs: TEST_WARNING_MODE: fail - uses: actions/upload-artifact@v2 - if: ${{ always() }} + if: ${{ failure() }} with: name: ${{ matrix.test }} (${{ matrix.java }}) Results + path: build/reports/ + + # Special case this test to run across all os's + reproducible_build_test: + needs: build + + strategy: + fail-fast: false + matrix: + java: [ 1.8, 11, 15 ] + os: [ windows-2019, ubuntu-20.04, macos-10.15 ] + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + + - run: ./gradlew test --tests *ReproducibleBuildTest --stacktrace + + - uses: actions/upload-artifact@v2 + if: ${{ failure() }} + with: + name: Reproducible Build ${{ matrix.os }} (${{ matrix.java }}) Results path: build/reports/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5664a2f4..f1d8e6bb 100644 --- a/build.gradle +++ b/build.gradle @@ -211,6 +211,11 @@ task writeActionsTestMatrix() { return } + if (it.name.endsWith("ReproducibleBuildTest.groovy")) { + // This test gets a special case to run across all os's + return + } + testMatrix.add(it.name.replace(".groovy", "")) } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java index 97e8503c..931e8672 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java @@ -118,13 +118,15 @@ public class MinecraftAssetsProvider { try { HashedDownloadUtil.downloadIfInvalid(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, sha1, project.getLogger(), true, () -> { - if (loggers.isEmpty()) { + ProgressLogger logger = loggers.pollFirst(); + + if (logger == null) { //Create a new logger if we need one progressLogger[0] = ProgressLogger.getProgressFactory(project, MinecraftAssetsProvider.class.getName()); progressLogger[0].start("Downloading assets...", "assets"); } else { // use a free logger if we can - progressLogger[0] = loggers.pop(); + progressLogger[0] = logger; } project.getLogger().debug("downloading asset " + assetName[0]); diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index 2c0a3d6a..2e69f12a 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -62,6 +62,7 @@ import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.TinyRemapperMappingsHelper; import net.fabricmc.loom.util.gradle.GradleSupport; +import net.fabricmc.loom.util.ZipReprocessorUtil; import net.fabricmc.stitch.util.Pair; import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyUtils; @@ -173,6 +174,14 @@ public class RemapJarTask extends Jar { boolean replaced = ZipUtil.replaceEntry(data.output.toFile(), accessWidener.getLeft(), accessWidener.getRight()); Preconditions.checkArgument(replaced, "Failed to remap access widener"); } + + if (isReproducibleFileOrder() || !isPreserveFileTimestamps()) { + try { + ZipReprocessorUtil.reprocessZip(output.toFile(), isReproducibleFileOrder(), isPreserveFileTimestamps()); + } catch (IOException e) { + throw new RuntimeException("Failed to re-process jar", e); + } + } }); } diff --git a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java index 2d388fba..9548ad7f 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java @@ -26,8 +26,6 @@ package net.fabricmc.loom.task; import java.io.File; -import org.gradle.api.model.ObjectFactory; -import org.gradle.api.provider.Property; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.Internal; @@ -35,29 +33,24 @@ import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskAction; import net.fabricmc.loom.util.SourceRemapper; -import net.fabricmc.loom.util.ZipReprocessorUtil; public class RemapSourcesJarTask extends AbstractLoomTask { private Object input; private Object output; private String direction = "intermediary"; private SourceRemapper sourceRemapper = null; - private final Property archivePreserveFileTimestamps; - private final Property archiveReproducibleFileOrder; + private boolean preserveFileTimestamps = true; + private boolean reproducibleFileOrder = false; public RemapSourcesJarTask() { - ObjectFactory objectFactory = getProject().getObjects(); - archivePreserveFileTimestamps = objectFactory.property(Boolean.class); - archiveReproducibleFileOrder = objectFactory.property(Boolean.class); } @TaskAction public void remap() throws Exception { if (sourceRemapper == null) { - SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named")); - ZipReprocessorUtil.reprocessZip(getOutput(), archivePreserveFileTimestamps.getOrElse(true), archiveReproducibleFileOrder.getOrElse(false)); + SourceRemapper.remapSources(getProject(), getInput(), getOutput(), direction.equals("named"), reproducibleFileOrder, preserveFileTimestamps); } else { - sourceRemapper.scheduleRemapSources(getInput(), getOutput(), archivePreserveFileTimestamps.getOrElse(true), archiveReproducibleFileOrder.getOrElse(false)); + sourceRemapper.scheduleRemapSources(getInput(), getOutput(), reproducibleFileOrder, preserveFileTimestamps); } } @@ -97,4 +90,22 @@ public class RemapSourcesJarTask extends AbstractLoomTask { public void setTargetNamespace(String value) { this.direction = value; } + + @Input + public boolean isPreserveFileTimestamps() { + return preserveFileTimestamps; + } + + public void setPreserveFileTimestamps(boolean preserveFileTimestamps) { + this.preserveFileTimestamps = preserveFileTimestamps; + } + + @Input + public boolean isReproducibleFileOrder() { + return reproducibleFileOrder; + } + + public void setReproducibleFileOrder(boolean reproducibleFileOrder) { + this.reproducibleFileOrder = reproducibleFileOrder; + } } diff --git a/src/main/java/net/fabricmc/loom/util/OperatingSystem.java b/src/main/java/net/fabricmc/loom/util/OperatingSystem.java index 2f69bcb8..db622790 100644 --- a/src/main/java/net/fabricmc/loom/util/OperatingSystem.java +++ b/src/main/java/net/fabricmc/loom/util/OperatingSystem.java @@ -49,6 +49,10 @@ public class OperatingSystem { return System.getProperty("sun.arch.data.model").contains("64"); } + public static boolean isWindows() { + return getOS().equals("windows"); + } + public static boolean isCIBuild() { String loomProperty = System.getProperty("fabric.loom.ci"); diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 873b2e09..e673d0a7 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -62,17 +62,12 @@ public class SourceRemapper { this.toNamed = toNamed; } - public static void remapSources(Project project, File input, File output, boolean named) throws Exception { + public static void remapSources(Project project, File input, File output, boolean named, boolean reproducibleFileOrder, boolean preserveFileTimestamps) { SourceRemapper sourceRemapper = new SourceRemapper(project, named); - sourceRemapper.scheduleRemapSources(input, output, false, true); + sourceRemapper.scheduleRemapSources(input, output, reproducibleFileOrder, preserveFileTimestamps); sourceRemapper.remapAll(); } - @Deprecated - public void scheduleRemapSources(File source, File destination) throws Exception { - scheduleRemapSources(source, destination, false, true); // Not reproducable by default, old behavior - } - public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) { remapTasks.add((logger) -> { try { diff --git a/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java b/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java index 662acf82..735b3346 100644 --- a/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java +++ b/src/main/java/net/fabricmc/loom/util/ZipReprocessorUtil.java @@ -29,11 +29,20 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.attribute.FileTime; +import java.util.Calendar; +import java.util.Comparator; +import java.util.GregorianCalendar; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; public class ZipReprocessorUtil { + /** + * See {@link org.gradle.api.internal.file.archive.ZipCopyAction} about this. + */ + private static final long CONSTANT_TIME_FOR_ZIP_ENTRIES = new GregorianCalendar(1980, Calendar.FEBRUARY, 1, 0, 0, 0).getTimeInMillis(); + private ZipReprocessorUtil() { } public static void reprocessZip(File file, boolean reproducibleFileOrder, boolean preserveFileTimestamps) throws IOException { @@ -45,7 +54,7 @@ public class ZipReprocessorUtil { ZipEntry[] entries; if (reproducibleFileOrder) { - entries = zipFile.stream().sorted((a, b) -> a.getName().compareTo(b.getName())).toArray(ZipEntry[]::new); + entries = zipFile.stream().sorted(Comparator.comparing(ZipEntry::getName)).toArray(ZipEntry[]::new); } else { entries = zipFile.stream().toArray(ZipEntry[]::new); } @@ -54,11 +63,16 @@ public class ZipReprocessorUtil { try (ZipOutputStream zipOutputStream = new ZipOutputStream(outZip)) { for (ZipEntry entry : entries) { + ZipEntry newEntry = entry; + if (!preserveFileTimestamps) { - entry.setTime(0); + 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)); } - zipOutputStream.putNextEntry(entry); + zipOutputStream.putNextEntry(newEntry); InputStream inputStream = zipFile.getInputStream(entry); byte[] buf = new byte[1024]; int length; diff --git a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy index cb1343ba..362899f8 100644 --- a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy @@ -28,13 +28,11 @@ import com.google.common.hash.HashCode import com.google.common.hash.Hashing import com.google.common.io.Files import net.fabricmc.loom.util.ProjectTestTrait -import spock.lang.IgnoreIf import spock.lang.Specification import spock.lang.Unroll import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -@IgnoreIf({ os.windows }) // Linux and mac create the same files, im unsure why windows is different. Let me know if you have any ideas? class ReproducibleBuildTest extends Specification implements ProjectTestTrait { @Override String name() { @@ -48,11 +46,11 @@ class ReproducibleBuildTest extends Specification implements ProjectTestTrait { then: result.task(":build").outcome == SUCCESS getOutputHash("fabric-example-mod-1.0.0.jar") == modHash - getOutputHash("fabric-example-mod-1.0.0-sources.jar") == sourceHash + getOutputHash("fabric-example-mod-1.0.0-sources.jar") in sourceHash // Done for different line endings. where: gradle | modHash | sourceHash - '6.8.3' | "ccd6aaff1b06df01e4dd8c08625b82c9" | "8bd590dc03b7dd0de3a4a7aeb431d4e8" - '7.0-milestone-2' | "ccd6aaff1b06df01e4dd8c08625b82c9" | "8bd590dc03b7dd0de3a4a7aeb431d4e8" + '6.8.3' | "6132ffb4117adb7e258f663110552952" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] + '7.0-milestone-2' | "6132ffb4117adb7e258f663110552952" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] } String getOutputHash(String name) { diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index ecde3932..b81b26f0 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -26,7 +26,6 @@ package net.fabricmc.loom.util import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner -import spock.lang.Shared trait ProjectTestTrait { static File gradleHome = File.createTempDir() diff --git a/src/test/resources/projects/reproducible/build.gradle b/src/test/resources/projects/reproducible/build.gradle index 0fb0dc6f..de5d2cc3 100644 --- a/src/test/resources/projects/reproducible/build.gradle +++ b/src/test/resources/projects/reproducible/build.gradle @@ -14,7 +14,6 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" } processResources { @@ -48,4 +47,9 @@ jar { tasks.withType(AbstractArchiveTask) { preserveFileTimestamps = false reproducibleFileOrder = true +} + +remapSourcesJar { + preserveFileTimestamps = false + reproducibleFileOrder = true } \ No newline at end of file diff --git a/src/test/resources/projects/reproducible/gradle.properties b/src/test/resources/projects/reproducible/gradle.properties index 2e85dfd8..3dc7831a 100644 --- a/src/test/resources/projects/reproducible/gradle.properties +++ b/src/test/resources/projects/reproducible/gradle.properties @@ -11,7 +11,3 @@ org.gradle.jvmargs=-Xmx1G mod_version = 1.0.0 maven_group = com.example archives_base_name = fabric-example-mod - -# Dependencies - # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version=0.31.0+1.16 From 72a79ffb9cde85185523d2a31de178810570ea75 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Thu, 18 Mar 2021 14:39:30 +0000 Subject: [PATCH 12/24] Fix case where it wont try to download file. --- src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java b/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java index 86cf80a3..8f1f2b25 100644 --- a/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java +++ b/src/main/java/net/fabricmc/loom/util/HashedDownloadUtil.java @@ -100,6 +100,11 @@ public class HashedDownloadUtil { @Nullable private static String getSha1(File to, Logger logger) { + if (!to.exists()) { + delete(to); + return null; + } + File sha1File = getSha1File(to); try { From c02f436123e2e89dd6beef8bc3ea2872ca6dc509 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Tue, 23 Mar 2021 08:51:41 +0000 Subject: [PATCH 13/24] Run tests against 7.0-rc-1 --- .../net/fabricmc/loom/AccessWidenerTest.groovy | 6 +++--- .../groovy/net/fabricmc/loom/DecompileTest.groovy | 2 +- src/test/groovy/net/fabricmc/loom/KotlinTest.groovy | 6 +++--- .../fabricmc/loom/MojangMappingsProjectTest.groovy | 6 +++--- .../groovy/net/fabricmc/loom/MultiProjectTest.groovy | 6 +++--- .../net/fabricmc/loom/ReproducibleBuildTest.groovy | 6 +++--- .../groovy/net/fabricmc/loom/RunConfigTest.groovy | 12 ++++++------ .../net/fabricmc/loom/SimpleProjectTest.groovy | 6 +++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy index 37e6cf9c..de18a6f4 100644 --- a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy @@ -45,9 +45,9 @@ class AccessWidenerTest extends Specification implements ProjectTestTrait, Archi result.task(":build").outcome == SUCCESS getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r','') where: - gradle | _ - '6.8.3' | _ - '7.0-milestone-2' | _ + gradle | _ + '6.8.3' | _ + '7.0-rc-1' | _ } String expected() { diff --git a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy b/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy index c0e5ea6d..47ec05b9 100644 --- a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy @@ -48,7 +48,7 @@ class DecompileTest extends Specification implements ProjectTestTrait { decompiler | task | gradle 'fernflower' | "genSources" | "6.8.3" 'fernflower' | "genSources" | "4.9" - 'fernflower' | "genSources" | "7.0-milestone-2" + 'fernflower' | "genSources" | "7.0-rc-1" 'cfr' | "genSourcesWithExperimentalCfr" | "6.8.3" } } diff --git a/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy b/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy index 380dffda..d9a07847 100644 --- a/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy @@ -43,8 +43,8 @@ class KotlinTest extends Specification implements ProjectTestTrait { then: result.task(":build").outcome == SUCCESS where: - gradle | _ - '6.8.3' | _ - '7.0-milestone-2' | _ + gradle | _ + '6.8.3' | _ + '7.0-rc-1' | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy index dd8a9808..1a2c303f 100644 --- a/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy @@ -43,8 +43,8 @@ class MojangMappingsProjectTest extends Specification implements ProjectTestTrai then: result.task(":build").outcome == SUCCESS where: - gradle | _ - '6.8.3' | _ - '7.0-milestone-2' | _ + gradle | _ + '6.8.3' | _ + '7.0-rc-1' | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy index 26381351..15bb017b 100644 --- a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy @@ -54,8 +54,8 @@ class MultiProjectTest extends Specification implements ProjectTestTrait, Archiv hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar") where: - gradle | _ - '6.8.3' | _ - '7.0-milestone-2' | _ + gradle | _ + '6.8.3' | _ + '7.0-rc-1' | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy index 362899f8..0d1ba1b5 100644 --- a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy @@ -48,9 +48,9 @@ class ReproducibleBuildTest extends Specification implements ProjectTestTrait { getOutputHash("fabric-example-mod-1.0.0.jar") == modHash getOutputHash("fabric-example-mod-1.0.0-sources.jar") in sourceHash // Done for different line endings. where: - gradle | modHash | sourceHash - '6.8.3' | "6132ffb4117adb7e258f663110552952" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] - '7.0-milestone-2' | "6132ffb4117adb7e258f663110552952" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] + gradle | modHash | sourceHash + '6.8.3' | "6132ffb4117adb7e258f663110552952" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] + '7.0-rc-1' | "6132ffb4117adb7e258f663110552952" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] } String getOutputHash(String name) { diff --git a/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy b/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy index e76369cc..96619f5f 100644 --- a/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy @@ -44,11 +44,11 @@ class RunConfigTest extends Specification implements ProjectTestTrait { then: result.task(":${task}").outcome == SUCCESS where: - task | _ - 'runClient' | _ - 'runServer' | _ - 'runTestmodClient' | _ - 'runTestmodServer' | _ - 'runAutoTestServer' | _ + task | _ + 'runClient' | _ + 'runServer' | _ + 'runTestmodClient' | _ + 'runTestmodServer' | _ + 'runAutoTestServer' | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy index 6954b88d..f4993561 100644 --- a/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy @@ -43,9 +43,9 @@ class SimpleProjectTest extends Specification implements ProjectTestTrait { then: result.task(":build").outcome == SUCCESS where: - gradle | _ - '6.8.3' | _ - '7.0-milestone-2' | _ + gradle | _ + '6.8.3' | _ + '7.0-rc-1' | _ } @Unroll From 43a6b0f65fa468b57a63795c62ce4f48e05b7eb2 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Tue, 23 Mar 2021 19:08:15 +0000 Subject: [PATCH 14/24] Revert some of the changes to genSource's. More work is needed to fix all the issues with it but its not really something I want to get into right now. --- .../fernflower/ForkingJavaExec.java | 25 ++++++++++++++++++- .../loom/util/ProjectTestTrait.groovy | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java index b62784fb..f33e491f 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java @@ -24,10 +24,14 @@ package net.fabricmc.loom.decompilers.fernflower; +import java.net.URL; import java.net.URLClassLoader; import org.gradle.api.Action; import org.gradle.api.Project; +import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.file.FileCollection; import org.gradle.process.ExecResult; import org.gradle.process.JavaExecSpec; @@ -40,8 +44,27 @@ import org.gradle.process.JavaExecSpec; public class ForkingJavaExec { public static ExecResult javaexec(Project project, Action action) { return project.javaexec(spec -> { - spec.classpath((Object[]) ((URLClassLoader) ForkingJavaExec.class.getClassLoader()).getURLs()); + spec.classpath(getClasspath(project)); action.execute(spec); }); } + + private static Object getClasspath(Project project) { + if (System.getProperty("fabric.loom.test") != null) { + return getTestClasspath(); + } + + return getRuntimeClasspath(project.getRootProject().getPlugins().hasPlugin("fabric-loom") ? project.getRootProject() : project); + } + + private static FileCollection getRuntimeClasspath(Project project) { + ConfigurationContainer configurations = project.getBuildscript().getConfigurations(); + DependencyHandler handler = project.getDependencies(); + return configurations.getByName("classpath") + .plus(configurations.detachedConfiguration(handler.localGroovy())); + } + + private static URL[] getTestClasspath() { + return ((URLClassLoader) ForkingJavaExec.class.getClassLoader()).getURLs(); + } } diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index b81b26f0..e66879f0 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -72,6 +72,8 @@ trait ProjectTestTrait { } BuildResult create(String task, String gradleVersion = "6.8.3") { + System.setProperty("fabric.loom.test", "true") + GradleRunner.create() .withProjectDir(testProjectDir) .withArguments(task, "--stacktrace", "--warning-mode", warningMode(gradleVersion), "--gradle-user-home", gradleHomeDirectory(gradleVersion)) From 759cac2e6b0f9b8ecfc707472b27985e0591adb8 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Thu, 25 Mar 2021 19:03:35 +0000 Subject: [PATCH 15/24] Constant unpicking (#328) * Start adding constant unpicking * Update to use unpick cli * Fix build? * Fix? * Fix log spam when unpicking * Improve unpick tests --- .../fabricmc/loom/LoomGradleExtension.java | 4 + .../configuration/CompileConfiguration.java | 4 + .../providers/mappings/MappingsProvider.java | 75 +++++++++++ .../minecraft/MinecraftMappedProvider.java | 4 + .../loom/task/GenerateSourcesTask.java | 31 +++-- .../net/fabricmc/loom/task/LoomTasks.java | 25 +++- .../net/fabricmc/loom/task/UnpickJarTask.java | 126 ++++++++++++++++++ .../net/fabricmc/loom/util/Constants.java | 2 + src/main/resources/unpick-logging.properties | 1 + .../net/fabricmc/loom/UnpickTest.groovy | 62 +++++++++ .../loom/util/ProjectTestTrait.groovy | 7 +- .../resources/projects/unpick/build.gradle | 9 ++ .../unpick/src/main/java/ExampleMod.java | 10 ++ 13 files changed, 345 insertions(+), 15 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/task/UnpickJarTask.java create mode 100644 src/main/resources/unpick-logging.properties create mode 100644 src/test/groovy/net/fabricmc/loom/UnpickTest.groovy create mode 100644 src/test/resources/projects/unpick/build.gradle create mode 100644 src/test/resources/projects/unpick/src/main/java/ExampleMod.java diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index ea089af0..3234a628 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -354,6 +354,10 @@ public class LoomGradleExtension { return new File(getProjectPersistentCache(), "log4j.xml"); } + public File getUnpickLoggingConfigFile() { + return new File(getProjectPersistentCache(), "unpick-logging.properties"); + } + public ConfigurableFileCollection getLog4jConfigs() { return log4jConfigs; } diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index e6e7787e..6552089b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -64,9 +64,13 @@ public final class CompileConfiguration { Configuration includeConfig = project.getConfigurations().maybeCreate(Constants.Configurations.INCLUDE); includeConfig.setTransitive(false); // Dont get transitive deps + project.getConfigurations().maybeCreate(Constants.Configurations.MAPPING_CONSTANTS); + extendsFrom(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Constants.Configurations.MAPPING_CONSTANTS, project); + project.getConfigurations().maybeCreate(Constants.Configurations.MAPPINGS); project.getConfigurations().maybeCreate(Constants.Configurations.MAPPINGS_FINAL); project.getConfigurations().maybeCreate(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES); + project.getConfigurations().maybeCreate(Constants.Configurations.UNPICK_CLASSPATH); for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { Configuration compileModsConfig = project.getConfigurations().maybeCreate(entry.getSourceConfiguration()); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java index 8b19a3da..448082b9 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java @@ -28,6 +28,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; @@ -38,6 +39,7 @@ import java.util.function.Consumer; import com.google.common.base.Preconditions; import com.google.common.net.UrlEscapers; +import com.google.gson.JsonObject; import org.apache.commons.io.FileUtils; import org.apache.tools.ant.util.StringUtils; import org.gradle.api.Project; @@ -46,6 +48,7 @@ import org.zeroturnaround.zip.ZipEntrySource; import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessorManager; @@ -78,6 +81,9 @@ public class MappingsProvider extends DependencyProvider { // The mappings we use in practice public File tinyMappings; public File tinyMappingsJar; + private File unpickDefinitionsFile; + private boolean hasUnpickDefinitions; + private UnpickMetadata unpickMetadata; public MappingsProvider(Project project) { super(project); @@ -142,16 +148,32 @@ public class MappingsProvider extends DependencyProvider { } tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile(); + unpickDefinitionsFile = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".unpick").toFile(); tinyMappingsJar = new File(getExtension().getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar")); if (!tinyMappings.exists() || isRefreshDeps()) { storeMappings(getProject(), minecraftProvider, mappingsJar.toPath()); + } else { + try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) { + extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath()); + } } if (!tinyMappingsJar.exists() || isRefreshDeps()) { ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar); } + if (hasUnpickDefinitions()) { + String notation = String.format("%s:%s:%s:constants", + dependency.getDependency().getGroup(), + dependency.getDependency().getName(), + dependency.getDependency().getVersion() + ); + + getProject().getDependencies().add(Constants.Configurations.MAPPING_CONSTANTS, notation); + populateUnpickClasspath(); + } + addDependency(tinyMappingsJar, Constants.Configurations.MAPPINGS_FINAL); LoomGradleExtension extension = getExtension(); @@ -180,6 +202,7 @@ public class MappingsProvider extends DependencyProvider { try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) { extractMappings(fileSystem, baseTinyMappings); + extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath()); } if (baseMappingsAreV2()) { @@ -221,6 +244,40 @@ public class MappingsProvider extends DependencyProvider { Files.copy(jar.getPath("mappings/mappings.tiny"), extractTo, StandardCopyOption.REPLACE_EXISTING); } + private void extractUnpickDefinitions(FileSystem jar, Path extractTo) throws IOException { + Path unpickPath = jar.getPath("extras/definitions.unpick"); + Path unpickMetadataPath = jar.getPath("extras/unpick.json"); + + if (!Files.exists(unpickPath) || !Files.exists(unpickMetadataPath)) { + return; + } + + Files.copy(unpickPath, extractTo, StandardCopyOption.REPLACE_EXISTING); + + unpickMetadata = parseUnpickMetadata(unpickMetadataPath); + hasUnpickDefinitions = true; + } + + private UnpickMetadata parseUnpickMetadata(Path input) throws IOException { + JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(new String(Files.readAllBytes(input), StandardCharsets.UTF_8), JsonObject.class); + + if (!jsonObject.has("version") || jsonObject.get("version").getAsInt() != 1) { + throw new UnsupportedOperationException("Unsupported unpick version"); + } + + return new UnpickMetadata( + jsonObject.get("unpickGroup").getAsString(), + jsonObject.get("unpickVersion").getAsString() + ); + } + + private void populateUnpickClasspath() { + String unpickCliName = "unpick-cli"; + getProject().getDependencies().add(Constants.Configurations.UNPICK_CLASSPATH, + String.format("%s:%s:%s", unpickMetadata.unpickGroup, unpickCliName, unpickMetadata.unpickVersion) + ); + } + private void extractIntermediary(Path intermediaryJar, Path intermediaryTiny) throws IOException { getProject().getLogger().info(":extracting " + intermediaryJar.getFileName()); @@ -343,4 +400,22 @@ public class MappingsProvider extends DependencyProvider { public String getMappingsKey() { return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsVersion; } + + public File getUnpickDefinitionsFile() { + return unpickDefinitionsFile; + } + + public boolean hasUnpickDefinitions() { + return hasUnpickDefinitions; + } + + public static class UnpickMetadata { + public final String unpickGroup; + public final String unpickVersion; + + public UnpickMetadata(String unpickGroup, String unpickVersion) { + this.unpickGroup = unpickGroup; + this.unpickVersion = unpickVersion; + } + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java index 6301050a..0a61f2ba 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java @@ -169,6 +169,10 @@ public class MinecraftMappedProvider extends DependencyProvider { return minecraftMappedJar; } + public File getUnpickedJar() { + return new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("unpicked") + ".jar"); + } + @Override public String getTargetConfig() { return Constants.Configurations.MINECRAFT_NAMED; diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index 7c5862e4..25d6fe47 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; +import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.TaskAction; import net.fabricmc.loom.LoomGradleExtension; @@ -49,6 +50,8 @@ import net.fabricmc.stitch.util.StitchUtil; public class GenerateSourcesTask extends AbstractLoomTask { public final LoomDecompiler decompiler; + private File inputJar; + @Inject public GenerateSourcesTask(LoomDecompiler decompiler) { this.decompiler = decompiler; @@ -65,26 +68,18 @@ public class GenerateSourcesTask extends AbstractLoomTask { .stream().map(File::toPath).collect(Collectors.toSet()); DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries); - Path compiledJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath(); + Path runtimeJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath(); Path sourcesDestination = getMappedJarFileWithSuffix("-sources.jar").toPath(); Path linemap = getMappedJarFileWithSuffix("-sources.lmap").toPath(); - decompiler.decompile(compiledJar, sourcesDestination, linemap, metadata); + decompiler.decompile(inputJar.toPath(), sourcesDestination, linemap, metadata); if (Files.exists(linemap)) { Path linemappedJarDestination = getMappedJarFileWithSuffix("-linemapped.jar").toPath(); - remapLineNumbers(compiledJar, linemap, linemappedJarDestination); + // Line map the actually jar used to run the game, not the one used to decompile + remapLineNumbers(runtimeJar, linemap, linemappedJarDestination); - // In order for IDEs to recognize the new line mappings, we need to overwrite the existing compiled jar - // with the linemapped one. In the name of not destroying the existing jar, we will copy it to somewhere else. - Path unlinemappedJar = getMappedJarFileWithSuffix("-unlinemapped.jar").toPath(); - - // The second time genSources is ran, we want to keep the existing unlinemapped jar. - if (!Files.exists(unlinemappedJar)) { - Files.copy(compiledJar, unlinemappedJar); - } - - Files.copy(linemappedJarDestination, compiledJar, StandardCopyOption.REPLACE_EXISTING); + Files.copy(linemappedJarDestination, runtimeJar, StandardCopyOption.REPLACE_EXISTING); Files.delete(linemappedJarDestination); } } @@ -117,4 +112,14 @@ public class GenerateSourcesTask extends AbstractLoomTask { return new File(path.substring(0, path.length() - 4) + suffix); } + + @InputFile + public File getInputJar() { + return inputJar; + } + + public GenerateSourcesTask setInputJar(File inputJar) { + this.inputJar = inputJar; + return this; + } } diff --git a/src/main/java/net/fabricmc/loom/task/LoomTasks.java b/src/main/java/net/fabricmc/loom/task/LoomTasks.java index 198f92e6..1b1de6a7 100644 --- a/src/main/java/net/fabricmc/loom/task/LoomTasks.java +++ b/src/main/java/net/fabricmc/loom/task/LoomTasks.java @@ -24,6 +24,8 @@ package net.fabricmc.loom.task; +import java.io.File; + import com.google.common.base.Preconditions; import org.gradle.api.Project; import org.gradle.api.tasks.TaskContainer; @@ -31,6 +33,7 @@ import org.gradle.api.tasks.TaskContainer; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.configuration.ide.RunConfigSettings; +import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler; public final class LoomTasks { @@ -110,10 +113,30 @@ public final class LoomTasks { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); project.afterEvaluate(p -> { + MappingsProvider mappingsProvider = extension.getMappingsProvider(); + File inputJar = mappingsProvider.mappedProvider.getMappedJar(); + + if (mappingsProvider.hasUnpickDefinitions()) { + File outputJar = mappingsProvider.mappedProvider.getUnpickedJar(); + + tasks.register("unpickJar", UnpickJarTask.class, unpickJarTask -> { + unpickJarTask.setUnpickDefinition(mappingsProvider.getUnpickDefinitionsFile()); + unpickJarTask.setInputJar(mappingsProvider.mappedProvider.getMappedJar()); + unpickJarTask.setOutputJar(outputJar); + }); + + inputJar = outputJar; + } + for (LoomDecompiler decompiler : extension.getDecompilers()) { String taskName = decompiler instanceof FabricFernFlowerDecompiler ? "genSources" : "genSourcesWith" + decompiler.name(); // decompiler will be passed to the constructor of GenerateSourcesTask - tasks.register(taskName, GenerateSourcesTask.class, decompiler); + GenerateSourcesTask generateSourcesTask = tasks.register(taskName, GenerateSourcesTask.class, decompiler).get(); + generateSourcesTask.setInputJar(inputJar); + + if (mappingsProvider.hasUnpickDefinitions()) { + generateSourcesTask.dependsOn(tasks.getByName("unpickJar")); + } } }); } diff --git a/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java b/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java new file mode 100644 index 00000000..e27d2ff2 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java @@ -0,0 +1,126 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.task; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; + +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.JavaExec; +import org.gradle.api.tasks.OutputFile; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.LaunchProvider; +import net.fabricmc.loom.util.Constants; + +public class UnpickJarTask extends JavaExec { + File inputJar; + File unpickDefinition; + + File outputJar; + + public UnpickJarTask() { + getOutputs().upToDateWhen(e -> false); + classpath(getProject().getConfigurations().getByName(Constants.Configurations.UNPICK_CLASSPATH)); + setMain("daomephsta.unpick.cli.Main"); + } + + @Override + public void exec() { + fileArg(getInputJar(), getOutputJar(), getUnpickDefinition()); + fileArg(getConstantJar()); + + // Classpath + fileArg(getExtension().getMinecraftMappedProvider().getMappedJar()); + fileArg(getMinecraftDependencies()); + + writeUnpickLogConfig(); + systemProperty("java.util.logging.config.file", getExtension().getUnpickLoggingConfigFile().getAbsolutePath()); + + super.exec(); + } + + private void writeUnpickLogConfig() { + try (InputStream is = LaunchProvider.class.getClassLoader().getResourceAsStream("unpick-logging.properties")) { + Files.deleteIfExists(getExtension().getUnpickLoggingConfigFile().toPath()); + Files.copy(is, getExtension().getUnpickLoggingConfigFile().toPath()); + } catch (IOException e) { + throw new RuntimeException("Failed to copy unpick logging config", e); + } + } + + private File[] getMinecraftDependencies() { + return getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES) + .resolve().toArray(new File[0]); + } + + private File getConstantJar() { + return getProject().getConfigurations().getByName(Constants.Configurations.MAPPING_CONSTANTS).getSingleFile(); + } + + @InputFile + public File getInputJar() { + return inputJar; + } + + public UnpickJarTask setInputJar(File inputJar) { + this.inputJar = inputJar; + return this; + } + + @InputFile + public File getUnpickDefinition() { + return unpickDefinition; + } + + public UnpickJarTask setUnpickDefinition(File unpickDefinition) { + this.unpickDefinition = unpickDefinition; + return this; + } + + @OutputFile + public File getOutputJar() { + return outputJar; + } + + public UnpickJarTask setOutputJar(File outputJar) { + this.outputJar = outputJar; + return this; + } + + private void fileArg(File... files) { + for (File file : files) { + args(file.getAbsolutePath()); + } + } + + @Internal + protected LoomGradleExtension getExtension() { + return getProject().getExtensions().getByType(LoomGradleExtension.class); + } +} diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index fb4ac480..beff10df 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -79,6 +79,8 @@ public class Constants { public static final String LOOM_DEVELOPMENT_DEPENDENCIES = "loomDevelopmentDependencies"; @Deprecated // Not to be used in gradle 7+ public static final String COMPILE = "compile"; + public static final String MAPPING_CONSTANTS = "mappingsConstants"; + public static final String UNPICK_CLASSPATH = "unpick"; private Configurations() { } diff --git a/src/main/resources/unpick-logging.properties b/src/main/resources/unpick-logging.properties new file mode 100644 index 00000000..98bb581e --- /dev/null +++ b/src/main/resources/unpick-logging.properties @@ -0,0 +1 @@ +unpick.level=WARNING diff --git a/src/test/groovy/net/fabricmc/loom/UnpickTest.groovy b/src/test/groovy/net/fabricmc/loom/UnpickTest.groovy new file mode 100644 index 00000000..ee228b8a --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/UnpickTest.groovy @@ -0,0 +1,62 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ProjectTestTrait +import org.zeroturnaround.zip.ZipUtil +import spock.lang.Specification + +import java.nio.charset.StandardCharsets + +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class UnpickTest extends Specification implements ProjectTestTrait { + static final String MAPPINGS = "21w11a-mapped-net.fabricmc.yarn-21w11a+build.22-v2" + + @Override + String name() { + "unpick" + } + + def "unpick decompile"() { + when: + def result = create("genSources") + then: + result.task(":genSources").outcome == SUCCESS + getClassSource("net/minecraft/block/CakeBlock.java").contains("SetBlockStateFlags.PROPAGATE_CHANGE | SetBlockStateFlags.NOTIFY_LISTENERS") + } + + def "unpick build"() { + when: + def result = create("build") + then: + result.task(":build").outcome == SUCCESS + } + + String getClassSource(String classname, String mappings = MAPPINGS) { + File sourcesJar = getGeneratedSources(mappings) + return new String(ZipUtil.unpackEntry(sourcesJar, classname), StandardCharsets.UTF_8) + } +} diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index e66879f0..e5cfa9a9 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -29,6 +29,7 @@ import org.gradle.testkit.runner.GradleRunner trait ProjectTestTrait { static File gradleHome = File.createTempDir() + final static String DEFAULT_GRADLE = "6.8.3" File testProjectDir = File.createTempDir() @@ -71,7 +72,7 @@ trait ProjectTestTrait { gradleHome.deleteDir() } - BuildResult create(String task, String gradleVersion = "6.8.3") { + BuildResult create(String task, String gradleVersion = DEFAULT_GRADLE) { System.setProperty("fabric.loom.test", "true") GradleRunner.create() @@ -106,4 +107,8 @@ trait ProjectTestTrait { return file } + + File getGeneratedSources(String mappings, String gradleVersion = DEFAULT_GRADLE) { + return new File(gradleHomeDirectory(gradleVersion), "caches/fabric-loom/${mappings}/minecraft-${mappings}-sources.jar") + } } \ No newline at end of file diff --git a/src/test/resources/projects/unpick/build.gradle b/src/test/resources/projects/unpick/build.gradle new file mode 100644 index 00000000..2b728507 --- /dev/null +++ b/src/test/resources/projects/unpick/build.gradle @@ -0,0 +1,9 @@ +plugins { + id 'fabric-loom' +} + +dependencies { + minecraft "com.mojang:minecraft:21w11a" + mappings "net.fabricmc:yarn:21w11a+build.22:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.2" +} diff --git a/src/test/resources/projects/unpick/src/main/java/ExampleMod.java b/src/test/resources/projects/unpick/src/main/java/ExampleMod.java new file mode 100644 index 00000000..0ad290f7 --- /dev/null +++ b/src/test/resources/projects/unpick/src/main/java/ExampleMod.java @@ -0,0 +1,10 @@ +import net.fabricmc.api.ModInitializer; +import net.fabricmc.yarn.constants.SetBlockStateFlags; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // Just enough to make sure it can compile against the flags + System.out.println(SetBlockStateFlags.PROPAGATE_CHANGE); + } +} \ No newline at end of file From ff6701e8177b6eced8508332d423b6048c52c466 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Thu, 25 Mar 2021 22:57:28 +0000 Subject: [PATCH 16/24] Add basic groovy code style validation. IDK how well this would work on a gradle script but might be interesting to try on yarn or something. --- .gitignore | 3 +- build.gradle | 6 ++ codenarc.groovy | 66 +++++++++++++++++++ .../fabricmc/loom/AccessWidenerTest.groovy | 2 +- .../loom/util/ProjectTestTrait.groovy | 2 +- 5 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 codenarc.groovy diff --git a/.gitignore b/.gitignore index af5b65fc..c316a770 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ !/README.md !/settings.gradle !/Jenkinsfile -!/checkstyle.xml \ No newline at end of file +!/checkstyle.xml +!/codenarc.groovy \ No newline at end of file diff --git a/build.gradle b/build.gradle index f1d8e6bb..1458eac6 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,7 @@ plugins { id 'groovy' id 'checkstyle' id 'jacoco' + id 'codenarc' id "org.cadixdev.licenser" version "0.5.0" } @@ -110,6 +111,11 @@ checkstyle { toolVersion = '8.39' } +codenarc { + toolVersion = "2.0.0" + configFile = file("codenarc.groovy") +} + gradlePlugin { plugins { fabricLoom { diff --git a/codenarc.groovy b/codenarc.groovy new file mode 100644 index 00000000..9f15eb60 --- /dev/null +++ b/codenarc.groovy @@ -0,0 +1,66 @@ +ruleset { + UnnecessarySemicolon + BlockEndsWithBlankLine + BlockStartsWithBlankLine + ConsecutiveBlankLines + MissingBlankLineAfterImports + MissingBlankLineAfterPackage + + // Braces + BracesForClass + BracesForForLoop + BracesForIfElse + BracesForMethod + BracesForTryCatchFinally + + // Spaces + SpaceAfterCatch + SpaceAfterComma + SpaceAfterClosingBrace + SpaceAfterFor + SpaceAfterIf + SpaceAfterOpeningBrace + SpaceAfterSemicolon + SpaceAfterSwitch + SpaceAfterWhile + SpaceAroundClosureArrow + SpaceAroundMapEntryColon + SpaceAroundOperator + SpaceBeforeClosingBrace + SpaceBeforeOpeningBrace + TrailingWhitespace + + // Groovyism - See: https://codenarc.org/codenarc-rules-groovyism.html + ClosureAsLastMethodParameter + ExplicitArrayListInstantiation + ExplicitCallToAndMethod + ExplicitCallToCompareToMethod + ExplicitCallToDivMethod + ExplicitCallToEqualsMethod + ExplicitCallToGetAtMethod + ExplicitCallToLeftShiftMethod + ExplicitCallToMinusMethod + ExplicitCallToMultiplyMethod + ExplicitCallToModMethod + ExplicitCallToOrMethod + ExplicitCallToPlusMethod + ExplicitCallToPowerMethod + ExplicitCallToRightShiftMethod + ExplicitCallToXorMethod + ExplicitHashMapInstantiation + ExplicitLinkedHashMapInstantiation + ExplicitHashSetInstantiation + ExplicitLinkedListInstantiation + ExplicitStackInstantiation + ExplicitTreeSetInstantiation + GetterMethodCouldBeProperty + GStringAsMapKey + GStringExpressionWithinString + CouldBeElvis + TernaryCouldBeElvis + FieldTypeRequired + MethodParameterTypeRequired + + //Misc + LongLiteralWithLowerCaseL +} diff --git a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy index de18a6f4..bb67a201 100644 --- a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy @@ -43,7 +43,7 @@ class AccessWidenerTest extends Specification implements ProjectTestTrait, Archi def result = create("build", gradle) then: result.task(":build").outcome == SUCCESS - getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r','') + getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r', '') where: gradle | _ '6.8.3' | _ diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index e5cfa9a9..fb323b6a 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -43,7 +43,7 @@ trait ProjectTestTrait { throw new FileNotFoundException("Failed to find project directory at:" + baseProjectDir.absolutePath) } - baseProjectDir.eachFileRecurse {file -> + baseProjectDir.eachFileRecurse { file -> if (file.isDirectory()) { return } From ed08e47aab209bd65070d8b83f632c9776e04164 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Thu, 25 Mar 2021 22:58:20 +0000 Subject: [PATCH 17/24] Record javadoc support. (#366) * Record javadoc support * Ensure we dont add JD twice --- .../fernflower/TinyJavadocProvider.java | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java index 15cf3bf8..07db43f1 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java @@ -36,6 +36,8 @@ import java.util.Map; import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructField; import org.jetbrains.java.decompiler.struct.StructMethod; +import org.jetbrains.java.decompiler.struct.StructRecordComponent; +import org.objectweb.asm.Opcodes; import net.fabricmc.fernflower.api.IFabricJavadocProvider; import net.fabricmc.mapping.tree.ClassDef; @@ -73,11 +75,63 @@ public class TinyJavadocProvider implements IFabricJavadocProvider { @Override public String getClassDoc(StructClass structClass) { ClassDef classDef = classes.get(structClass.qualifiedName); - return classDef != null ? classDef.getComment() : null; + + if (classDef == null) { + return null; + } + + if (!isRecord(structClass)) { + return classDef.getComment(); + } + + /** + * Handle the record component docs here. + * + * Record components are mapped via the field name, thus take the docs from the fields and display them on then class. + */ + List parts = new ArrayList<>(); + + if (classDef.getComment() != null) { + parts.add(classDef.getComment()); + } + + boolean addedParam = false; + + for (StructRecordComponent component : structClass.getRecordComponents()) { + // The component will always match the field name and descriptor + FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, component.getName(), component.getDescriptor())); + + if (fieldDef == null) { + continue; + } + + String comment = fieldDef.getComment(); + + if (comment != null) { + if (!addedParam && classDef.getComment() != null) { + //Add a blank line before components when the class has a comment + parts.add(""); + addedParam = true; + } + + parts.add(String.format("@param %s %s", fieldDef.getName(namespace), comment)); + } + } + + if (parts.isEmpty()) { + return null; + } + + return String.join("\n", parts); } @Override public String getFieldDoc(StructClass structClass, StructField structField) { + // None static fields in records are handled in the class javadoc. + if (isRecord(structClass) && !isStatic(structField)) { + return null; + } + FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, structField.getName(), structField.getDescriptor())); return fieldDef != null ? fieldDef.getComment() : null; } @@ -126,4 +180,12 @@ public class TinyJavadocProvider implements IFabricJavadocProvider { throw new RuntimeException("Failed to read mappings", e); } } + + public static boolean isRecord(StructClass structClass) { + return (structClass.getAccessFlags() & Opcodes.ACC_RECORD) != 0; + } + + public static boolean isStatic(StructField structField) { + return (structField.getAccessFlags() & Opcodes.ACC_STATIC) != 0; + } } From 71535fa75f7555a9ca663331eebcca6d0e5b465d Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 27 Mar 2021 20:26:10 +0000 Subject: [PATCH 18/24] Add MavenProjectTest (#372) --- build.gradle | 1 + .../net/fabricmc/loom/MavenProjectTest.groovy | 96 +++++++++++++++++++ .../loom/util/ArchiveAssertionsTrait.groovy | 2 +- .../loom/util/MockMavenServerTrait.groovy | 91 ++++++++++++++++++ .../loom/util/ProjectTestTrait.groovy | 11 ++- .../resources/projects/maven/build.gradle | 25 +++++ .../net/fabricmc/examplemod/ExampleMod.java | 12 +++ .../projects/mavenLibrary/build.gradle | 52 ++++++++++ .../projects/mavenLibrary/settings.gradle | 2 + .../java/net/fabricmc/example/ExampleLib.java | 13 +++ .../src/main/resources/fabric.mod.json | 4 + 11 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy create mode 100644 src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy create mode 100644 src/test/resources/projects/maven/build.gradle create mode 100644 src/test/resources/projects/maven/src/main/java/net/fabricmc/examplemod/ExampleMod.java create mode 100644 src/test/resources/projects/mavenLibrary/build.gradle create mode 100644 src/test/resources/projects/mavenLibrary/settings.gradle create mode 100644 src/test/resources/projects/mavenLibrary/src/main/java/net/fabricmc/example/ExampleLib.java create mode 100644 src/test/resources/projects/mavenLibrary/src/main/resources/fabric.mod.json diff --git a/build.gradle b/build.gradle index 1458eac6..e128c26d 100644 --- a/build.gradle +++ b/build.gradle @@ -78,6 +78,7 @@ dependencies { testImplementation('org.spockframework:spock-core:1.3-groovy-2.4') { exclude module: 'groovy-all' } + testImplementation 'io.javalin:javalin:3.13.4' compileOnly 'org.jetbrains:annotations:20.1.0' } diff --git a/src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy new file mode 100644 index 00000000..9c70591e --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy @@ -0,0 +1,96 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import net.fabricmc.loom.util.ArchiveAssertionsTrait +import net.fabricmc.loom.util.MockMavenServerTrait +import spock.lang.Specification +import spock.lang.Stepwise +import spock.lang.Unroll +import spock.util.environment.RestoreSystemProperties + +import static java.lang.System.setProperty +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +/** + * This tests publishing a range of versions and then tries to resolve and build against them + */ +@Stepwise +class MavenProjectTest extends Specification implements MockMavenServerTrait, ArchiveAssertionsTrait { + @RestoreSystemProperties + @Unroll + def "publish lib #version"() { + given: + setProperty('loom.test.version', version) + library = true + when: + def result = create("publish") + then: + result.task(":publish").outcome == SUCCESS + hasArchiveEntry("fabric-example-lib-${version}.jar", "net/fabricmc/example/ExampleLib.class") + where: + version | _ + '1.0.0' | _ + '1.1.0' | _ + '1.1.1' | _ + '1.2.0+meta' | _ + '2.0.0-SNAPSHOT' | _ + '2.0.0-SNAPSHOT' | _ // Publish this twice to give ourselves a bit of a challenge + 'master-SNAPSHOT' | _ + } + + @RestoreSystemProperties + @Unroll + def "resolve #version"() { + given: + setProperty('loom.test.resolve', "com.example:fabric-example-lib:${version}") + library = false + when: + def result = create("build") + then: + result.task(":build").outcome == SUCCESS + hasArchiveEntry("fabric-example-mod-1.0.0.jar", "net/fabricmc/examplemod/ExampleMod.class") + where: + version | _ + '1.0.0' | _ + '1.1.+' | _ + '1.2.0+meta' | _ + '2.0.0-SNAPSHOT' | _ + 'master-SNAPSHOT' | _ + '1.0.0:classifier' | _ + '1.1.+:classifier' | _ + '1.2.0+meta:classifier' | _ + '2.0.0-SNAPSHOT:classifier' | _ + 'master-SNAPSHOT:classifier' | _ + } + + // Set to true when to build and publish the mavenLibrary + private boolean library = false + + @Override + String name() { + library ? "mavenLibrary" : "maven" + } +} diff --git a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy index 88d4df11..5a7a74be 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy @@ -26,7 +26,7 @@ package net.fabricmc.loom.util import org.zeroturnaround.zip.ZipUtil -trait ArchiveAssertionsTrait extends ProjectTestTrait { +trait ArchiveAssertionsTrait { String getArchiveEntry(String name, String entry, String project = "") { def file = getOutputFile(name, project) diff --git a/src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy new file mode 100644 index 00000000..f7bfcb46 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy @@ -0,0 +1,91 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util + +import io.javalin.Javalin +import org.apache.commons.io.IOUtils + +trait MockMavenServerTrait extends ProjectTestTrait { + public final int mavenServerPort = 9876 + public final File testMavenDir = File.createTempDir() + private Javalin server + + @SuppressWarnings('unused') + def setupSpec() { + println "Maven server path: ${testMavenDir.absolutePath}" + + server = Javalin.create { config -> + config.enableDevLogging() + }.start(mavenServerPort) + + /** + * A very very basic maven server impl, DO NOT copy this and use in production as its not secure + */ + server.get("*") { ctx -> + println "GET: " + ctx.path() + File file = getMavenPath(ctx.path()) + + if (!file.exists()) { + ctx.status(404) + return + } + + ctx.result(file.bytes) + } + + server.put("*") { ctx -> + println "PUT: " + ctx.path() + File file = getMavenPath(ctx.path()) + file.parentFile.mkdirs() + + file.withOutputStream { + IOUtils.copy(ctx.bodyAsInputStream(), it) + } + } + } + + @SuppressWarnings('unused') + def setup() { + System.setProperty('loom.test.mavenPort', port()) + } + + @SuppressWarnings('unused') + def cleanupSpec() { + server.stop() + super.cleanupSpec() + } + + File getMavenDirectory() { + new File(testMavenDir, "maven") + } + + File getMavenPath(String path) { + new File(getMavenDirectory(), path) + } + + String port() { + "${mavenServerPort}" + } +} \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy index fb323b6a..76278f60 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy @@ -35,8 +35,9 @@ trait ProjectTestTrait { abstract String name() - @SuppressWarnings('unused') - def setup() { + def copyInputFiles() { + println "Project directory: ${testProjectDir}" + def baseProjectDir = new File("src/test/resources/projects/" + name()) if (!baseProjectDir.exists()) { @@ -51,6 +52,11 @@ trait ProjectTestTrait { def path = file.path.replace(baseProjectDir.path, "") File tempFile = new File(testProjectDir, path) + + if (tempFile.exists()) { + tempFile.delete() + } + tempFile.parentFile.mkdirs() tempFile << file.text } @@ -74,6 +80,7 @@ trait ProjectTestTrait { BuildResult create(String task, String gradleVersion = DEFAULT_GRADLE) { System.setProperty("fabric.loom.test", "true") + copyInputFiles() GradleRunner.create() .withProjectDir(testProjectDir) diff --git a/src/test/resources/projects/maven/build.gradle b/src/test/resources/projects/maven/build.gradle new file mode 100644 index 00000000..56930fcd --- /dev/null +++ b/src/test/resources/projects/maven/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +archivesBaseName = "fabric-example-mod" +version = "1.0.0" +group = "com.example" + +println archivesBaseName + +repositories { + maven { + url = "http://localhost:${System.getProperty("loom.test.mavenPort")}/" + allowInsecureProtocol = true + } +} + +dependencies { + minecraft "com.mojang:minecraft:1.16.5" + mappings "net.fabricmc:yarn:1.16.5+build.5:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.2" + + modImplementation System.getProperty("loom.test.resolve") +} \ No newline at end of file diff --git a/src/test/resources/projects/maven/src/main/java/net/fabricmc/examplemod/ExampleMod.java b/src/test/resources/projects/maven/src/main/java/net/fabricmc/examplemod/ExampleMod.java new file mode 100644 index 00000000..f9831e92 --- /dev/null +++ b/src/test/resources/projects/maven/src/main/java/net/fabricmc/examplemod/ExampleMod.java @@ -0,0 +1,12 @@ +package net.fabricmc.examplemod; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.example.ExampleLib; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // Lets make sure we can compile against the lib + ExampleLib.hello(); + } +} diff --git a/src/test/resources/projects/mavenLibrary/build.gradle b/src/test/resources/projects/mavenLibrary/build.gradle new file mode 100644 index 00000000..e0121c35 --- /dev/null +++ b/src/test/resources/projects/mavenLibrary/build.gradle @@ -0,0 +1,52 @@ +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +archivesBaseName = "fabric-example-lib" +version = System.getProperty("loom.test.version") +group = "com.example" + +println archivesBaseName + +dependencies { + minecraft "com.mojang:minecraft:1.16.5" + mappings "net.fabricmc:yarn:1.16.5+build.5:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.2" +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +java { + withSourcesJar() +} + +publishing { + publications { + mavenJava(MavenPublication) { + artifact(remapJar) { + builtBy remapJar + } + artifact(remapJar) { + builtBy remapJar + classifier "classifier" + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } + + repositories { + maven { + url "http://localhost:${System.getProperty("loom.test.mavenPort")}/" + allowInsecureProtocol = true + } + } +} diff --git a/src/test/resources/projects/mavenLibrary/settings.gradle b/src/test/resources/projects/mavenLibrary/settings.gradle new file mode 100644 index 00000000..fc4c0f72 --- /dev/null +++ b/src/test/resources/projects/mavenLibrary/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-lib" + diff --git a/src/test/resources/projects/mavenLibrary/src/main/java/net/fabricmc/example/ExampleLib.java b/src/test/resources/projects/mavenLibrary/src/main/java/net/fabricmc/example/ExampleLib.java new file mode 100644 index 00000000..e6ec1e65 --- /dev/null +++ b/src/test/resources/projects/mavenLibrary/src/main/java/net/fabricmc/example/ExampleLib.java @@ -0,0 +1,13 @@ +package net.fabricmc.example; + +import net.fabricmc.api.ModInitializer; + +public class ExampleLib implements ModInitializer { + @Override + public void onInitialize() { + } + + public static void hello() { + System.out.println("Hello Fabric world!"); + } +} diff --git a/src/test/resources/projects/mavenLibrary/src/main/resources/fabric.mod.json b/src/test/resources/projects/mavenLibrary/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..f527100e --- /dev/null +++ b/src/test/resources/projects/mavenLibrary/src/main/resources/fabric.mod.json @@ -0,0 +1,4 @@ +{ + "schemaVersion": 1, + "id": "modid" +} From 806dd1b84068a94facdb5a036f523c47526c93ab Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Mon, 29 Mar 2021 00:48:52 -0700 Subject: [PATCH 19/24] Fix name comparision in GroovyXmlUtil (#373) Nodes can also have groovy.xml.QNames, which need to be compared using their matches(Object) method. --- .../net/fabricmc/loom/util/GroovyXmlUtil.java | 17 ++++- .../fabricmc/loom/GroovyXmlUtilTest.groovy | 74 +++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy diff --git a/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java b/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java index c07fa64c..801cc118 100644 --- a/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java +++ b/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java @@ -29,13 +29,14 @@ import java.util.Optional; import java.util.stream.Stream; import groovy.util.Node; +import groovy.xml.QName; public final class GroovyXmlUtil { private GroovyXmlUtil() { } public static Node getOrCreateNode(Node parent, String name) { for (Object object : parent.children()) { - if (object instanceof Node && name.equals(((Node) object).name())) { + if (object instanceof Node && isSameName(((Node) object).name(), name)) { return (Node) object; } } @@ -45,7 +46,7 @@ public final class GroovyXmlUtil { public static Optional getNode(Node parent, String name) { for (Object object : parent.children()) { - if (object instanceof Node && name.equals(((Node) object).name())) { + if (object instanceof Node && isSameName(((Node) object).name(), name)) { return Optional.of((Node) object); } } @@ -53,6 +54,18 @@ public final class GroovyXmlUtil { return Optional.empty(); } + private static boolean isSameName(Object nodeName, String givenName) { + if (nodeName instanceof String) { + return nodeName.equals(givenName); + } + + if (nodeName instanceof QName) { + return ((QName) nodeName).matches(givenName); + } + + throw new UnsupportedOperationException("Cannot determine if " + nodeName.getClass() + " is the same as a String"); + } + public static Stream childrenNodesStream(Node node) { //noinspection unchecked return (Stream) (Stream) (((List) node.children()).stream().filter((i) -> i instanceof Node)); diff --git a/src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy b/src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy new file mode 100644 index 00000000..a379b727 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy @@ -0,0 +1,74 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom + +import groovy.xml.QName +import net.fabricmc.loom.util.GroovyXmlUtil +import spock.lang.Specification + +class GroovyXmlUtilTest extends Specification { + def "getOrCreateNode finds existing node"() { + when: + def xmlTree = new XmlParser().parseText(text) + def existingNode = xmlTree[innerName] + def actualNode = GroovyXmlUtil.getOrCreateNode(xmlTree, innerName) + + then: + existingNode.text() == actualNode.text() + + where: + innerName | text + "bar" | "inner content to ensure correct" + "dependencies" | "inner content to ensure correct" + } + + def "getOrCreateNode creates a node if needed"() { + when: + def xmlTree = new XmlParser().parseText(text) + def actualNode = GroovyXmlUtil.getOrCreateNode(xmlTree, innerName) + + then: + xmlTree[QName.valueOf(actualNode.name().toString())] != null + + where: + innerName | text + "bar" | "" + "dependencies" | "" + } + + def "getNode finds existing node"() { + when: + def xmlTree = new XmlParser().parseText(text) + def actualNode = GroovyXmlUtil.getNode(xmlTree, innerName) + + then: + actualNode.isPresent() + + where: + innerName | text + "bar" | "inner content to ensure correct" + "dependencies" | "inner content to ensure correct" + } +} From a3c90aca198e1612d44c7190c573ad173b6a47b0 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Wed, 31 Mar 2021 13:14:24 +0100 Subject: [PATCH 20/24] Ensure output is deleted before remapping the game. --- .../providers/minecraft/MinecraftMappedProvider.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java index 0a61f2ba..37297014 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java @@ -26,6 +26,7 @@ package net.fabricmc.loom.configuration.providers.minecraft; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Map; @@ -111,6 +112,8 @@ public class MinecraftMappedProvider extends DependencyProvider { getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")"); + Files.delete(output); + TinyRemapper remapper = getTinyRemapper(fromM, toM); try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) { From ce1946712166e2195b9c5023bb1e0477ac224829 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Wed, 31 Mar 2021 13:28:26 +0100 Subject: [PATCH 21/24] Fix last commit, oops --- .../providers/minecraft/MinecraftMappedProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java index 37297014..0032a177 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java @@ -112,7 +112,7 @@ public class MinecraftMappedProvider extends DependencyProvider { getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")"); - Files.delete(output); + Files.deleteIfExists(output); TinyRemapper remapper = getTinyRemapper(fromM, toM); From 153afc1418ef21fa3954a57c431c04ece9681fb4 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Fri, 2 Apr 2021 12:20:03 +0100 Subject: [PATCH 22/24] Reorganise tests (#378) --- .github/workflows/test-push.yml | 2 +- build.gradle | 14 +++++++------- .../intergration}/AccessWidenerTest.groovy | 12 ++++++------ .../{ => test/intergration}/DecompileTest.groovy | 12 ++++++------ .../loom/{ => test/intergration}/KotlinTest.groovy | 10 +++++----- .../intergration}/LegacyProjectTest.groovy | 6 +++--- .../intergration}/MavenProjectTest.groovy | 6 +++--- .../intergration}/MojangMappingsProjectTest.groovy | 10 +++++----- .../intergration}/MultiProjectTest.groovy | 12 ++++++------ .../intergration}/ReproducibleBuildTest.groovy | 4 ++-- .../{ => test/intergration}/RunConfigTest.groovy | 4 ++-- .../intergration}/SimpleProjectTest.groovy | 10 +++++----- .../loom/{ => test/intergration}/UnpickTest.groovy | 4 ++-- .../loom/{ => test/unit}/GroovyXmlUtilTest.groovy | 2 +- .../{ => test}/util/ArchiveAssertionsTrait.groovy | 2 +- .../{ => test}/util/MockMavenServerTrait.groovy | 2 +- .../loom/{ => test}/util/ProjectTestTrait.groovy | 8 +++++--- 17 files changed, 61 insertions(+), 59 deletions(-) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/AccessWidenerTest.groovy (88%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/DecompileTest.groovy (83%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/KotlinTest.groovy (90%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/LegacyProjectTest.groovy (91%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/MavenProjectTest.groovy (95%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/MojangMappingsProjectTest.groovy (90%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/MultiProjectTest.groovy (89%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/ReproducibleBuildTest.groovy (96%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/RunConfigTest.groovy (94%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/SimpleProjectTest.groovy (91%) rename src/test/groovy/net/fabricmc/loom/{ => test/intergration}/UnpickTest.groovy (95%) rename src/test/groovy/net/fabricmc/loom/{ => test/unit}/GroovyXmlUtilTest.groovy (98%) rename src/test/groovy/net/fabricmc/loom/{ => test}/util/ArchiveAssertionsTrait.groovy (97%) rename src/test/groovy/net/fabricmc/loom/{ => test}/util/MockMavenServerTrait.groovy (98%) rename src/test/groovy/net/fabricmc/loom/{ => test}/util/ProjectTestTrait.groovy (95%) diff --git a/.github/workflows/test-push.yml b/.github/workflows/test-push.yml index 5b1aa687..93cfb7ab 100644 --- a/.github/workflows/test-push.yml +++ b/.github/workflows/test-push.yml @@ -61,7 +61,7 @@ jobs: steps: - uses: actions/checkout@v2 - - run: gradle test --tests *${{ matrix.test }} --stacktrace + - run: gradle test --tests ${{ matrix.test }} --stacktrace env: TEST_WARNING_MODE: fail diff --git a/build.gradle b/build.gradle index e128c26d..7b7f8316 100644 --- a/build.gradle +++ b/build.gradle @@ -211,21 +211,21 @@ publishing { task writeActionsTestMatrix() { doLast { def testMatrix = [] - file('src/test/groovy/net/fabricmc/loom').eachFile { + file('src/test/groovy/net/fabricmc/loom/test/intergration').eachFile { if (it.name.endsWith("Test.groovy")) { - if (it.text.contains("@Ignore")) { - // A quick hack to disable currently broken tests. - return - } - if (it.name.endsWith("ReproducibleBuildTest.groovy")) { // This test gets a special case to run across all os's return } - testMatrix.add(it.name.replace(".groovy", "")) + def className = it.name.replace(".groovy", "") + testMatrix.add("net.fabricmc.loom.test.intergration.${className}") } } + + // Run all the unit tests togeather + testMatrix.add("net.fabricmc.loom.test.unit.*") + def json = groovy.json.JsonOutput.toJson(testMatrix) def output = file("build/test_matrix.json") output.parentFile.mkdir() diff --git a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/AccessWidenerTest.groovy similarity index 88% rename from src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/AccessWidenerTest.groovy index bb67a201..0cde47a5 100644 --- a/src/test/groovy/net/fabricmc/loom/AccessWidenerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/AccessWidenerTest.groovy @@ -22,10 +22,10 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ArchiveAssertionsTrait -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ArchiveAssertionsTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -45,9 +45,9 @@ class AccessWidenerTest extends Specification implements ProjectTestTrait, Archi result.task(":build").outcome == SUCCESS getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r', '') where: - gradle | _ - '6.8.3' | _ - '7.0-rc-1' | _ + gradle | _ + DEFAULT_GRADLE | _ + PRE_RELEASE_GRADLE | _ } String expected() { diff --git a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/DecompileTest.groovy similarity index 83% rename from src/test/groovy/net/fabricmc/loom/DecompileTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/DecompileTest.groovy index 47ec05b9..4e4c182a 100644 --- a/src/test/groovy/net/fabricmc/loom/DecompileTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/DecompileTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -46,9 +46,9 @@ class DecompileTest extends Specification implements ProjectTestTrait { where: decompiler | task | gradle - 'fernflower' | "genSources" | "6.8.3" - 'fernflower' | "genSources" | "4.9" - 'fernflower' | "genSources" | "7.0-rc-1" - 'cfr' | "genSourcesWithExperimentalCfr" | "6.8.3" + 'fernflower' | "genSources" | DEFAULT_GRADLE + 'fernflower' | "genSources" | LEGACY_GRADLE + 'fernflower' | "genSources" | PRE_RELEASE_GRADLE + 'cfr' | "genSourcesWithExperimentalCfr" | DEFAULT_GRADLE } } diff --git a/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/KotlinTest.groovy similarity index 90% rename from src/test/groovy/net/fabricmc/loom/KotlinTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/KotlinTest.groovy index d9a07847..a2d2ec03 100644 --- a/src/test/groovy/net/fabricmc/loom/KotlinTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/KotlinTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -43,8 +43,8 @@ class KotlinTest extends Specification implements ProjectTestTrait { then: result.task(":build").outcome == SUCCESS where: - gradle | _ - '6.8.3' | _ - '7.0-rc-1' | _ + gradle | _ + DEFAULT_GRADLE | _ + PRE_RELEASE_GRADLE | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/LegacyProjectTest.groovy similarity index 91% rename from src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/LegacyProjectTest.groovy index 8d837a69..6187f02e 100644 --- a/src/test/groovy/net/fabricmc/loom/LegacyProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/LegacyProjectTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -40,7 +40,7 @@ class LegacyProjectTest extends Specification implements ProjectTestTrait { @Unroll def "build"() { when: - def result = create("build", "4.9") + def result = create("build", LEGACY_GRADLE) then: result.task(":build").outcome == SUCCESS } diff --git a/src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy similarity index 95% rename from src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy index 9c70591e..3e511dd4 100644 --- a/src/test/groovy/net/fabricmc/loom/MavenProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy @@ -22,10 +22,10 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ArchiveAssertionsTrait -import net.fabricmc.loom.util.MockMavenServerTrait +import net.fabricmc.loom.test.util.ArchiveAssertionsTrait +import net.fabricmc.loom.test.util.MockMavenServerTrait import spock.lang.Specification import spock.lang.Stepwise import spock.lang.Unroll diff --git a/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/MojangMappingsProjectTest.groovy similarity index 90% rename from src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/MojangMappingsProjectTest.groovy index 1a2c303f..a98fb851 100644 --- a/src/test/groovy/net/fabricmc/loom/MojangMappingsProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/MojangMappingsProjectTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -43,8 +43,8 @@ class MojangMappingsProjectTest extends Specification implements ProjectTestTrai then: result.task(":build").outcome == SUCCESS where: - gradle | _ - '6.8.3' | _ - '7.0-rc-1' | _ + gradle | _ + DEFAULT_GRADLE | _ + PRE_RELEASE_GRADLE | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/MultiProjectTest.groovy similarity index 89% rename from src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/MultiProjectTest.groovy index 15bb017b..05317dcc 100644 --- a/src/test/groovy/net/fabricmc/loom/MultiProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/MultiProjectTest.groovy @@ -22,10 +22,10 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ArchiveAssertionsTrait -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ArchiveAssertionsTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -54,8 +54,8 @@ class MultiProjectTest extends Specification implements ProjectTestTrait, Archiv hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar") where: - gradle | _ - '6.8.3' | _ - '7.0-rc-1' | _ + gradle | _ + DEFAULT_GRADLE | _ + PRE_RELEASE_GRADLE | _ } } diff --git a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/ReproducibleBuildTest.groovy similarity index 96% rename from src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/ReproducibleBuildTest.groovy index 0d1ba1b5..8bcac7b6 100644 --- a/src/test/groovy/net/fabricmc/loom/ReproducibleBuildTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/ReproducibleBuildTest.groovy @@ -22,12 +22,12 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration import com.google.common.hash.HashCode import com.google.common.hash.Hashing import com.google.common.io.Files -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll diff --git a/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/RunConfigTest.groovy similarity index 94% rename from src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/RunConfigTest.groovy index 96619f5f..6ffb1130 100644 --- a/src/test/groovy/net/fabricmc/loom/RunConfigTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/RunConfigTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll diff --git a/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/SimpleProjectTest.groovy similarity index 91% rename from src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/SimpleProjectTest.groovy index f4993561..8be25043 100644 --- a/src/test/groovy/net/fabricmc/loom/SimpleProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/SimpleProjectTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import spock.lang.Specification import spock.lang.Unroll @@ -43,9 +43,9 @@ class SimpleProjectTest extends Specification implements ProjectTestTrait { then: result.task(":build").outcome == SUCCESS where: - gradle | _ - '6.8.3' | _ - '7.0-rc-1' | _ + gradle | _ + DEFAULT_GRADLE | _ + PRE_RELEASE_GRADLE | _ } @Unroll diff --git a/src/test/groovy/net/fabricmc/loom/UnpickTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy similarity index 95% rename from src/test/groovy/net/fabricmc/loom/UnpickTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy index ee228b8a..73547e22 100644 --- a/src/test/groovy/net/fabricmc/loom/UnpickTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy @@ -22,9 +22,9 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.intergration -import net.fabricmc.loom.util.ProjectTestTrait +import net.fabricmc.loom.test.util.ProjectTestTrait import org.zeroturnaround.zip.ZipUtil import spock.lang.Specification diff --git a/src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/GroovyXmlUtilTest.groovy similarity index 98% rename from src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy rename to src/test/groovy/net/fabricmc/loom/test/unit/GroovyXmlUtilTest.groovy index a379b727..4d6353a9 100644 --- a/src/test/groovy/net/fabricmc/loom/GroovyXmlUtilTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/GroovyXmlUtilTest.groovy @@ -22,7 +22,7 @@ * SOFTWARE. */ -package net.fabricmc.loom +package net.fabricmc.loom.test.unit import groovy.xml.QName import net.fabricmc.loom.util.GroovyXmlUtil diff --git a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/ArchiveAssertionsTrait.groovy similarity index 97% rename from src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy rename to src/test/groovy/net/fabricmc/loom/test/util/ArchiveAssertionsTrait.groovy index 5a7a74be..fa4492fc 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ArchiveAssertionsTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/ArchiveAssertionsTrait.groovy @@ -22,7 +22,7 @@ * SOFTWARE. */ -package net.fabricmc.loom.util +package net.fabricmc.loom.test.util import org.zeroturnaround.zip.ZipUtil diff --git a/src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy similarity index 98% rename from src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy rename to src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy index f7bfcb46..604c1faa 100644 --- a/src/test/groovy/net/fabricmc/loom/util/MockMavenServerTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/MockMavenServerTrait.groovy @@ -22,7 +22,7 @@ * SOFTWARE. */ -package net.fabricmc.loom.util +package net.fabricmc.loom.test.util import io.javalin.Javalin import org.apache.commons.io.IOUtils diff --git a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy similarity index 95% rename from src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy rename to src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy index 76278f60..619973e2 100644 --- a/src/test/groovy/net/fabricmc/loom/util/ProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy @@ -22,15 +22,17 @@ * SOFTWARE. */ -package net.fabricmc.loom.util +package net.fabricmc.loom.test.util import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner trait ProjectTestTrait { - static File gradleHome = File.createTempDir() + final static String LEGACY_GRADLE = "4.9" final static String DEFAULT_GRADLE = "6.8.3" + final static String PRE_RELEASE_GRADLE = "7.0-rc-2" + static File gradleHome = File.createTempDir() File testProjectDir = File.createTempDir() abstract String name() @@ -93,7 +95,7 @@ trait ProjectTestTrait { } String warningMode(String gradleVersion) { - if (gradleVersion == "4.9") { + if (gradleVersion == LEGACY_GRADLE) { return "all" } From 93afc7574d01e260e4219d8c8a17c0880042adf7 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Fri, 2 Apr 2021 14:44:18 +0100 Subject: [PATCH 23/24] Update UnpickTest to latest snapshot. This ensures that constants included in the mc jar can be used. --- .../net/fabricmc/loom/test/intergration/UnpickTest.groovy | 4 ++-- src/test/resources/projects/unpick/build.gradle | 6 +++--- .../resources/projects/unpick/src/main/java/ExampleMod.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy index 73547e22..da1de2de 100644 --- a/src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/UnpickTest.groovy @@ -33,7 +33,7 @@ import java.nio.charset.StandardCharsets import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class UnpickTest extends Specification implements ProjectTestTrait { - static final String MAPPINGS = "21w11a-mapped-net.fabricmc.yarn-21w11a+build.22-v2" + static final String MAPPINGS = "21w13a-mapped-net.fabricmc.yarn-21w13a+build.30-v2" @Override String name() { @@ -45,7 +45,7 @@ class UnpickTest extends Specification implements ProjectTestTrait { def result = create("genSources") then: result.task(":genSources").outcome == SUCCESS - getClassSource("net/minecraft/block/CakeBlock.java").contains("SetBlockStateFlags.PROPAGATE_CHANGE | SetBlockStateFlags.NOTIFY_LISTENERS") + getClassSource("net/minecraft/block/CakeBlock.java").contains("Block.DEFAULT_SET_BLOCK_STATE_FLAG") } def "unpick build"() { diff --git a/src/test/resources/projects/unpick/build.gradle b/src/test/resources/projects/unpick/build.gradle index 2b728507..4b79a1b0 100644 --- a/src/test/resources/projects/unpick/build.gradle +++ b/src/test/resources/projects/unpick/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - minecraft "com.mojang:minecraft:21w11a" - mappings "net.fabricmc:yarn:21w11a+build.22:v2" - modImplementation "net.fabricmc:fabric-loader:0.11.2" + minecraft "com.mojang:minecraft:21w13a" + mappings "net.fabricmc:yarn:21w13a+build.30:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.3" } diff --git a/src/test/resources/projects/unpick/src/main/java/ExampleMod.java b/src/test/resources/projects/unpick/src/main/java/ExampleMod.java index 0ad290f7..567dd53f 100644 --- a/src/test/resources/projects/unpick/src/main/java/ExampleMod.java +++ b/src/test/resources/projects/unpick/src/main/java/ExampleMod.java @@ -1,10 +1,10 @@ import net.fabricmc.api.ModInitializer; -import net.fabricmc.yarn.constants.SetBlockStateFlags; +import net.fabricmc.yarn.constants.CatTypes; public class ExampleMod implements ModInitializer { @Override public void onInitialize() { // Just enough to make sure it can compile against the flags - System.out.println(SetBlockStateFlags.PROPAGATE_CHANGE); + System.out.println(CatTypes.TABBY); } } \ No newline at end of file From 98731532d57d31e3084ef932cce2435d872772c2 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Fri, 2 Apr 2021 19:30:43 +0100 Subject: [PATCH 24/24] Support Groovy 3's QName in GroovyXmlUtil (#379) --- build.gradle | 3 ++ .../net/fabricmc/loom/util/GroovyXmlUtil.java | 12 +++++ .../test/intergration/MavenProjectTest.groovy | 48 ++++++++++--------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/build.gradle b/build.gradle index 7b7f8316..7e1216a4 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,9 @@ repositories { dependencies { implementation gradleApi() + // Compile against groovy 3 to aid with gradle 7 support. Remove when updating to gradle 7 + compileOnly 'org.codehaus.groovy:groovy-all:3.0.7' + // libraries implementation ('commons-io:commons-io:2.8.0') implementation ('org.zeroturnaround:zt-zip:1.14') diff --git a/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java b/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java index 801cc118..4e587e10 100644 --- a/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java +++ b/src/main/java/net/fabricmc/loom/util/GroovyXmlUtil.java @@ -31,6 +31,8 @@ import java.util.stream.Stream; import groovy.util.Node; import groovy.xml.QName; +import net.fabricmc.loom.util.gradle.GradleSupport; + public final class GroovyXmlUtil { private GroovyXmlUtil() { } @@ -63,9 +65,19 @@ public final class GroovyXmlUtil { return ((QName) nodeName).matches(givenName); } + // New groovy 3 (gradle 7) class + if (GradleSupport.IS_GRADLE_7_OR_NEWER && nodeName.getClass().getName().equals("groovy.namespace.QName")) { + return isSameNameGroovy3(nodeName, givenName); + } + throw new UnsupportedOperationException("Cannot determine if " + nodeName.getClass() + " is the same as a String"); } + // TODO Move out of its own method when requiring gradle 7 + private static boolean isSameNameGroovy3(Object nodeName, String givenName) { + return ((groovy.namespace.QName) nodeName).matches(givenName); + } + public static Stream childrenNodesStream(Node node) { //noinspection unchecked return (Stream) (Stream) (((List) node.children()).stream().filter((i) -> i instanceof Node)); diff --git a/src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy index 3e511dd4..6358b7e4 100644 --- a/src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/intergration/MavenProjectTest.groovy @@ -41,49 +41,51 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class MavenProjectTest extends Specification implements MockMavenServerTrait, ArchiveAssertionsTrait { @RestoreSystemProperties @Unroll - def "publish lib #version"() { + def "publish lib #version #gradle"() { given: setProperty('loom.test.version', version) library = true when: - def result = create("publish") + def result = create("publish", gradle) then: result.task(":publish").outcome == SUCCESS hasArchiveEntry("fabric-example-lib-${version}.jar", "net/fabricmc/example/ExampleLib.class") where: - version | _ - '1.0.0' | _ - '1.1.0' | _ - '1.1.1' | _ - '1.2.0+meta' | _ - '2.0.0-SNAPSHOT' | _ - '2.0.0-SNAPSHOT' | _ // Publish this twice to give ourselves a bit of a challenge - 'master-SNAPSHOT' | _ + version | gradle + '1.0.0' | DEFAULT_GRADLE + '1.0.0' | PRE_RELEASE_GRADLE + '1.1.0' | DEFAULT_GRADLE + '1.1.1' | DEFAULT_GRADLE + '1.2.0+meta' | DEFAULT_GRADLE + '2.0.0-SNAPSHOT' | DEFAULT_GRADLE + '2.0.0-SNAPSHOT' | DEFAULT_GRADLE // Publish this twice to give ourselves a bit of a challenge + 'master-SNAPSHOT' | DEFAULT_GRADLE } @RestoreSystemProperties @Unroll - def "resolve #version"() { + def "resolve #version #gradle"() { given: setProperty('loom.test.resolve', "com.example:fabric-example-lib:${version}") library = false when: - def result = create("build") + def result = create("build", gradle) then: result.task(":build").outcome == SUCCESS hasArchiveEntry("fabric-example-mod-1.0.0.jar", "net/fabricmc/examplemod/ExampleMod.class") where: - version | _ - '1.0.0' | _ - '1.1.+' | _ - '1.2.0+meta' | _ - '2.0.0-SNAPSHOT' | _ - 'master-SNAPSHOT' | _ - '1.0.0:classifier' | _ - '1.1.+:classifier' | _ - '1.2.0+meta:classifier' | _ - '2.0.0-SNAPSHOT:classifier' | _ - 'master-SNAPSHOT:classifier' | _ + version | gradle + '1.0.0' | DEFAULT_GRADLE + '1.0.0' | PRE_RELEASE_GRADLE + '1.1.+' | DEFAULT_GRADLE + '1.2.0+meta' | DEFAULT_GRADLE + '2.0.0-SNAPSHOT' | DEFAULT_GRADLE + 'master-SNAPSHOT' | DEFAULT_GRADLE + '1.0.0:classifier' | DEFAULT_GRADLE + '1.1.+:classifier' | DEFAULT_GRADLE + '1.2.0+meta:classifier' | DEFAULT_GRADLE + '2.0.0-SNAPSHOT:classifier' | DEFAULT_GRADLE + 'master-SNAPSHOT:classifier' | DEFAULT_GRADLE } // Set to true when to build and publish the mavenLibrary