From d9b8c90b5fdd3e25a73965379e67cb2bacf54f70 Mon Sep 17 00:00:00 2001 From: Adrian Siekierka Date: Sat, 22 Dec 2018 15:29:46 +0100 Subject: [PATCH] working source code remapping for mod dependencies --- .../loom/providers/MappingsProvider.java | 7 +- .../providers/MinecraftMappedProvider.java | 3 +- .../loom/providers/MinecraftProvider.java | 3 +- .../loom/providers/ModRemapperProvider.java | 30 +++++-- .../loom/util/DependencyProvider.java | 86 ++++++++++++++++--- .../loom/util/LoomDependencyManager.java | 10 ++- .../fabricmc/loom/util/SourceRemapper.java | 13 ++- 7 files changed, 129 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/providers/MappingsProvider.java b/src/main/java/net/fabricmc/loom/providers/MappingsProvider.java index 989ee34..ec4cf33 100644 --- a/src/main/java/net/fabricmc/loom/providers/MappingsProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MappingsProvider.java @@ -35,6 +35,7 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.function.Consumer; //TODO fix local mappings //TODO possibly use maven for mappings, can fix above at the same time @@ -52,13 +53,13 @@ public class MappingsProvider extends DependencyProvider { public File MAPPINGS_MIXIN_EXPORT; @Override - public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception { + public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class); project.getLogger().lifecycle(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")"); String version = dependency.getResolvedVersion(); - File mappingsJar = dependency.resolveFile(); + File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find dependency " + dependency)); this.mappingsName = dependency.getDependency().getName(); this.minecraftVersion = version.substring(0, version.lastIndexOf('.')); @@ -95,7 +96,7 @@ public class MappingsProvider extends DependencyProvider { mappedProvider = new MinecraftMappedProvider(); mappedProvider.initFiles(project, minecraftProvider, this); - mappedProvider.provide(dependency, project, extension); + mappedProvider.provide(dependency, project, extension, postPopulationScheduler); } public void initFiles(Project project) { diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java index 771eed2..082f2d3 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftMappedProvider.java @@ -32,6 +32,7 @@ import org.gradle.api.Project; import java.io.File; import java.util.Collection; +import java.util.function.Consumer; public class MinecraftMappedProvider extends DependencyProvider { public File MINECRAFT_MAPPED_JAR; @@ -40,7 +41,7 @@ public class MinecraftMappedProvider extends DependencyProvider { private MinecraftProvider minecraftProvider; @Override - public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception { + public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { throw new RuntimeException("mappings file not found"); } diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java index c5c6d75..7295abf 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java @@ -38,6 +38,7 @@ import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Optional; +import java.util.function.Consumer; public class MinecraftProvider extends DependencyProvider { @@ -55,7 +56,7 @@ public class MinecraftProvider extends DependencyProvider { Gson gson = new Gson(); @Override - public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception { + public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception { minecraftVersion = dependency.getDependency().getVersion(); initFiles(project); diff --git a/src/main/java/net/fabricmc/loom/providers/ModRemapperProvider.java b/src/main/java/net/fabricmc/loom/providers/ModRemapperProvider.java index 17b0a3a..ec2073c 100644 --- a/src/main/java/net/fabricmc/loom/providers/ModRemapperProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/ModRemapperProvider.java @@ -24,27 +24,33 @@ package net.fabricmc.loom.providers; +import com.google.common.io.Files; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.DependencyProvider; import net.fabricmc.loom.util.ModProcessor; +import net.fabricmc.loom.util.SourceRemapper; import org.gradle.api.Project; import java.io.File; +import java.io.IOException; +import java.util.Optional; +import java.util.function.Consumer; public class ModRemapperProvider extends DependencyProvider { @Override - public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) { - File input = dependency.resolveFile(); + public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) { + // Provide JAR + File input = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find dependency " + dependency)); - project.getLogger().lifecycle("Providing " + dependency.getDepString()); + project.getLogger().lifecycle(":providing " + dependency.getDepString()); MappingsProvider mappingsProvider = getDependencyManager().getProvider(MappingsProvider.class); String verSuffix = ".mapped." + mappingsProvider.mappingsName + "." + mappingsProvider.mappingsVersion; - String outputName = input.getName().substring(0, input.getName().length() - 4) + verSuffix + ".jar";//TODO use the hash of the input file or something? + String outputNamePrefix = input.getName().substring(0, input.getName().length() - 4) + verSuffix;//TODO use the hash of the input file or something? File modStore = extension.getRemappedModCache(); - File output = new File(modStore, outputName); + File output = new File(modStore, outputNamePrefix + ".jar"); if(output.exists()){ output.delete(); } @@ -58,6 +64,20 @@ public class ModRemapperProvider extends DependencyProvider { project.getDependencies().add("compile", project.getDependencies().module( dependency.getDepString() + verSuffix )); + + postPopulationScheduler.accept(() -> { + // Provide sources JAR, if present + Optional sourcesFile = dependency.resolveFile("sources"); + if (sourcesFile.isPresent()) { + project.getLogger().lifecycle(":providing " + dependency.getDepString() + " sources"); + + try { + SourceRemapper.remapSources(project, sourcesFile.get(), new File(modStore, outputNamePrefix + "-sources.jar"), true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); } @Override diff --git a/src/main/java/net/fabricmc/loom/util/DependencyProvider.java b/src/main/java/net/fabricmc/loom/util/DependencyProvider.java index 637d627..e6d4b01 100644 --- a/src/main/java/net/fabricmc/loom/util/DependencyProvider.java +++ b/src/main/java/net/fabricmc/loom/util/DependencyProvider.java @@ -24,20 +24,33 @@ package net.fabricmc.loom.util; +import com.google.common.collect.ImmutableSet; import net.fabricmc.loom.LoomGradleExtension; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.ResolvedArtifact; import org.gradle.api.artifacts.ResolvedDependency; +import org.gradle.api.artifacts.query.ArtifactResolutionQuery; +import org.gradle.api.artifacts.result.ArtifactResolutionResult; +import org.gradle.api.artifacts.result.ArtifactResult; +import org.gradle.api.artifacts.result.ComponentArtifactsResult; +import org.gradle.api.artifacts.result.ResolvedArtifactResult; +import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier; +import org.gradle.jvm.JvmLibrary; +import org.gradle.language.base.artifact.SourcesArtifact; import java.io.File; +import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; public abstract class DependencyProvider { private LoomDependencyManager dependencyManager; - public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception; + public abstract void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer postPopulationScheduler) throws Exception; public abstract String getTargetConfig(); @@ -61,10 +74,12 @@ public abstract class DependencyProvider { } public static class DependencyInfo { + final Project project; final Dependency dependency; final Configuration sourceConfiguration; - public DependencyInfo(Dependency dependency, Configuration sourceConfiguration) { + public DependencyInfo(Project project, Dependency dependency, Configuration sourceConfiguration) { + this.project = project; this.dependency = dependency; this.sourceConfiguration = sourceConfiguration; } @@ -87,17 +102,68 @@ public abstract class DependencyProvider { return sourceConfiguration; } - public Set resolve(){ - return sourceConfiguration.files(dependency); + // TODO: Can this be done with stable APIs only? + @SuppressWarnings("UnstableApiUsage") + public Set resolve(String classifier) { + if (classifier.isEmpty()) { + return sourceConfiguration.files(dependency); + } else if ("sources".equals(classifier)) { + for (ResolvedArtifact rd : sourceConfiguration.getResolvedConfiguration().getResolvedArtifacts()) { + if (rd.getModuleVersion().getId().getGroup().equals(dependency.getGroup()) + && rd.getModuleVersion().getId().getName().equals(dependency.getName()) + && rd.getModuleVersion().getId().getVersion().equals(dependency.getVersion())) { + + ImmutableSet.Builder files = ImmutableSet.builder(); + + ArtifactResolutionQuery query = project.getDependencies().createArtifactResolutionQuery(); + query.forComponents(DefaultModuleComponentIdentifier.newId(rd.getModuleVersion().getId())); + //noinspection unchecked + query.withArtifacts(JvmLibrary.class, SourcesArtifact.class); + for (ComponentArtifactsResult cresult : query.execute().getResolvedComponents()) { + for (ArtifactResult result : cresult.getArtifacts(SourcesArtifact.class)) { + if (result instanceof ResolvedArtifactResult) { + files.add(((ResolvedArtifactResult) result).getFile()); + } + } + } + + return files.build(); + } + } + + return ImmutableSet.of(); + } else { + project.getLogger().warn("Unsupported classifier '" + classifier + "'"); + return ImmutableSet.of(); + } } - public File resolveFile(){ - Set files = resolve(); - if(files.size() != 1){ - throw new RuntimeException(dependency + " resolves to more than one file"); + public Optional resolveFile() { + return resolveFile(""); + } + + public Optional resolveFile(String classifier) { + Set files = resolve(classifier); + if (files.isEmpty()) { + return Optional.empty(); + } else if (files.size() > 1) { + StringBuilder builder = new StringBuilder(this.toString()); + if (!classifier.isEmpty()) { + builder.append(" [").append(classifier).append("]"); + } + builder.append(" resolves to more than one file:"); + for (File f : files) { + builder.append("\n\t-").append(f.getAbsolutePath()); + } + throw new RuntimeException(builder.toString()); + } else { + return files.stream().findFirst(); } - File file = files.stream().findFirst().orElse(null); - return file; + } + + @Override + public String toString() { + return getDepString(); } public String getDepString(){ diff --git a/src/main/java/net/fabricmc/loom/util/LoomDependencyManager.java b/src/main/java/net/fabricmc/loom/util/LoomDependencyManager.java index 7893edf..a69ed07 100644 --- a/src/main/java/net/fabricmc/loom/util/LoomDependencyManager.java +++ b/src/main/java/net/fabricmc/loom/util/LoomDependencyManager.java @@ -61,6 +61,8 @@ public class LoomDependencyManager { } public void handleDependencies(Project project){ + List afterTasks = new ArrayList<>(); + project.getLogger().lifecycle(":setting up loom dependencies"); LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); Set targetConfigs = new LinkedHashSet<>(); @@ -72,9 +74,9 @@ public class LoomDependencyManager { configuration.getDependencies().forEach(dependency -> { for(DependencyProvider provider : dependencyProviderList){ if(provider.getTargetConfig().equals(config)){ - DependencyProvider.DependencyInfo info = new DependencyProvider.DependencyInfo(dependency, configuration); + DependencyProvider.DependencyInfo info = new DependencyProvider.DependencyInfo(project, dependency, configuration); try { - provider.provide(info, project, extension); + provider.provide(info, project, extension, afterTasks::add); } catch (Exception e) { throw new RuntimeException("Failed to provide", e); } @@ -88,6 +90,10 @@ public class LoomDependencyManager { } else { project.getLogger().warn("fabric-installer.json not found in classpath!"); } + + for (Runnable runnable : afterTasks) { + runnable.run(); + } } private static void handleInstallerJson(JsonObject jsonObject, Project project){ diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 3fdb162..36e1048 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -35,6 +35,7 @@ import org.cadixdev.lorenz.io.TextMappingsReader; import org.cadixdev.mercury.Mercury; import org.cadixdev.mercury.remapper.MercuryRemapper; import org.gradle.api.Project; +import org.gradle.internal.impldep.aQute.bnd.build.Run; import org.objectweb.asm.commons.Remapper; import org.zeroturnaround.zip.ZipUtil; @@ -104,10 +105,20 @@ public class SourceRemapper { ZipUtil.unpack(source, srcPath.toFile()); } + if (!destination.isDirectory() && destination.exists()) { + if (!destination.delete()) { + throw new RuntimeException("Could not delete " + destination.getName() + "!"); + } + } + StitchUtil.FileSystemDelegate dstFs = destination.isDirectory() ? null : StitchUtil.getJarFileSystem(destination, true); Path dstPath = dstFs != null ? dstFs.get().getPath("/") : destination.toPath(); - mercury.rewrite(srcPath, dstPath); + try { + mercury.rewrite(srcPath, dstPath); + } catch (Exception e) { + project.getLogger().warn("Could not remap " + source.getName() + " fully!", e); + } if (dstFs != null) { dstFs.close();