working source code remapping for mod dependencies
This commit is contained in:
		
							parent
							
								
									530896e41a
								
							
						
					
					
						commit
						d9b8c90b5f
					
				
					 7 changed files with 129 additions and 23 deletions
				
			
		|  | @ -35,6 +35,7 @@ import java.nio.file.FileSystem; | ||||||
| import java.nio.file.FileSystems; | import java.nio.file.FileSystems; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
|  | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
| //TODO fix local mappings | //TODO fix local mappings | ||||||
| //TODO possibly use maven for mappings, can fix above at the same time | //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; | 	public File MAPPINGS_MIXIN_EXPORT; | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception { | 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||||
| 		MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class); | 		MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class); | ||||||
| 
 | 
 | ||||||
| 		project.getLogger().lifecycle(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")"); | 		project.getLogger().lifecycle(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")"); | ||||||
| 
 | 
 | ||||||
| 		String version = 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.mappingsName = dependency.getDependency().getName(); | ||||||
| 		this.minecraftVersion = version.substring(0, version.lastIndexOf('.')); | 		this.minecraftVersion = version.substring(0, version.lastIndexOf('.')); | ||||||
|  | @ -95,7 +96,7 @@ public class MappingsProvider extends DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 		mappedProvider = new MinecraftMappedProvider(); | 		mappedProvider = new MinecraftMappedProvider(); | ||||||
| 		mappedProvider.initFiles(project, minecraftProvider, this); | 		mappedProvider.initFiles(project, minecraftProvider, this); | ||||||
| 		mappedProvider.provide(dependency, project, extension); | 		mappedProvider.provide(dependency, project, extension, postPopulationScheduler); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void initFiles(Project project) { | 	public void initFiles(Project project) { | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
| public class MinecraftMappedProvider extends DependencyProvider { | public class MinecraftMappedProvider extends DependencyProvider { | ||||||
|     public File MINECRAFT_MAPPED_JAR; |     public File MINECRAFT_MAPPED_JAR; | ||||||
|  | @ -40,7 +41,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | ||||||
|     private MinecraftProvider minecraftProvider; |     private MinecraftProvider minecraftProvider; | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception { |     public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||||
|         if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { |         if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) { | ||||||
|             throw new RuntimeException("mappings file not found"); |             throw new RuntimeException("mappings file not found"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -38,6 +38,7 @@ import java.io.IOException; | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
|  | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
| public class MinecraftProvider extends DependencyProvider { | public class MinecraftProvider extends DependencyProvider { | ||||||
| 
 | 
 | ||||||
|  | @ -55,7 +56,7 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 	Gson gson = new Gson(); | 	Gson gson = new Gson(); | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) throws Exception { | 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||||
| 		minecraftVersion = dependency.getDependency().getVersion(); | 		minecraftVersion = dependency.getDependency().getVersion(); | ||||||
| 
 | 
 | ||||||
| 		initFiles(project); | 		initFiles(project); | ||||||
|  |  | ||||||
|  | @ -24,27 +24,33 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.providers; | package net.fabricmc.loom.providers; | ||||||
| 
 | 
 | ||||||
|  | import com.google.common.io.Files; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| import net.fabricmc.loom.util.DependencyProvider; | import net.fabricmc.loom.util.DependencyProvider; | ||||||
| import net.fabricmc.loom.util.ModProcessor; | import net.fabricmc.loom.util.ModProcessor; | ||||||
|  | import net.fabricmc.loom.util.SourceRemapper; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.Optional; | ||||||
|  | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
| public class ModRemapperProvider extends DependencyProvider { | public class ModRemapperProvider extends DependencyProvider { | ||||||
| 	@Override | 	@Override | ||||||
| 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension) { | 	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) { | ||||||
| 		File input = dependency.resolveFile(); | 		// 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); | 		MappingsProvider mappingsProvider = getDependencyManager().getProvider(MappingsProvider.class); | ||||||
| 		String verSuffix = ".mapped." + mappingsProvider.mappingsName + "." + mappingsProvider.mappingsVersion; | 		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 modStore = extension.getRemappedModCache(); | ||||||
| 		File output = new File(modStore, outputName); | 		File output = new File(modStore, outputNamePrefix + ".jar"); | ||||||
| 		if(output.exists()){ | 		if(output.exists()){ | ||||||
| 			output.delete(); | 			output.delete(); | ||||||
| 		} | 		} | ||||||
|  | @ -58,6 +64,20 @@ public class ModRemapperProvider extends DependencyProvider { | ||||||
| 		project.getDependencies().add("compile", project.getDependencies().module( | 		project.getDependencies().add("compile", project.getDependencies().module( | ||||||
| 				dependency.getDepString() + verSuffix | 				dependency.getDepString() + verSuffix | ||||||
| 		)); | 		)); | ||||||
|  | 
 | ||||||
|  | 		postPopulationScheduler.accept(() -> { | ||||||
|  | 			// Provide sources JAR, if present | ||||||
|  | 			Optional<File> 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 | 	@Override | ||||||
|  |  | ||||||
|  | @ -24,20 +24,33 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.util; | package net.fabricmc.loom.util; | ||||||
| 
 | 
 | ||||||
|  | import com.google.common.collect.ImmutableSet; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.artifacts.Configuration; | import org.gradle.api.artifacts.Configuration; | ||||||
| import org.gradle.api.artifacts.Dependency; | import org.gradle.api.artifacts.Dependency; | ||||||
|  | import org.gradle.api.artifacts.ResolvedArtifact; | ||||||
| import org.gradle.api.artifacts.ResolvedDependency; | 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.io.File; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Optional; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
|  | import java.util.function.Consumer; | ||||||
| 
 | 
 | ||||||
| public abstract class DependencyProvider { | public abstract class DependencyProvider { | ||||||
| 
 | 
 | ||||||
| 	private LoomDependencyManager dependencyManager; | 	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<Runnable> postPopulationScheduler) throws Exception; | ||||||
| 
 | 
 | ||||||
| 	public abstract String getTargetConfig(); | 	public abstract String getTargetConfig(); | ||||||
| 
 | 
 | ||||||
|  | @ -61,10 +74,12 @@ public abstract class DependencyProvider { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static class DependencyInfo { | 	public static class DependencyInfo { | ||||||
|  | 		final Project project; | ||||||
| 		final Dependency dependency; | 		final Dependency dependency; | ||||||
| 		final Configuration sourceConfiguration; | 		final Configuration sourceConfiguration; | ||||||
| 
 | 
 | ||||||
| 		public DependencyInfo(Dependency dependency, Configuration sourceConfiguration) { | 		public DependencyInfo(Project project, Dependency dependency, Configuration sourceConfiguration) { | ||||||
|  | 			this.project = project; | ||||||
| 			this.dependency = dependency; | 			this.dependency = dependency; | ||||||
| 			this.sourceConfiguration = sourceConfiguration; | 			this.sourceConfiguration = sourceConfiguration; | ||||||
| 		} | 		} | ||||||
|  | @ -87,17 +102,68 @@ public abstract class DependencyProvider { | ||||||
| 			return sourceConfiguration; | 			return sourceConfiguration; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public Set<File> resolve(){ | 		// TODO: Can this be done with stable APIs only? | ||||||
| 			return sourceConfiguration.files(dependency); | 		@SuppressWarnings("UnstableApiUsage") | ||||||
|  | 		public Set<File> 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<File> 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(){ | 		public Optional<File> resolveFile() { | ||||||
| 			Set<File> files = resolve(); | 			return resolveFile(""); | ||||||
| 			if(files.size() != 1){ | 		} | ||||||
| 				throw new RuntimeException(dependency + " resolves to more than one file"); | 
 | ||||||
|  | 		public Optional<File> resolveFile(String classifier) { | ||||||
|  | 			Set<File> 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(){ | 		public String getDepString(){ | ||||||
|  |  | ||||||
|  | @ -61,6 +61,8 @@ public class LoomDependencyManager { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void handleDependencies(Project project){ | 	public void handleDependencies(Project project){ | ||||||
|  | 		List<Runnable> afterTasks = new ArrayList<>(); | ||||||
|  | 
 | ||||||
| 		project.getLogger().lifecycle(":setting up loom dependencies"); | 		project.getLogger().lifecycle(":setting up loom dependencies"); | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		Set<String> targetConfigs = new LinkedHashSet<>(); | 		Set<String> targetConfigs = new LinkedHashSet<>(); | ||||||
|  | @ -72,9 +74,9 @@ public class LoomDependencyManager { | ||||||
| 			configuration.getDependencies().forEach(dependency -> { | 			configuration.getDependencies().forEach(dependency -> { | ||||||
| 				for(DependencyProvider provider : dependencyProviderList){ | 				for(DependencyProvider provider : dependencyProviderList){ | ||||||
| 					if(provider.getTargetConfig().equals(config)){ | 					if(provider.getTargetConfig().equals(config)){ | ||||||
| 						DependencyProvider.DependencyInfo info = new DependencyProvider.DependencyInfo(dependency, configuration); | 						DependencyProvider.DependencyInfo info = new DependencyProvider.DependencyInfo(project, dependency, configuration); | ||||||
| 						try { | 						try { | ||||||
| 							provider.provide(info, project, extension); | 							provider.provide(info, project, extension, afterTasks::add); | ||||||
| 						} catch (Exception e) { | 						} catch (Exception e) { | ||||||
| 							throw new RuntimeException("Failed to provide", e); | 							throw new RuntimeException("Failed to provide", e); | ||||||
| 						} | 						} | ||||||
|  | @ -88,6 +90,10 @@ public class LoomDependencyManager { | ||||||
| 		} else { | 		} else { | ||||||
| 			project.getLogger().warn("fabric-installer.json not found in classpath!"); | 			project.getLogger().warn("fabric-installer.json not found in classpath!"); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		for (Runnable runnable : afterTasks) { | ||||||
|  | 			runnable.run(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void handleInstallerJson(JsonObject jsonObject, Project project){ | 	private static void handleInstallerJson(JsonObject jsonObject, Project project){ | ||||||
|  |  | ||||||
|  | @ -35,6 +35,7 @@ import org.cadixdev.lorenz.io.TextMappingsReader; | ||||||
| import org.cadixdev.mercury.Mercury; | import org.cadixdev.mercury.Mercury; | ||||||
| import org.cadixdev.mercury.remapper.MercuryRemapper; | import org.cadixdev.mercury.remapper.MercuryRemapper; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
|  | import org.gradle.internal.impldep.aQute.bnd.build.Run; | ||||||
| import org.objectweb.asm.commons.Remapper; | import org.objectweb.asm.commons.Remapper; | ||||||
| import org.zeroturnaround.zip.ZipUtil; | import org.zeroturnaround.zip.ZipUtil; | ||||||
| 
 | 
 | ||||||
|  | @ -104,10 +105,20 @@ public class SourceRemapper { | ||||||
| 			ZipUtil.unpack(source, srcPath.toFile()); | 			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); | 		StitchUtil.FileSystemDelegate dstFs = destination.isDirectory() ? null : StitchUtil.getJarFileSystem(destination, true); | ||||||
| 		Path dstPath = dstFs != null ? dstFs.get().getPath("/") : destination.toPath(); | 		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) { | 		if (dstFs != null) { | ||||||
| 			dstFs.close(); | 			dstFs.close(); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue