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 0000000..6330b61 --- /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 0000000..566002d --- /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 c88c448..dbca51e 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 0000000..badb265 --- /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 0000000..3ddbae3 --- /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 4fd1a0a..e6e7787 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 0000000..2fb2ae7 --- /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 0000000..7534c27 --- /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 10d5257..2c0a3d6 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 0000000..1dfc43b --- /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 3716aff..2638135 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 7530ff1..ecde393 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 0000000..38e811d --- /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" +}