Merge commit '9157c22448cb4847586772f8028010f717accc14' into dev/1.8

This commit is contained in:
shedaniel
2024-11-16 20:17:29 +08:00
63 changed files with 1034 additions and 972 deletions

View File

@@ -27,7 +27,7 @@ import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.LfWriter; import net.fabricmc.loom.util.LfWriter;
import net.fabricmc.loom.util.aw2at.Aw2At; import net.fabricmc.loom.util.aw2at.Aw2At;
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper; import net.fabricmc.loom.util.service.ServiceFactory;
public final class ModBuildExtensions { public final class ModBuildExtensions {
public static Set<String> readMixinConfigsFromManifest(File jarFile) { public static Set<String> readMixinConfigsFromManifest(File jarFile) {
@@ -49,7 +49,7 @@ public final class ModBuildExtensions {
} }
} }
public static void convertAwToAt(SetProperty<String> atAccessWidenersProperty, Path outputFile, Property<String> mappingBuildServiceUuid) throws IOException { public static void convertAwToAt(ServiceFactory serviceFactory, SetProperty<String> atAccessWidenersProperty, Path outputFile, Property<MappingsService.Options> options) throws IOException {
if (!atAccessWidenersProperty.isPresent()) { if (!atAccessWidenersProperty.isPresent()) {
return; return;
} }
@@ -84,8 +84,8 @@ public final class ModBuildExtensions {
Files.delete(awPath); Files.delete(awPath);
} }
MappingsService service = UnsafeWorkQueueHelper.get(mappingBuildServiceUuid, MappingsService.class); MappingsService service = serviceFactory.get(options);
at = at.remap(service.getMemoryMappingTree(), service.getFromNamespace(), service.getToNamespace()); at = at.remap(service.getMemoryMappingTree(), service.getFrom(), service.getTo());
try (Writer writer = new LfWriter(Files.newBufferedWriter(atPath))) { try (Writer writer = new LfWriter(Files.newBufferedWriter(atPath))) {
AccessTransformFormats.FML.write(writer, at); AccessTransformFormats.FML.write(writer, at);

View File

@@ -24,6 +24,8 @@
package net.fabricmc.loom.api.remapping; package net.fabricmc.loom.api.remapping;
import java.io.Serializable;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
/** /**
@@ -31,7 +33,7 @@ import org.jetbrains.annotations.ApiStatus;
* *
* <p>Design based off of Gradle's {@link org.gradle.workers.WorkParameters}. * <p>Design based off of Gradle's {@link org.gradle.workers.WorkParameters}.
*/ */
public interface RemapperParameters { public interface RemapperParameters extends Serializable {
final class None implements RemapperParameters { final class None implements RemapperParameters {
@ApiStatus.Internal @ApiStatus.Internal
public static None INSTANCE = new None(); public static None INSTANCE = new None();

View File

@@ -91,8 +91,8 @@ import net.fabricmc.loom.util.ExceptionUtil;
import net.fabricmc.loom.util.ProcessUtil; import net.fabricmc.loom.util.ProcessUtil;
import net.fabricmc.loom.util.gradle.GradleUtils; import net.fabricmc.loom.util.gradle.GradleUtils;
import net.fabricmc.loom.util.gradle.SourceSetHelper; import net.fabricmc.loom.util.gradle.SourceSetHelper;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.ScopedServiceFactory;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
public abstract class CompileConfiguration implements Runnable { public abstract class CompileConfiguration implements Runnable {
@Inject @Inject
@@ -110,8 +110,8 @@ public abstract class CompileConfiguration implements Runnable {
javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath()));
}); });
afterEvaluationWithService((serviceManager) -> { afterEvaluationWithService((serviceFactory) -> {
final ConfigContext configContext = new ConfigContextImpl(getProject(), serviceManager, extension); final ConfigContext configContext = new ConfigContextImpl(getProject(), serviceFactory, extension);
MinecraftSourceSets.get(getProject()).afterEvaluate(getProject()); MinecraftSourceSets.get(getProject()).afterEvaluate(getProject());
@@ -129,7 +129,7 @@ public abstract class CompileConfiguration implements Runnable {
LoomDependencyManager dependencyManager = new LoomDependencyManager(); LoomDependencyManager dependencyManager = new LoomDependencyManager();
extension.setDependencyManager(dependencyManager); extension.setDependencyManager(dependencyManager);
dependencyManager.handleDependencies(getProject(), serviceManager); dependencyManager.handleDependencies(getProject(), serviceFactory);
} catch (Exception e) { } catch (Exception e) {
ExceptionUtil.processException(e, getProject()); ExceptionUtil.processException(e, getProject());
disownLock(); disownLock();
@@ -159,7 +159,7 @@ public abstract class CompileConfiguration implements Runnable {
// because of https://github.com/architectury/architectury-loom/issues/72. // because of https://github.com/architectury/architectury-loom/issues/72.
if (!ModConfigurationRemapper.isCIBuild()) { if (!ModConfigurationRemapper.isCIBuild()) {
try { try {
ForgeSourcesRemapper.addBaseForgeSources(getProject()); ForgeSourcesRemapper.addBaseForgeSources(getProject(), configContext.serviceFactory());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -225,7 +225,7 @@ public abstract class CompileConfiguration implements Runnable {
setupDependencyProviders(project, extension); setupDependencyProviders(project, extension);
final DependencyInfo mappingsDep = DependencyInfo.create(getProject(), Configurations.MAPPINGS); final DependencyInfo mappingsDep = DependencyInfo.create(getProject(), Configurations.MAPPINGS);
final MappingConfiguration mappingConfiguration = MappingConfiguration.create(getProject(), configContext.serviceManager(), mappingsDep, minecraftProvider); final MappingConfiguration mappingConfiguration = MappingConfiguration.create(getProject(), configContext.serviceFactory(), mappingsDep, minecraftProvider);
extension.setMappingConfiguration(mappingConfiguration); extension.setMappingConfiguration(mappingConfiguration);
if (extension.isForgeLike()) { if (extension.isForgeLike()) {
@@ -241,7 +241,7 @@ public abstract class CompileConfiguration implements Runnable {
} }
if (minecraftProvider instanceof ForgeMinecraftProvider patched) { if (minecraftProvider instanceof ForgeMinecraftProvider patched) {
patched.getPatchedProvider().remapJar(); patched.getPatchedProvider().remapJar(configContext.serviceFactory());
} }
// Provide the remapped mc jars // Provide the remapped mc jars
@@ -540,10 +540,12 @@ public abstract class CompileConfiguration implements Runnable {
dependencyProviders.handleDependencies(project); dependencyProviders.handleDependencies(project);
} }
private void afterEvaluationWithService(Consumer<SharedServiceManager> consumer) { private void afterEvaluationWithService(Consumer<ServiceFactory> consumer) {
GradleUtils.afterSuccessfulEvaluation(getProject(), () -> { GradleUtils.afterSuccessfulEvaluation(getProject(), () -> {
try (var serviceManager = new ScopedSharedServiceManager()) { try (var serviceFactory = new ScopedServiceFactory()) {
consumer.accept(serviceManager); consumer.accept(serviceFactory);
} catch (IOException e) {
throw new UncheckedIOException(e);
} }
}); });
} }

View File

@@ -27,10 +27,10 @@ package net.fabricmc.loom.configuration;
import org.gradle.api.Project; import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
public interface ConfigContext { public interface ConfigContext {
Project project(); Project project();
SharedServiceManager serviceManager(); ServiceFactory serviceFactory();
LoomGradleExtension extension(); LoomGradleExtension extension();
} }

View File

@@ -27,7 +27,7 @@ package net.fabricmc.loom.configuration;
import org.gradle.api.Project; import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
public record ConfigContextImpl(Project project, SharedServiceManager serviceManager, LoomGradleExtension extension) implements ConfigContext { public record ConfigContextImpl(Project project, ServiceFactory serviceFactory, LoomGradleExtension extension) implements ConfigContext {
} }

View File

@@ -29,18 +29,18 @@ import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.mods.ModConfigurationRemapper; import net.fabricmc.loom.configuration.mods.ModConfigurationRemapper;
import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
public class LoomDependencyManager { public class LoomDependencyManager {
public void handleDependencies(Project project, SharedServiceManager serviceManager) { public void handleDependencies(Project project, ServiceFactory serviceFactory) {
project.getLogger().info(":setting up loom dependencies"); project.getLogger().info(":setting up loom dependencies");
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
SourceRemapper sourceRemapper = new SourceRemapper(project, serviceManager, true); SourceRemapper sourceRemapper = new SourceRemapper(project, serviceFactory, true);
String platformSuffix = extension.isForgeLike() ? "_forge" : extension.isQuilt() ? "_arch_quilt" : ""; String platformSuffix = extension.isForgeLike() ? "_forge" : extension.isQuilt() ? "_arch_quilt" : "";
String mappingsIdentifier = extension.getMappingConfiguration().mappingsIdentifier() + platformSuffix; String mappingsIdentifier = extension.getMappingConfiguration().mappingsIdentifier() + platformSuffix;
ModConfigurationRemapper.supplyModConfigurations(project, serviceManager, mappingsIdentifier, extension, sourceRemapper); ModConfigurationRemapper.supplyModConfigurations(project, serviceFactory, mappingsIdentifier, extension, sourceRemapper);
sourceRemapper.remapAll(); sourceRemapper.remapAll();

View File

@@ -68,7 +68,7 @@ import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.ExceptionUtil; import net.fabricmc.loom.util.ExceptionUtil;
import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.gradle.SourceSetHelper; import net.fabricmc.loom.util.gradle.SourceSetHelper;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings("UnstableApiUsage")
public class ModConfigurationRemapper { public class ModConfigurationRemapper {
@@ -76,7 +76,7 @@ public class ModConfigurationRemapper {
// This can happen when the dependency is a FileCollectionDependency or from a flatDir repository. // This can happen when the dependency is a FileCollectionDependency or from a flatDir repository.
public static final String MISSING_GROUP = "unspecified"; public static final String MISSING_GROUP = "unspecified";
public static void supplyModConfigurations(Project project, SharedServiceManager serviceManager, String mappingsSuffix, LoomGradleExtension extension, SourceRemapper sourceRemapper) { public static void supplyModConfigurations(Project project, ServiceFactory serviceFactory, String mappingsSuffix, LoomGradleExtension extension, SourceRemapper sourceRemapper) {
final DependencyHandler dependencies = project.getDependencies(); final DependencyHandler dependencies = project.getDependencies();
// The configurations where the source and remapped artifacts go. // The configurations where the source and remapped artifacts go.
// key: source, value: target // key: source, value: target
@@ -202,7 +202,7 @@ public class ModConfigurationRemapper {
if (!toRemap.isEmpty()) { if (!toRemap.isEmpty()) {
try { try {
new ModProcessor(project, sourceConfig, serviceManager).processMods(toRemap); new ModProcessor(project, sourceConfig, serviceFactory).processMods(toRemap);
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException("Failed to remap mods", e); throw new UncheckedIOException("Failed to remap mods", e);
} }

View File

@@ -64,7 +64,7 @@ import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.kotlin.KotlinClasspathService; import net.fabricmc.loom.util.kotlin.KotlinClasspathService;
import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader; import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.srg.AtClassRemapper; import net.fabricmc.loom.util.srg.AtClassRemapper;
import net.fabricmc.loom.util.srg.CoreModClassRemapper; import net.fabricmc.loom.util.srg.CoreModClassRemapper;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
@@ -81,12 +81,12 @@ public class ModProcessor {
private final Project project; private final Project project;
private final Configuration sourceConfiguration; private final Configuration sourceConfiguration;
private final SharedServiceManager serviceManager; private final ServiceFactory serviceFactory;
public ModProcessor(Project project, Configuration sourceConfiguration, SharedServiceManager serviceManager) { public ModProcessor(Project project, Configuration sourceConfiguration, ServiceFactory serviceFactory) {
this.project = project; this.project = project;
this.sourceConfiguration = sourceConfiguration; this.sourceConfiguration = sourceConfiguration;
this.serviceManager = serviceManager; this.serviceFactory = serviceFactory;
} }
public void processMods(List<ModDependency> remapList) throws IOException { public void processMods(List<ModDependency> remapList) throws IOException {
@@ -174,7 +174,7 @@ public class ModProcessor {
} }
MappingOption mappingOption = MappingOption.forPlatform(extension); MappingOption mappingOption = MappingOption.forPlatform(extension);
MemoryMappingTree mappings = mappingConfiguration.getMappingsService(serviceManager, mappingOption).getMappingTree(); MemoryMappingTree mappings = mappingConfiguration.getMappingsService(project, serviceManager, mappingOption).getMappingTree();
LoggerFilter.replaceSystemOut(); LoggerFilter.replaceSystemOut();
TinyRemapper.Builder builder = TinyRemapper.newRemapper() TinyRemapper.Builder builder = TinyRemapper.newRemapper()
@@ -183,7 +183,7 @@ public class ModProcessor {
.renameInvalidLocals(false) .renameInvalidLocals(false)
.extraAnalyzeVisitor(AccessWidenerAnalyzeVisitorProvider.createFromMods(fromM, remapList, extension.getPlatform().get())); .extraAnalyzeVisitor(AccessWidenerAnalyzeVisitorProvider.createFromMods(fromM, remapList, extension.getPlatform().get()));
final KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(serviceManager, project); final KotlinClasspathService kotlinClasspathService = serviceFactory.getOrNull(KotlinClasspathService.createOptions(project));
KotlinRemapperClassloader kotlinRemapperClassloader = null; KotlinRemapperClassloader kotlinRemapperClassloader = null;
if (kotlinClasspathService != null) { if (kotlinClasspathService != null) {
@@ -201,7 +201,7 @@ public class ModProcessor {
} }
for (RemapperExtensionHolder holder : extension.getRemapperExtensions().get()) { for (RemapperExtensionHolder holder : extension.getRemapperExtensions().get()) {
holder.apply(builder, fromM, toM, project.getObjects()); holder.apply(builder, fromM, toM);
} }
final TinyRemapper remapper = builder.build(); final TinyRemapper remapper = builder.build();

View File

@@ -41,7 +41,7 @@ public final class ContextImplHelper {
public static LazyCloseable<TinyRemapper> createRemapper(ConfigContext configContext, MappingsNamespace from, MappingsNamespace to) { public static LazyCloseable<TinyRemapper> createRemapper(ConfigContext configContext, MappingsNamespace from, MappingsNamespace to) {
return new LazyCloseable<>(() -> { return new LazyCloseable<>(() -> {
try { try {
TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext.project(), configContext.serviceManager(), from.toString(), to.toString()); TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext.project(), configContext.serviceFactory(), from.toString(), to.toString());
for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) {
tinyRemapper.readClassPath(minecraftJar); tinyRemapper.readClassPath(minecraftJar);

View File

@@ -66,6 +66,6 @@ public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar min
public MemoryMappingTree getMappings() { public MemoryMappingTree getMappings() {
LoomGradleExtension extension = LoomGradleExtension.get(configContext().project()); LoomGradleExtension extension = LoomGradleExtension.get(configContext().project());
final MappingOption mappingOption = MappingOption.forPlatform(extension); final MappingOption mappingOption = MappingOption.forPlatform(extension);
return extension.getMappingConfiguration().getMappingsService(configContext().serviceManager(), mappingOption).getMappingTree(); return extension.getMappingConfiguration().getMappingsService(configContext().project(), configContext().serviceFactory(), mappingOption).getMappingTree();
} }
} }

View File

@@ -55,6 +55,9 @@ import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import dev.architectury.loom.forge.UserdevConfig; import dev.architectury.loom.forge.UserdevConfig;
import dev.architectury.loom.util.MappingOption; import dev.architectury.loom.util.MappingOption;
import dev.architectury.loom.util.TempFiles; import dev.architectury.loom.util.TempFiles;
import net.fabricmc.loom.util.service.ServiceFactory;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logger;
@@ -83,8 +86,6 @@ import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.function.FsPathConsumer; import net.fabricmc.loom.util.function.FsPathConsumer;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
import net.fabricmc.loom.util.service.SharedServiceManager;
import net.fabricmc.loom.util.srg.CoreModClassRemapper; import net.fabricmc.loom.util.srg.CoreModClassRemapper;
import net.fabricmc.loom.util.srg.InnerClassRemapper; import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.mappingio.tree.MappingTree;
@@ -207,12 +208,9 @@ public class MinecraftPatchedProvider {
} }
} }
public void remapJar() throws Exception { public void remapJar(ServiceFactory serviceFactory) throws Exception {
if (dirty) { if (dirty) {
try (var serviceManager = new ScopedSharedServiceManager()) { remapPatchedJar(serviceFactory);
remapPatchedJar(serviceManager);
}
fillClientExtraJar(); fillClientExtraJar();
} }
@@ -226,9 +224,9 @@ public class MinecraftPatchedProvider {
copyNonClassFiles(minecraftProvider.getMinecraftClientJar().toPath(), minecraftClientExtra); copyNonClassFiles(minecraftProvider.getMinecraftClientJar().toPath(), minecraftClientExtra);
} }
private TinyRemapper buildRemapper(SharedServiceManager serviceManager, Path input) throws IOException { private TinyRemapper buildRemapper(ServiceFactory serviceFactory, Path input) throws IOException {
final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); final MappingOption mappingOption = MappingOption.forPlatform(getExtension());
TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(project, serviceFactory, mappingOption);
final String sourceNamespace = IntermediaryNamespaces.intermediary(project); final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
MemoryMappingTree mappings = mappingsService.getMappingTree(); MemoryMappingTree mappings = mappingsService.getMappingTree();
@@ -408,7 +406,7 @@ public class MinecraftPatchedProvider {
project.getLogger().lifecycle(":access transformed minecraft in " + stopwatch.stop()); project.getLogger().lifecycle(":access transformed minecraft in " + stopwatch.stop());
} }
private void remapPatchedJar(SharedServiceManager serviceManager) throws Exception { private void remapPatchedJar(ServiceFactory serviceFactory) throws Exception {
logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)"); logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)");
Path mcInput = minecraftPatchedIntermediateAtJar; Path mcInput = minecraftPatchedIntermediateAtJar;
Path mcOutput = minecraftPatchedJar; Path mcOutput = minecraftPatchedJar;
@@ -416,7 +414,7 @@ public class MinecraftPatchedProvider {
Path forgeUserdevJar = getForgeUserdevJar().toPath(); Path forgeUserdevJar = getForgeUserdevJar().toPath();
Files.deleteIfExists(mcOutput); Files.deleteIfExists(mcOutput);
TinyRemapper remapper = buildRemapper(serviceManager, mcInput); TinyRemapper remapper = buildRemapper(serviceFactory, mcInput);
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(mcOutput).build()) { try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(mcOutput).build()) {
outputConsumer.addNonClassFiles(mcInput); outputConsumer.addNonClassFiles(mcInput);
@@ -435,13 +433,13 @@ public class MinecraftPatchedProvider {
} }
copyUserdevFiles(forgeUserdevJar, mcOutput); copyUserdevFiles(forgeUserdevJar, mcOutput);
remapCoreMods(mcOutput, serviceManager); remapCoreMods(mcOutput, serviceFactory);
applyLoomPatchVersion(mcOutput); applyLoomPatchVersion(mcOutput);
} }
private void remapCoreMods(Path patchedJar, SharedServiceManager serviceManager) throws Exception { private void remapCoreMods(Path patchedJar, ServiceFactory serviceFactory) throws Exception {
final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); final MappingOption mappingOption = MappingOption.forPlatform(getExtension());
final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(project, serviceFactory, mappingOption);
final MappingTree mappings = mappingsService.getMappingTree(); final MappingTree mappings = mappingsService.getMappingTree();
CoreModClassRemapper.remapJar(project, getExtension().getPlatform().get(), patchedJar, mappings); CoreModClassRemapper.remapJar(project, getExtension().getPlatform().get(), patchedJar, mappings);
} }

View File

@@ -25,6 +25,8 @@
package net.fabricmc.loom.configuration.providers.mappings; package net.fabricmc.loom.configuration.providers.mappings;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -39,7 +41,7 @@ import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.layered.MappingContext; import net.fabricmc.loom.api.mappings.layered.MappingContext;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.util.download.DownloadBuilder; import net.fabricmc.loom.util.download.DownloadBuilder;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.ScopedServiceFactory;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
public class GradleMappingContext implements MappingContext { public class GradleMappingContext implements MappingContext {
@@ -74,8 +76,11 @@ public class GradleMappingContext implements MappingContext {
@Override @Override
public Supplier<MemoryMappingTree> intermediaryTree() { public Supplier<MemoryMappingTree> intermediaryTree() {
return () -> { return () -> {
try (var serviceManager = new ScopedSharedServiceManager()) { try (var serviceFactory = new ScopedServiceFactory()) {
return IntermediateMappingsService.getInstance(serviceManager, project, minecraftProvider()).getMemoryMappingTree(); IntermediateMappingsService intermediateMappingsService = serviceFactory.get(IntermediateMappingsService.createOptions(project, minecraftProvider()));
return intermediateMappingsService.getMemoryMappingTree();
} catch (IOException e) {
throw new UncheckedIOException(e);
} }
}; };
} }

View File

@@ -31,77 +31,101 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.jetbrains.annotations.VisibleForTesting; import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider; import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.util.service.SharedService; import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.mappingio.adapter.MappingNsCompleter; import net.fabricmc.mappingio.adapter.MappingNsCompleter;
import net.fabricmc.mappingio.format.tiny.Tiny2FileReader; import net.fabricmc.mappingio.format.tiny.Tiny2FileReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
public final class IntermediateMappingsService implements SharedService { public final class IntermediateMappingsService extends Service<IntermediateMappingsService.Options> {
private final Path intermediaryTiny; public static final ServiceType<Options, IntermediateMappingsService> TYPE = new ServiceType<>(Options.class, IntermediateMappingsService.class);
private final String expectedSrcNs; private static final Logger LOGGER = LoggerFactory.getLogger(IntermediateMappingsService.class);
public interface Options extends Service.Options {
@InputFile
RegularFileProperty getIntermediaryTiny();
@Input
Property<String> getExpectedSrcNs();
@Input
Property<String> getMinecraftVersion();
}
private final Supplier<MemoryMappingTree> memoryMappingTree = Suppliers.memoize(this::createMemoryMappingTree); private final Supplier<MemoryMappingTree> memoryMappingTree = Suppliers.memoize(this::createMemoryMappingTree);
private IntermediateMappingsService(Path intermediaryTiny, String expectedSrcNs) { public IntermediateMappingsService(Options options, ServiceFactory serviceFactory) {
this.intermediaryTiny = intermediaryTiny; super(options, serviceFactory);
this.expectedSrcNs = expectedSrcNs;
} }
public static synchronized IntermediateMappingsService getInstance(SharedServiceManager sharedServiceManager, Project project, MinecraftProvider minecraftProvider) { public static Provider<Options> createOptions(Project project, MinecraftProvider minecraftProvider) {
final LoomGradleExtension extension = LoomGradleExtension.get(project); final LoomGradleExtension extension = LoomGradleExtension.get(project);
final IntermediateMappingsProvider intermediateProvider = extension.getIntermediateMappingsProvider(); final IntermediateMappingsProvider intermediateProvider = extension.getIntermediateMappingsProvider();
final String id = "IntermediateMappingsService:%s:%s".formatted(intermediateProvider.getName(), intermediateProvider.getMinecraftVersion().get()); final Path intermediaryTiny = minecraftProvider.file(intermediateProvider.getName() + ".tiny").toPath();
return sharedServiceManager.getOrCreateService(id, () -> create(intermediateProvider, minecraftProvider, project));
}
@VisibleForTesting
public static IntermediateMappingsService create(IntermediateMappingsProvider intermediateMappingsProvider, MinecraftProvider minecraftProvider, Project project) {
final Path intermediaryTiny = minecraftProvider.file(intermediateMappingsProvider.getName() + ".tiny").toPath();
try { try {
if (intermediateMappingsProvider instanceof IntermediateMappingsProviderInternal internal) { if (intermediateProvider instanceof IntermediateMappingsProviderInternal internal) {
internal.provide(intermediaryTiny, project); internal.provide(intermediaryTiny, project);
} else { } else {
intermediateMappingsProvider.provide(intermediaryTiny); intermediateProvider.provide(intermediaryTiny);
} }
} catch (IOException e) { } catch (IOException e) {
try { try {
Files.deleteIfExists(intermediaryTiny); Files.deleteIfExists(intermediaryTiny);
} catch (IOException ex) { } catch (IOException ex) {
ex.printStackTrace(); LOGGER.warn("Failed to delete intermediary mappings file", ex);
} }
throw new UncheckedIOException("Failed to provide intermediate mappings", e); throw new UncheckedIOException("Failed to provide intermediate mappings", e);
} }
return createOptions(project, minecraftProvider, intermediaryTiny);
}
private static Provider<Options> createOptions(Project project, MinecraftProvider minecraftProvider, Path intermediaryTiny) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final IntermediateMappingsProvider intermediateProvider = extension.getIntermediateMappingsProvider();
// When merging legacy versions there will be multiple named namespaces, so use intermediary as the common src ns // When merging legacy versions there will be multiple named namespaces, so use intermediary as the common src ns
// Newer versions will use intermediary as the src ns // Newer versions will use intermediary as the src ns
final String expectedSrcNs = minecraftProvider.isLegacyVersion() final String expectedSrcNs = minecraftProvider.isLegacyVersion()
? MappingsNamespace.INTERMEDIARY.toString() // <1.3 ? MappingsNamespace.INTERMEDIARY.toString() // <1.3
: MappingsNamespace.OFFICIAL.toString(); // >=1.3 : MappingsNamespace.OFFICIAL.toString(); // >=1.3
return new IntermediateMappingsService(intermediaryTiny, expectedSrcNs); return TYPE.create(project, options -> {
options.getIntermediaryTiny().set(intermediaryTiny.toFile());
options.getExpectedSrcNs().set(expectedSrcNs);
options.getMinecraftVersion().set(intermediateProvider.getMinecraftVersion());
});
} }
private MemoryMappingTree createMemoryMappingTree() { private MemoryMappingTree createMemoryMappingTree() {
return createMemoryMappingTree(getIntermediaryTiny(), getOptions().getExpectedSrcNs().get());
}
@VisibleForTesting
public static MemoryMappingTree createMemoryMappingTree(Path mappingFile, String expectedSrcNs) {
final MemoryMappingTree tree = new MemoryMappingTree(); final MemoryMappingTree tree = new MemoryMappingTree();
try { try {
MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true); MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true);
try (BufferedReader reader = Files.newBufferedReader(getIntermediaryTiny(), StandardCharsets.UTF_8)) { try (BufferedReader reader = Files.newBufferedReader(mappingFile, StandardCharsets.UTF_8)) {
Tiny2FileReader.read(reader, nsCompleter); Tiny2FileReader.read(reader, nsCompleter);
} }
} catch (IOException e) { } catch (IOException e) {
@@ -120,6 +144,6 @@ public final class IntermediateMappingsService implements SharedService {
} }
public Path getIntermediaryTiny() { public Path getIntermediaryTiny() {
return Objects.requireNonNull(intermediaryTiny, "Intermediary mappings have not been setup"); return getOptions().getIntermediaryTiny().get().getAsFile().toPath();
} }
} }

View File

@@ -47,9 +47,15 @@ import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import dev.architectury.loom.util.MappingOption; import dev.architectury.loom.util.MappingOption;
import dev.architectury.loom.util.MappingOption;
import net.fabricmc.loom.util.service.ServiceFactory;
import org.apache.tools.ant.util.StringUtils; import org.apache.tools.ant.util.StringUtils;
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.provider.Provider;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -68,8 +74,7 @@ import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DeletingFileVisitor; import net.fabricmc.loom.util.DeletingFileVisitor;
import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.SharedServiceManager;
import net.fabricmc.loom.util.srg.ForgeMappingsMerger; import net.fabricmc.loom.util.srg.ForgeMappingsMerger;
import net.fabricmc.loom.util.srg.MCPReader; import net.fabricmc.loom.util.srg.MCPReader;
import net.fabricmc.loom.util.srg.SrgNamedWriter; import net.fabricmc.loom.util.srg.SrgNamedWriter;
@@ -119,7 +124,7 @@ public class MappingConfiguration {
this.mappingOptions.put(MappingOption.DEFAULT, () -> this.tinyMappings); this.mappingOptions.put(MappingOption.DEFAULT, () -> this.tinyMappings);
} }
public static MappingConfiguration create(Project project, SharedServiceManager serviceManager, DependencyInfo dependency, MinecraftProvider minecraftProvider) { public static MappingConfiguration create(Project project, ServiceFactory serviceFactory, DependencyInfo dependency, MinecraftProvider minecraftProvider) {
final String version = dependency.getResolvedVersion(); final String version = dependency.getResolvedVersion();
final Path inputJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not resolve mappings: " + dependency)).toPath(); final Path inputJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not resolve mappings: " + dependency)).toPath();
final String mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged"); final String mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");
@@ -146,29 +151,25 @@ public class MappingConfiguration {
final Path workingDir = minecraftProvider.dir(mappingsIdentifier).toPath(); final Path workingDir = minecraftProvider.dir(mappingsIdentifier).toPath();
MappingConfiguration mappingConfiguration; MappingConfiguration mappingProvider;
if (extension.isForgeLike()) { if (extension.isForgeLike()) {
mappingConfiguration = new ForgeMigratedMappingConfiguration(mappingsIdentifier, workingDir); mappingProvider = new ForgeMigratedMappingConfiguration(mappingsIdentifier, workingDir);
} else { } else {
mappingConfiguration = new MappingConfiguration(mappingsIdentifier, workingDir); mappingProvider = new MappingConfiguration(mappingsIdentifier, workingDir);
} }
try { try {
mappingConfiguration.setup(project, serviceManager, minecraftProvider, inputJar); mappingProvider.setup(project, serviceFactory, minecraftProvider, inputJar);
} catch (IOException e) { } catch (IOException e) {
cleanWorkingDirectory(workingDir); cleanWorkingDirectory(workingDir);
throw new UncheckedIOException("Failed to setup mappings: " + dependency.getDepString(), e); throw new UncheckedIOException("Failed to setup mappings: " + dependency.getDepString(), e);
} }
return mappingConfiguration; return mappingProvider;
} }
public TinyMappingsService getMappingsService(SharedServiceManager serviceManager) { public Path getMappingsPath(MappingOption mappingOption) {
return getMappingsService(serviceManager, MappingOption.DEFAULT);
}
public TinyMappingsService getMappingsService(SharedServiceManager serviceManager, MappingOption mappingOption) {
Supplier<Path> mappingsSupplier = this.mappingOptions.get(mappingOption); Supplier<Path> mappingsSupplier = this.mappingOptions.get(mappingOption);
if (mappingsSupplier == null) { if (mappingsSupplier == null) {
@@ -177,16 +178,32 @@ public class MappingConfiguration {
throw new UnsupportedOperationException("Mapping option " + mappingOption + " found but file does not exist!"); throw new UnsupportedOperationException("Mapping option " + mappingOption + " found but file does not exist!");
} }
return TinyMappingsService.create(serviceManager, Objects.requireNonNull(mappingsSupplier.get())); return Objects.requireNonNull(mappingsSupplier.get());
} }
protected void setup(Project project, SharedServiceManager serviceManager, MinecraftProvider minecraftProvider, Path inputJar) throws IOException { public Provider<TinyMappingsService.Options> getMappingsServiceOptions(Project project) {
return getMappingsServiceOptions(project, MappingOption.DEFAULT);
}
public Provider<TinyMappingsService.Options> getMappingsServiceOptions(Project project, MappingOption mappingOption) {
return TinyMappingsService.createOptions(project, Objects.requireNonNull(getMappingsPath(mappingOption)));
}
public TinyMappingsService getMappingsService(Project project, ServiceFactory serviceFactory) {
return serviceFactory.get(getMappingsServiceOptions(project));
}
public TinyMappingsService getMappingsService(Project project, ServiceFactory serviceFactory, MappingOption mappingOption) {
return serviceFactory.get(getMappingsServiceOptions(project, mappingOption));
}
protected void setup(Project project, ServiceFactory serviceFactory, MinecraftProvider minecraftProvider, Path inputJar) throws IOException {
if (minecraftProvider.refreshDeps()) { if (minecraftProvider.refreshDeps()) {
cleanWorkingDirectory(mappingsWorkingDir); cleanWorkingDirectory(mappingsWorkingDir);
} }
if (Files.notExists(tinyMappings) || minecraftProvider.refreshDeps()) { if (Files.notExists(tinyMappings) || minecraftProvider.refreshDeps()) {
storeMappings(project, serviceManager, minecraftProvider, inputJar); storeMappings(project, serviceFactory, minecraftProvider, inputJar);
} else { } else {
try (FileSystemUtil.Delegate fileSystem = FileSystemUtil.getJarFileSystem(inputJar, false)) { try (FileSystemUtil.Delegate fileSystem = FileSystemUtil.getJarFileSystem(inputJar, false)) {
extractExtras(fileSystem.get()); extractExtras(fileSystem.get());
@@ -318,12 +335,12 @@ public class MappingConfiguration {
return isV2 ? "-v2" : ""; return isV2 ? "-v2" : "";
} }
private void storeMappings(Project project, SharedServiceManager serviceManager, MinecraftProvider minecraftProvider, Path inputJar) throws IOException { private void storeMappings(Project project, ServiceFactory serviceFactory, MinecraftProvider minecraftProvider, Path inputJar) throws IOException {
LOGGER.info(":extracting " + inputJar.getFileName()); LOGGER.info(":extracting " + inputJar.getFileName());
if (isMCP(inputJar)) { if (isMCP(inputJar)) {
try { try {
readAndMergeMCP(project, serviceManager, minecraftProvider, inputJar); readAndMergeMCP(project, serviceFactory, minecraftProvider, inputJar);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -338,7 +355,7 @@ public class MappingConfiguration {
if (areMappingsV2(baseTinyMappings)) { if (areMappingsV2(baseTinyMappings)) {
// These are unmerged v2 mappings // These are unmerged v2 mappings
IntermediateMappingsService intermediateMappingsService = IntermediateMappingsService.getInstance(serviceManager, project, minecraftProvider); IntermediateMappingsService intermediateMappingsService = serviceFactory.get(IntermediateMappingsService.createOptions(project, minecraftProvider));
MappingsMerger.mergeAndSaveMappings(baseTinyMappings, tinyMappings, minecraftProvider, intermediateMappingsService); MappingsMerger.mergeAndSaveMappings(baseTinyMappings, tinyMappings, minecraftProvider, intermediateMappingsService);
} else { } else {
@@ -365,7 +382,7 @@ public class MappingConfiguration {
} }
} }
private void readAndMergeMCP(Project project, SharedServiceManager serviceManager, MinecraftProvider minecraftProvider, Path mcpJar) throws Exception { private void readAndMergeMCP(Project project, ServiceFactory serviceFactory, MinecraftProvider minecraftProvider, Path mcpJar) throws Exception {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
IntermediateMappingsService intermediateMappingsService = IntermediateMappingsService.getInstance(serviceManager, project, minecraftProvider); IntermediateMappingsService intermediateMappingsService = IntermediateMappingsService.getInstance(serviceManager, project, minecraftProvider);
Path intermediaryTinyPath = intermediateMappingsService.getIntermediaryTiny(); Path intermediaryTinyPath = intermediateMappingsService.getIntermediaryTiny();

View File

@@ -27,29 +27,47 @@ package net.fabricmc.loom.configuration.providers.mappings;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.function.Supplier;
import net.fabricmc.loom.util.service.SharedService; import com.google.common.base.Suppliers;
import net.fabricmc.loom.util.service.SharedServiceManager; import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.InputFile;
import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
public final class TinyMappingsService implements SharedService { public final class TinyMappingsService extends Service<TinyMappingsService.Options> {
private final MemoryMappingTree mappingTree; public static final ServiceType<Options, TinyMappingsService> TYPE = new ServiceType<>(Options.class, TinyMappingsService.class);
public TinyMappingsService(Path tinyMappings) { public interface Options extends Service.Options {
@InputFile
RegularFileProperty getMappings();
}
public static Provider<Options> createOptions(Project project, Path mappings) {
return TYPE.create(project, options -> options.getMappings().set(project.file(mappings)));
}
public TinyMappingsService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
}
private final Supplier<MemoryMappingTree> mappingTree = Suppliers.memoize(() -> {
try { try {
this.mappingTree = new MemoryMappingTree(); MemoryMappingTree mappingTree = new MemoryMappingTree();
MappingReader.read(tinyMappings, mappingTree); MappingReader.read(getOptions().getMappings().get().getAsFile().toPath(), mappingTree);
return mappingTree;
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException("Failed to read mappings", e); throw new UncheckedIOException("Failed to read mappings", e);
} }
} });
public static synchronized TinyMappingsService create(SharedServiceManager serviceManager, Path tinyMappings) {
return serviceManager.getOrCreateService("TinyMappingsService:" + tinyMappings.toAbsolutePath(), () -> new TinyMappingsService(tinyMappings));
}
public MemoryMappingTree getMappingTree() { public MemoryMappingTree getMappingTree() {
return mappingTree; return mappingTree.get();
} }
} }

View File

@@ -37,7 +37,7 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.api.TrClass; import net.fabricmc.tinyremapper.api.TrClass;
@@ -56,7 +56,7 @@ public record SignatureFixerApplyVisitor(Map<String, String> signatureFixes) imp
}; };
} }
public static Map<String, String> getRemappedSignatures(boolean toIntermediary, MappingConfiguration mappingConfiguration, Project project, SharedServiceManager serviceManager, String targetNamespace) throws IOException { public static Map<String, String> getRemappedSignatures(boolean toIntermediary, MappingConfiguration mappingConfiguration, Project project, ServiceFactory serviceFactory, String targetNamespace) throws IOException {
if (mappingConfiguration.getSignatureFixes() == null) { if (mappingConfiguration.getSignatureFixes() == null) {
// No fixes // No fixes
return Collections.emptyMap(); return Collections.emptyMap();
@@ -69,7 +69,7 @@ public record SignatureFixerApplyVisitor(Map<String, String> signatureFixes) imp
// Remap the sig fixes from intermediary to the target namespace // Remap the sig fixes from intermediary to the target namespace
final Map<String, String> remapped = new HashMap<>(); final Map<String, String> remapped = new HashMap<>();
final TinyRemapper sigTinyRemapper = TinyRemapperHelper.getTinyRemapper(project, serviceManager, MappingsNamespace.INTERMEDIARY.toString(), targetNamespace); final TinyRemapper sigTinyRemapper = TinyRemapperHelper.getTinyRemapper(project, serviceFactory, MappingsNamespace.INTERMEDIARY.toString(), targetNamespace);
final Remapper sigAsmRemapper = sigTinyRemapper.getEnvironment().getRemapper(); final Remapper sigAsmRemapper = sigTinyRemapper.getEnvironment().getRemapper();
// Remap the class names and the signatures using a new tiny remapper instance. // Remap the class names and the signatures using a new tiny remapper instance.

View File

@@ -56,7 +56,6 @@ import net.fabricmc.loom.configuration.providers.minecraft.SignatureFixerApplyVi
import net.fabricmc.loom.extension.LoomFiles; import net.fabricmc.loom.extension.LoomFiles;
import net.fabricmc.loom.util.SidedClassVisitor; import net.fabricmc.loom.util.SidedClassVisitor;
import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
import net.fabricmc.loom.util.srg.InnerClassRemapper; import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.RemapObjectHolderVisitor; import net.fabricmc.loom.util.srg.RemapObjectHolderVisitor;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
@@ -206,11 +205,11 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
Files.deleteIfExists(remappedJars.outputJarPath()); Files.deleteIfExists(remappedJars.outputJarPath());
final Set<String> classNames = extension.isForgeLike() ? InnerClassRemapper.readClassNames(remappedJars.inputJar()) : Set.of(); final Set<String> classNames = extension.isForgeLike() ? InnerClassRemapper.readClassNames(remappedJars.inputJar()) : Set.of();
final Map<String, String> remappedSignatures = SignatureFixerApplyVisitor.getRemappedSignatures(getTargetNamespace() == MappingsNamespace.INTERMEDIARY, mappingConfiguration, getProject(), configContext.serviceManager(), toM); final Map<String, String> remappedSignatures = SignatureFixerApplyVisitor.getRemappedSignatures(getTargetNamespace() == MappingsNamespace.INTERMEDIARY, mappingConfiguration, getProject(), configContext.serviceFactory(), toM);
final MinecraftVersionMeta.JavaVersion javaVersion = minecraftProvider.getVersionInfo().javaVersion(); final MinecraftVersionMeta.JavaVersion javaVersion = minecraftProvider.getVersionInfo().javaVersion();
final boolean fixRecords = javaVersion != null && javaVersion.majorVersion() >= 16; final boolean fixRecords = javaVersion != null && javaVersion.majorVersion() >= 16;
TinyRemapper remapper = TinyRemapperHelper.getTinyRemapper(getProject(), configContext.serviceManager(), fromM, toM, fixRecords, (builder) -> { TinyRemapper remapper = TinyRemapperHelper.getTinyRemapper(getProject(), configContext.serviceFactory(), fromM, toM, fixRecords, (builder) -> {
builder.extraPostApplyVisitor(new SignatureFixerApplyVisitor(remappedSignatures)); builder.extraPostApplyVisitor(new SignatureFixerApplyVisitor(remappedSignatures));
if (extension.isNeoForge()) builder.extension(new MixinExtension(inputTag -> true)); if (extension.isNeoForge()) builder.extension(new MixinExtension(inputTag -> true));
configureRemapper(remappedJars, builder); configureRemapper(remappedJars, builder);
@@ -234,21 +233,19 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
getMavenHelper(remappedJars.type()).savePom(); getMavenHelper(remappedJars.type()).savePom();
if (extension.isForgeLikeAndOfficial()) { if (extension.isForgeLikeAndOfficial()) {
try (var serviceManager = new ScopedSharedServiceManager()) { final MappingOption mappingOption = MappingOption.forPlatform(extension);
final MappingOption mappingOption = MappingOption.forPlatform(extension); final TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(project, configContext.serviceFactory(), mappingOption);
final TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(serviceManager, mappingOption); final String className;
final String className;
if (extension.isNeoForge()) { if (extension.isNeoForge()) {
className = "net.neoforged.neoforge.registries.ObjectHolderRegistry"; className = "net.neoforged.neoforge.registries.ObjectHolderRegistry";
} else { } else {
className = "net.minecraftforge.registries.ObjectHolderRegistry"; className = "net.minecraftforge.registries.ObjectHolderRegistry";
}
final String sourceNamespace = IntermediaryNamespaces.runtimeIntermediary(project);
final MemoryMappingTree mappings = mappingsService.getMappingTree();
RemapObjectHolderVisitor.remapObjectHolder(remappedJars.outputJar().getPath(), className, mappings, sourceNamespace, "named");
} }
final String sourceNamespace = IntermediaryNamespaces.runtimeIntermediary(project);
final MemoryMappingTree mappings = mappingsService.getMappingTree();
RemapObjectHolderVisitor.remapObjectHolder(remappedJars.outputJar().getPath(), className, mappings, sourceNamespace, "named");
} }
} }

View File

@@ -46,8 +46,8 @@ import org.apache.commons.io.output.NullOutputStream;
import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury; import org.cadixdev.mercury.Mercury;
import org.cadixdev.mercury.remapper.MercuryRemapper; import org.cadixdev.mercury.remapper.MercuryRemapper;
import org.jetbrains.annotations.Nullable;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
@@ -63,12 +63,11 @@ import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.ThreadingUtils; import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.SharedServiceManager;
import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.lorenztiny.TinyMappingsReader;
public class ForgeSourcesRemapper { public class ForgeSourcesRemapper {
public static void addBaseForgeSources(Project project) throws IOException { public static void addBaseForgeSources(Project project, ServiceFactory serviceFactory) throws IOException {
List<Path> minecraftJars = LoomGradleExtension.get(project).getMinecraftJars(MappingsNamespace.NAMED); List<Path> minecraftJars = LoomGradleExtension.get(project).getMinecraftJars(MappingsNamespace.NAMED);
Path minecraftJar; Path minecraftJar;
@@ -85,18 +84,16 @@ public class ForgeSourcesRemapper {
Path sourcesJar = GenerateSourcesTask.getJarFileWithSuffix("-sources.jar", minecraftJar).toPath(); Path sourcesJar = GenerateSourcesTask.getJarFileWithSuffix("-sources.jar", minecraftJar).toPath();
if (!Files.exists(sourcesJar)) { if (!Files.exists(sourcesJar)) {
try (var serviceManager = new ScopedSharedServiceManager()) { addForgeSources(project, serviceFactory, minecraftJar, sourcesJar);
addForgeSources(project, serviceManager, minecraftJar, sourcesJar);
}
} }
} }
public static void addForgeSources(Project project, SharedServiceManager serviceManager, @Nullable Path inputJar, Path sourcesJar) throws IOException { public static void addForgeSources(Project project, ServiceFactory serviceFactory, @Nullable Path inputJar, Path sourcesJar) throws IOException {
try (FileSystemUtil.Delegate inputFs = inputJar == null ? null : FileSystemUtil.getJarFileSystem(inputJar, true); try (FileSystemUtil.Delegate inputFs = inputJar == null ? null : FileSystemUtil.getJarFileSystem(inputJar, true);
FileSystemUtil.Delegate outputFs = FileSystemUtil.getJarFileSystem(sourcesJar, true)) { FileSystemUtil.Delegate outputFs = FileSystemUtil.getJarFileSystem(sourcesJar, true)) {
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter(); ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
provideForgeSources(project, serviceManager, path -> { provideForgeSources(project, serviceFactory, path -> {
Path inputPath = inputFs == null ? null : inputFs.get().getPath(path.replace(".java", ".class")); Path inputPath = inputFs == null ? null : inputFs.get().getPath(path.replace(".java", ".class"));
if (inputPath != null && Files.notExists(inputPath)) { if (inputPath != null && Files.notExists(inputPath)) {
@@ -126,7 +123,7 @@ public class ForgeSourcesRemapper {
} }
} }
public static void provideForgeSources(Project project, SharedServiceManager serviceManager, Predicate<String> classFilter, BiConsumer<String, byte[]> consumer) throws IOException { public static void provideForgeSources(Project project, ServiceFactory serviceFactory, Predicate<String> classFilter, BiConsumer<String, byte[]> consumer) throws IOException {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
String sourceDependency = extension.getForgeUserdevProvider().getConfig().sources(); String sourceDependency = extension.getForgeUserdevProvider().getConfig().sources();
List<Path> forgeInstallerSources = new ArrayList<>(); List<Path> forgeInstallerSources = new ArrayList<>();
@@ -140,11 +137,11 @@ public class ForgeSourcesRemapper {
Map<String, byte[]> forgeSources = extractSources(forgeInstallerSources); Map<String, byte[]> forgeSources = extractSources(forgeInstallerSources);
forgeSources.keySet().removeIf(classFilter.negate()); forgeSources.keySet().removeIf(classFilter.negate());
project.getLogger().lifecycle(":extracted {} forge source classes", forgeSources.size()); project.getLogger().lifecycle(":extracted {} forge source classes", forgeSources.size());
remapSources(project, serviceManager, forgeSources); remapSources(project, serviceFactory, forgeSources);
forgeSources.forEach(consumer); forgeSources.forEach(consumer);
} }
private static void remapSources(Project project, SharedServiceManager serviceManager, Map<String, byte[]> sources) throws IOException { private static void remapSources(Project project, ServiceFactory serviceFactory, Map<String, byte[]> sources) throws IOException {
File tmpInput = File.createTempFile("tmpInputForgeSources", null); File tmpInput = File.createTempFile("tmpInputForgeSources", null);
tmpInput.delete(); tmpInput.delete();
tmpInput.deleteOnExit(); tmpInput.deleteOnExit();
@@ -178,7 +175,7 @@ public class ForgeSourcesRemapper {
System.setErr(new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM)); System.setErr(new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM));
} }
remapForgeSourcesInner(project, serviceManager, tmpInput.toPath(), tmpOutput.toPath()); remapForgeSourcesInner(project, serviceFactory, tmpInput.toPath(), tmpOutput.toPath());
if (!ForgeToolExecutor.shouldShowVerboseStderr(project)) { if (!ForgeToolExecutor.shouldShowVerboseStderr(project)) {
System.setOut(out); System.setOut(out);
@@ -215,13 +212,13 @@ public class ForgeSourcesRemapper {
} }
} }
private static void remapForgeSourcesInner(Project project, SharedServiceManager serviceManager, Path tmpInput, Path tmpOutput) throws IOException { private static void remapForgeSourcesInner(Project project, ServiceFactory serviceFactory, Path tmpInput, Path tmpOutput) throws IOException {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false); Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false);
final MappingOption mappingOption = MappingOption.forPlatform(extension); final MappingOption mappingOption = MappingOption.forPlatform(extension);
final String sourceNamespace = IntermediaryNamespaces.intermediary(project); final String sourceNamespace = IntermediaryNamespaces.intermediary(project);
TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(serviceManager, mappingOption); TinyMappingsService mappingsService = extension.getMappingConfiguration().getMappingsService(project, serviceFactory, mappingOption);
MappingSet mappings = new TinyMappingsReader(mappingsService.getMappingTree(), sourceNamespace, "named").read(); MappingSet mappings = new TinyMappingsReader(mappingsService.getMappingTree(), sourceNamespace, "named").read();
for (Map.Entry<String, String> entry : TinyRemapperHelper.JSR_TO_JETBRAINS.entrySet()) { for (Map.Entry<String, String> entry : TinyRemapperHelper.JSR_TO_JETBRAINS.entrySet()) {

View File

@@ -484,7 +484,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
holder = objectFactory.newInstance(RemapperExtensionHolder.class, RemapperParameters.None.INSTANCE); holder = objectFactory.newInstance(RemapperExtensionHolder.class, RemapperParameters.None.INSTANCE);
} }
holder.getRemapperExtensionClass().set(remapperExtensionClass); holder.getRemapperExtensionClass().set(remapperExtensionClass.getName());
remapperExtensions.add(holder); remapperExtensions.add(holder);
} }

View File

@@ -24,12 +24,12 @@
package net.fabricmc.loom.extension; package net.fabricmc.loom.extension;
import java.lang.reflect.Constructor;
import javax.inject.Inject; import javax.inject.Inject;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
@@ -43,25 +43,19 @@ import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.api.TrClass; import net.fabricmc.tinyremapper.api.TrClass;
public abstract class RemapperExtensionHolder { public abstract class RemapperExtensionHolder {
// Null when RemapperParameters.None.class
private final RemapperParameters remapperParameters;
@Inject @Inject
public RemapperExtensionHolder(RemapperParameters remapperParameters) { public RemapperExtensionHolder(RemapperParameters remapperParameters) {
this.remapperParameters = remapperParameters; this.getRemapperParameters().set(remapperParameters);
} }
@Input @Input
public abstract Property<Class<? extends RemapperExtension<?>>> getRemapperExtensionClass(); public abstract Property<String> getRemapperExtensionClass();
@Nested
@Optional @Optional
public RemapperParameters getRemapperParameters() { public abstract Property<RemapperParameters> getRemapperParameters();
return remapperParameters;
}
public void apply(TinyRemapper.Builder tinyRemapperBuilder, String sourceNamespace, String targetNamespace, ObjectFactory objectFactory) { public void apply(TinyRemapper.Builder tinyRemapperBuilder, String sourceNamespace, String targetNamespace) {
final RemapperExtension<?> remapperExtension = newInstance(objectFactory); final RemapperExtension<?> remapperExtension = newInstance();
tinyRemapperBuilder.extraPostApplyVisitor(new RemapperExtensionImpl(remapperExtension, sourceNamespace, targetNamespace)); tinyRemapperBuilder.extraPostApplyVisitor(new RemapperExtensionImpl(remapperExtension, sourceNamespace, targetNamespace));
@@ -86,20 +80,41 @@ public abstract class RemapperExtensionHolder {
} }
} }
private RemapperExtension<?> newInstance(ObjectFactory objectFactory) { private RemapperExtension<?> newInstance() {
try { try {
Class<? extends RemapperExtension<?>> remapperExtensionClass = getRemapperExtensionClass().get(); //noinspection unchecked
final Class<? extends RemapperExtension<?>> remapperExtensionClass = (Class<? extends RemapperExtension<?>>) Class.forName(getRemapperExtensionClass().get());
final Constructor<?> constructor = getInjectedConstructor(remapperExtensionClass);
if (remapperParameters == RemapperParameters.None.INSTANCE) { if (getRemapperParameters().get() instanceof RemapperParameters.None) {
return objectFactory.newInstance(remapperExtensionClass); return (RemapperExtension<?>) constructor.newInstance();
} }
return objectFactory.newInstance(remapperExtensionClass, remapperParameters); return (RemapperExtension<?>) constructor.newInstance(getRemapperParameters().get());
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Failed to create remapper extension", e); throw new RuntimeException("Failed to create remapper extension for class: " + getRemapperExtensionClass().get(), e);
} }
} }
private static Constructor<?> getInjectedConstructor(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getConstructors();
Constructor<?> injectedConstructor = null;
for (Constructor<?> constructor : constructors) {
if (injectedConstructor != null) {
throw new RuntimeException("RemapperExtension class " + clazz.getName() + " has more than one constructor");
}
injectedConstructor = constructor;
}
if (injectedConstructor == null) {
throw new RuntimeException("RemapperExtension class " + clazz.getName() + " does not have a constructor");
}
return injectedConstructor;
}
private static final class RemapperExtensionImpl implements TinyRemapper.ApplyVisitorProvider { private static final class RemapperExtensionImpl implements TinyRemapper.ApplyVisitorProvider {
private final RemapperExtension<?> remapperExtension; private final RemapperExtension<?> remapperExtension;
private final String sourceNamespace; private final String sourceNamespace;

View File

@@ -230,7 +230,7 @@ public abstract class AbstractRemapJarTask extends Jar {
return getInputFile(); return getInputFile();
} }
protected static List<String> getRootPaths(Set<File> files) { public static List<String> getRootPaths(Set<File> files) {
return files.stream() return files.stream()
.map(root -> { .map(root -> {
String rootPath = root.getAbsolutePath().replace("\\", "/"); String rootPath = root.getAbsolutePath().replace("\\", "/");
@@ -243,7 +243,7 @@ public abstract class AbstractRemapJarTask extends Jar {
}).toList(); }).toList();
} }
protected static Function<File, String> relativePath(List<String> rootPaths) { public static Function<File, String> relativePath(List<String> rootPaths) {
return file -> { return file -> {
String s = file.getAbsolutePath().replace("\\", "/"); String s = file.getAbsolutePath().replace("\\", "/");

View File

@@ -109,7 +109,7 @@ import net.fabricmc.loom.util.gradle.ThreadedSimpleProgressLogger;
import net.fabricmc.loom.util.gradle.WorkerDaemonClientsManagerHelper; import net.fabricmc.loom.util.gradle.WorkerDaemonClientsManagerHelper;
import net.fabricmc.loom.util.ipc.IPCClient; import net.fabricmc.loom.util.ipc.IPCClient;
import net.fabricmc.loom.util.ipc.IPCServer; import net.fabricmc.loom.util.ipc.IPCServer;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.ScopedServiceFactory;
import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.tiny.Tiny2FileWriter; import net.fabricmc.mappingio.format.tiny.Tiny2FileWriter;
@@ -509,8 +509,8 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
private MinecraftJar rebuildInputJar() { private MinecraftJar rebuildInputJar() {
final List<MinecraftJar> minecraftJars; final List<MinecraftJar> minecraftJars;
try (var serviceManager = new ScopedSharedServiceManager()) { try (var serviceFactory = new ScopedServiceFactory()) {
final var configContext = new ConfigContextImpl(getProject(), serviceManager, getExtension()); final var configContext = new ConfigContextImpl(getProject(), serviceFactory, getExtension());
final var provideContext = new AbstractMappedMinecraftProvider.ProvideContext(false, true, configContext); final var provideContext = new AbstractMappedMinecraftProvider.ProvideContext(false, true, configContext);
minecraftJars = getExtension().getNamedMinecraftProvider().provide(provideContext); minecraftJars = getExtension().getNamedMinecraftProvider().provide(provideContext);
} catch (Exception e) { } catch (Exception e) {
@@ -764,9 +764,11 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
if (minecraftJarProcessorManager != null) { if (minecraftJarProcessorManager != null) {
mappingsProcessors.add(mappings -> { mappingsProcessors.add(mappings -> {
try (var serviceManager = new ScopedSharedServiceManager()) { try (var serviceFactory = new ScopedServiceFactory()) {
final var configContext = new ConfigContextImpl(getProject(), serviceManager, getExtension()); final var configContext = new ConfigContextImpl(getProject(), serviceFactory, getExtension());
return minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl(configContext)); return minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl(configContext));
} catch (IOException e) {
throw new UncheckedIOException(e);
} }
}); });
} }

View File

@@ -57,7 +57,7 @@ import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsFactory
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.ScopedServiceFactory;
import net.fabricmc.lorenztiny.TinyMappingsJoiner; import net.fabricmc.lorenztiny.TinyMappingsJoiner;
import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
@@ -110,8 +110,8 @@ public abstract class MigrateMappingsTask extends AbstractLoomTask {
File mappings = loadMappings(); File mappings = loadMappings();
MappingConfiguration mappingConfiguration = extension.getMappingConfiguration(); MappingConfiguration mappingConfiguration = extension.getMappingConfiguration();
try (var serviceManager = new ScopedSharedServiceManager()) { try (var serviceFactory = new ScopedServiceFactory()) {
MemoryMappingTree currentMappings = mappingConfiguration.getMappingsService(serviceManager).getMappingTree(); MemoryMappingTree currentMappings = mappingConfiguration.getMappingsService(project, serviceFactory).getMappingTree();
MemoryMappingTree targetMappings = getMappings(mappings); MemoryMappingTree targetMappings = getMappings(mappings);
migrateMappings(project, extension, inputDir, outputDir, currentMappings, targetMappings); migrateMappings(project, extension, inputDir, outputDir, currentMappings, targetMappings);
project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath()); project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath());

View File

@@ -25,18 +25,14 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.inject.Inject; import javax.inject.Inject;
@@ -50,11 +46,10 @@ import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.SetProperty; import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.TaskProvider;
@@ -71,8 +66,8 @@ import net.fabricmc.loom.build.nesting.JarNester;
import net.fabricmc.loom.build.nesting.NestableJarGenerationTask; import net.fabricmc.loom.build.nesting.NestableJarGenerationTask;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
import net.fabricmc.loom.configuration.mods.ArtifactMetadata; import net.fabricmc.loom.configuration.mods.ArtifactMetadata;
import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.task.service.MappingsService; import net.fabricmc.loom.task.service.MappingsService;
import net.fabricmc.loom.task.service.MixinRefmapService;
import net.fabricmc.loom.task.service.TinyRemapperService; import net.fabricmc.loom.task.service.TinyRemapperService;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.ExceptionUtil; import net.fabricmc.loom.util.ExceptionUtil;
@@ -80,11 +75,10 @@ import net.fabricmc.loom.util.ModPlatform;
import net.fabricmc.loom.util.Pair; import net.fabricmc.loom.util.Pair;
import net.fabricmc.loom.util.SidedClassVisitor; import net.fabricmc.loom.util.SidedClassVisitor;
import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.fmj.FabricModJson;
import net.fabricmc.loom.util.fmj.FabricModJsonFactory; import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
import net.fabricmc.loom.util.fmj.FabricModJsonUtils; import net.fabricmc.loom.util.fmj.FabricModJsonUtils;
import net.fabricmc.loom.util.service.BuildSharedServiceManager; import net.fabricmc.loom.util.service.ScopedServiceFactory;
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyRemapper;
@@ -137,13 +131,14 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
@Input @Input
@ApiStatus.Internal @ApiStatus.Internal
public abstract Property<Boolean> getUseMixinAP(); public abstract Property<Boolean> getUseMixinAP();
@Nested
private final Provider<BuildSharedServiceManager> serviceManagerProvider; public abstract Property<TinyRemapperService.Options> getTinyRemapperServiceOptions();
@Nested
public abstract ListProperty<MixinRefmapService.Options> getMixinRefmapServiceOptions();
@Inject @Inject
public RemapJarTask() { public RemapJarTask() {
super(); super();
serviceManagerProvider = BuildSharedServiceManager.createForTask(this, getBuildEventsListenerRegistry());
final ConfigurationContainer configurations = getProject().getConfigurations(); final ConfigurationContainer configurations = getProject().getConfigurations();
getClasspath().from(configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME)); getClasspath().from(configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME));
getAddNestedDependencies().convention(true).finalizeValueOnRead(); getAddNestedDependencies().convention(true).finalizeValueOnRead();
@@ -162,6 +157,9 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
setPreserveFileTimestamps(false); setPreserveFileTimestamps(false);
getJarType().set("classes"); getJarType().set("classes");
getTinyRemapperServiceOptions().set(TinyRemapperService.createOptions(this));
getMixinRefmapServiceOptions().set(MixinRefmapService.createOptions(this));
} }
@TaskAction @TaskAction
@@ -174,16 +172,14 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
} }
if (!params.namespacesMatch()) { if (!params.namespacesMatch()) {
params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getTinyRemapperService())); params.getTinyRemapperServiceOptions().set(getTinyRemapperServiceOptions());
params.getMixinRefmapServiceOptions().set(getMixinRefmapServiceOptions());
params.getRemapClasspath().from(getClasspath()); params.getRemapClasspath().from(getClasspath());
final boolean mixinAp = getUseMixinAP().get(); final boolean mixinAp = getUseMixinAP().get();
params.getUseMixinExtension().set(!mixinAp); params.getUseMixinExtension().set(!mixinAp);
if (mixinAp) {
setupLegacyMixinRefmapRemapping(params);
}
// Add the mixin refmap remap type to the manifest // Add the mixin refmap remap type to the manifest
// This is used by the mod dependency remapper to determine if it should remap the refmap // This is used by the mod dependency remapper to determine if it should remap the refmap
// or if the refmap should be remapped by mixin at runtime. // or if the refmap should be remapped by mixin at runtime.
@@ -199,56 +195,17 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
params.getInjectAccessWidener().set(extension.getAccessWidenerPath()); params.getInjectAccessWidener().set(extension.getAccessWidenerPath());
} }
params.getMappingBuildServiceUuid().convention("this should be unavailable!"); params.getReadMixinConfigsFromManifest().set(getReadMixinConfigsFromManifest());
params.getAtAccessWideners().set(getAtAccessWideners()); params.getAtAccessWideners().set(getAtAccessWideners());
if (!getAtAccessWideners().get().isEmpty()) { if (!getAtAccessWideners().get().isEmpty()) {
params.getMappingBuildServiceUuid().set(UnsafeWorkQueueHelper.create(MappingsService.createDefault(getProject(), serviceManagerProvider.get().get(), getSourceNamespace().get(), getTargetNamespace().get()))); params.getMappingsServiceOptions().set(MappingsService.createOptionsWithProjectMappings(getProject(), getSourceNamespace(), getTargetNamespace()));
} }
params.getOptimizeFmj().set(getOptimizeFabricModJson().get()); params.getOptimizeFmj().set(getOptimizeFabricModJson().get());
}); });
} }
private void setupLegacyMixinRefmapRemapping(RemapParams params) {
final LoomGradleExtension extension = LoomGradleExtension.get(getProject());
final MixinExtension mixinExtension = extension.getMixin();
final Collection<String> allMixinConfigs = new LinkedHashSet<>();
final FabricModJson fabricModJson = FabricModJsonFactory.createFromZipNullable(getInputFile().getAsFile().get().toPath());
if (fabricModJson != null) {
allMixinConfigs.addAll(fabricModJson.getMixinConfigurations());
}
if (getReadMixinConfigsFromManifest().get()) {
allMixinConfigs.addAll(ModBuildExtensions.readMixinConfigsFromManifest(getInputFile().get().getAsFile()));
}
if (allMixinConfigs.isEmpty()) {
return;
}
for (SourceSet sourceSet : mixinExtension.getMixinSourceSets()) {
MixinExtension.MixinInformationContainer container = Objects.requireNonNull(
MixinExtension.getMixinInformationContainer(sourceSet)
);
final List<String> rootPaths = getRootPaths(sourceSet.getResources().getSrcDirs());
final String refmapName = container.refmapNameProvider().get();
final List<String> mixinConfigs = container.sourceSet().getResources()
.matching(container.mixinConfigPattern())
.getFiles()
.stream()
.map(relativePath(rootPaths))
.filter(allMixinConfigs::contains)
.toList();
params.getMixinData().add(new RemapParams.RefmapData(mixinConfigs, refmapName));
}
}
public interface RemapParams extends AbstractRemapParams { public interface RemapParams extends AbstractRemapParams {
ConfigurableFileCollection getNestedJars(); ConfigurableFileCollection getNestedJars();
@@ -257,36 +214,35 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
Property<ModPlatform> getPlatform(); Property<ModPlatform> getPlatform();
RegularFileProperty getInjectAccessWidener(); RegularFileProperty getInjectAccessWidener();
Property<Boolean> getReadMixinConfigsFromManifest();
SetProperty<String> getAtAccessWideners(); SetProperty<String> getAtAccessWideners();
Property<Boolean> getUseMixinExtension(); Property<Boolean> getUseMixinExtension();
Property<Boolean> getOptimizeFmj(); Property<Boolean> getOptimizeFmj();
record RefmapData(List<String> mixinConfigs, String refmapName) implements Serializable { } Property<TinyRemapperService.Options> getTinyRemapperServiceOptions();
ListProperty<RefmapData> getMixinData(); ListProperty<MixinRefmapService.Options> getMixinRefmapServiceOptions();
Property<MappingsService.Options> getMappingsServiceOptions();
Property<String> getTinyRemapperBuildServiceUuid();
Property<String> getMappingBuildServiceUuid();
} }
public abstract static class RemapAction extends AbstractRemapAction<RemapParams> { public abstract static class RemapAction extends AbstractRemapAction<RemapParams> {
private static final Logger LOGGER = LoggerFactory.getLogger(RemapAction.class); private static final Logger LOGGER = LoggerFactory.getLogger(RemapAction.class);
private final @Nullable TinyRemapperService tinyRemapperService; private @Nullable TinyRemapperService tinyRemapperService;
private @Nullable TinyRemapper tinyRemapper; private @Nullable TinyRemapper tinyRemapper;
public RemapAction() { public RemapAction() {
this.tinyRemapperService = getParameters().getTinyRemapperBuildServiceUuid().isPresent()
? UnsafeWorkQueueHelper.get(getParameters().getTinyRemapperBuildServiceUuid(), TinyRemapperService.class)
: null;
} }
@Override @Override
public void execute() { public void execute() {
try { try (var serviceFactory = new ScopedServiceFactory()) {
LOGGER.info("Remapping {} to {}", inputFile, outputFile); LOGGER.info("Remapping {} to {}", inputFile, outputFile);
this.tinyRemapperService = getParameters().getTinyRemapperServiceOptions().isPresent()
? serviceFactory.get(getParameters().getTinyRemapperServiceOptions().get())
: null;
prepare(); prepare();
if (tinyRemapperService != null) { if (tinyRemapperService != null) {
@@ -305,9 +261,9 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
remapAccessWidener(); remapAccessWidener();
} }
addRefmaps(); addRefmaps(serviceFactory);
addNestedJars(); addNestedJars();
ModBuildExtensions.convertAwToAt(getParameters().getAtAccessWideners(), outputFile, getParameters().getMappingBuildServiceUuid()); ModBuildExtensions.convertAwToAt(serviceFactory, getParameters().getAtAccessWideners(), outputFile, getParameters().getMappingsServiceOptions());
if (!getParameters().getPlatform().get().isForgeLike()) { if (!getParameters().getPlatform().get().isForgeLike()) {
modifyJarManifest(); modifyJarManifest();
@@ -433,21 +389,14 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
JarNester.nestJars(nestedJars.getFiles(), outputFile.toFile(), getParameters().getPlatform().get(), LOGGER); JarNester.nestJars(nestedJars.getFiles(), outputFile.toFile(), getParameters().getPlatform().get(), LOGGER);
} }
private void addRefmaps() throws IOException { private void addRefmaps(ServiceFactory serviceFactory) throws IOException {
if (getParameters().getUseMixinExtension().getOrElse(false)) { if (getParameters().getUseMixinExtension().getOrElse(false)) {
return; return;
} }
for (RemapParams.RefmapData refmapData : getParameters().getMixinData().get()) { for (MixinRefmapService.Options options : getParameters().getMixinRefmapServiceOptions().get()) {
if (ZipUtils.contains(outputFile, refmapData.refmapName())) { MixinRefmapService mixinRefmapService = serviceFactory.get(options);
int transformed = ZipUtils.transformJson(JsonObject.class, outputFile, refmapData.mixinConfigs().stream().collect(Collectors.toMap(s -> s, s -> json -> { mixinRefmapService.applyToJar(outputFile, getParameters().getReadMixinConfigsFromManifest().get());
if (!json.has("refmap")) {
json.addProperty("refmap", refmapData.refmapName());
}
return json;
})));
}
} }
} }
@@ -475,9 +424,4 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
.map(relativePath(rootPaths)) .map(relativePath(rootPaths))
.toList(); .toList();
} }
@Internal
public TinyRemapperService getTinyRemapperService() {
return TinyRemapperService.getOrCreate(serviceManagerProvider.get().get(), this);
}
} }

View File

@@ -40,7 +40,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import net.fabricmc.loom.task.service.SourceRemapperService; import net.fabricmc.loom.task.service.SourceRemapperService;
import net.fabricmc.loom.util.newService.ScopedServiceFactory; import net.fabricmc.loom.util.service.ScopedServiceFactory;
public abstract class RemapSourcesJarTask extends AbstractRemapJarTask { public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
@Nested @Nested

View File

@@ -56,7 +56,7 @@ public abstract class JarManifestService implements BuildService<JarManifestServ
Property<MixinVersion> getMixinVersion(); Property<MixinVersion> getMixinVersion();
} }
public static synchronized Provider<JarManifestService> get(Project project) { public static Provider<JarManifestService> get(Project project) {
return project.getGradle().getSharedServices().registerIfAbsent("LoomJarManifestService:" + project.getName(), JarManifestService.class, spec -> { return project.getGradle().getSharedServices().registerIfAbsent("LoomJarManifestService:" + project.getName(), JarManifestService.class, spec -> {
spec.parameters(params -> { spec.parameters(params -> {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);

View File

@@ -26,53 +26,65 @@ package net.fabricmc.loom.task.service;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.Objects; import java.util.function.Supplier;
import dev.architectury.loom.util.MappingOption; import dev.architectury.loom.util.MappingOption;
import com.google.common.base.Suppliers;
import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.MappingSet;
import org.gradle.api.Project;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Nested;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.util.service.SharedService; import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public final class LorenzMappingService implements SharedService { public final class LorenzMappingService extends Service<LorenzMappingService.Options> {
private MappingSet mappings; public static final ServiceType<Options, LorenzMappingService> TYPE = new ServiceType<>(Options.class, LorenzMappingService.class);
public LorenzMappingService(MappingSet mappings) { public interface Options extends Service.Options {
this.mappings = mappings; @Nested
Property<MappingsService.Options> getMappings();
} }
public static synchronized LorenzMappingService create(SharedServiceManager sharedServiceManager, MappingConfiguration mappingConfiguration, MappingsNamespace from, MappingsNamespace to) { public static Provider<Options> createOptions(Project project, MappingConfiguration mappingConfiguration, MappingsNamespace from, MappingsNamespace to) {
return sharedServiceManager.getOrCreateService(mappingConfiguration.getBuildServiceName("LorenzMappingService", from.toString(), to.toString()), () -> { MappingOption mappingOption = from == MappingsNamespace.SRG || to == MappingsNamespace.SRG ? MappingOption.WITH_SRG
MappingOption mappingOption = MappingOption.DEFAULT; : from == MappingsNamespace.MOJANG || to == MappingsNamespace.MOJANG ? MappingOption.WITH_MOJANG : MappingOption.DEFAULT;
if (from == MappingsNamespace.SRG || to == MappingsNamespace.SRG) { return TYPE.create(project, options -> options.getMappings().set(
mappingOption = MappingOption.WITH_SRG; MappingsService.createOptions(
} else if (from == MappingsNamespace.MOJANG || to == MappingsNamespace.MOJANG) { project,
mappingOption = MappingOption.WITH_MOJANG; mappingConfiguration.getMappingsPath(mappingOption),
to.toString(),
from.toString(),
false)
));
}
private final Supplier<MappingSet> mappings = Suppliers.memoize(this::readMappings);
public LorenzMappingService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
}
private MappingSet readMappings() {
MappingsService mappingsService = getServiceFactory().get(getOptions().getMappings().get());
try {
try (var reader = new TinyMappingsReader(mappingsService.getMemoryMappingTree(), mappingsService.getFrom(), mappingsService.getTo())) {
return reader.read();
} }
} catch (IOException e) {
MemoryMappingTree m = mappingConfiguration.getMappingsService(sharedServiceManager, mappingOption).getMappingTree(); throw new UncheckedIOException("Failed to read lorenz mappings", e);
}
try {
try (var reader = new TinyMappingsReader(m, from.toString(), to.toString())) {
return new LorenzMappingService(reader.read());
}
} catch (IOException e) {
throw new UncheckedIOException("Failed to read lorenz mappings", e);
}
});
} }
@Override public MappingSet getMappings() {
public void close() throws IOException { return mappings.get();
this.mappings = null;
}
public MappingSet mappings() {
return Objects.requireNonNull(mappings);
} }
} }

View File

@@ -24,83 +24,121 @@
package net.fabricmc.loom.task.service; package net.fabricmc.loom.task.service;
import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.nio.file.Path; import java.nio.file.Path;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.service.SharedService; import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
import net.fabricmc.tinyremapper.IMappingProvider; import net.fabricmc.tinyremapper.IMappingProvider;
public final class MappingsService implements SharedService { /**
private record Options(Path mappingsFile, String from, String to, boolean remapLocals) { } * A service that provides mappings for remapping.
*/
public final class MappingsService extends Service<MappingsService.Options> implements Closeable {
public static ServiceType<Options, MappingsService> TYPE = new ServiceType<>(Options.class, MappingsService.class);
public static synchronized MappingsService create(SharedServiceManager sharedServiceManager, String name, Path mappingsFile, String from, String to, boolean remapLocals) { // TODO use a nested TinyMappingsService instead of duplicating it
final Options options = new Options(mappingsFile, from, to, remapLocals); public interface Options extends Service.Options {
final String id = name + options.hashCode(); @InputFile
return sharedServiceManager.getOrCreateService(id, () -> new MappingsService(options)); RegularFileProperty getMappingsFile();
@Input
Property<String> getFrom();
@Input
Property<String> getTo();
@Input
Property<Boolean> getRemapLocals();
} }
public static MappingsService createDefault(Project project, SharedServiceManager serviceManager, String from, String to) { /**
* Returns options for creating a new mappings service, with a given mappings file.
*/
public static Provider<Options> createOptions(Project project, Path mappingsFile, String from, String to, boolean remapLocals) {
return createOptions(project, mappingsFile, project.provider(() -> from), project.provider(() -> to), remapLocals);
}
/**
* Returns options for creating a new mappings service, with a given mappings file.
*/
public static Provider<Options> createOptions(Project project, Path mappingsFile, Provider<String> from, Provider<String> to, boolean remapLocals) {
return TYPE.create(project, o -> {
o.getMappingsFile().set(mappingsFile.toFile());
o.getFrom().set(from);
o.getTo().set(to);
o.getRemapLocals().set(remapLocals);
});
}
/**
* Returns options for creating a new mappings service, using the mappings as specified in the project's mapping configuration.
*/
public static Provider<Options> createOptionsWithProjectMappings(Project project, Provider<String> from, Provider<String> to) {
final MappingConfiguration mappingConfiguration = LoomGradleExtension.get(project).getMappingConfiguration(); final MappingConfiguration mappingConfiguration = LoomGradleExtension.get(project).getMappingConfiguration();
return createOptions(project, LoomGradleExtension.get(project).getPlatformMappingFile(), from, to, false);
final String name = mappingConfiguration.getBuildServiceName("mappingsProvider", from, to);
return MappingsService.create(serviceManager, name, LoomGradleExtension.get(project).getPlatformMappingFile(), from, to, false);
} }
private final Options options; public MappingsService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
public MappingsService(Options options) {
this.options = options;
} }
private IMappingProvider mappingProvider = null; private IMappingProvider mappingProvider = null;
private MemoryMappingTree memoryMappingTree = null; private MemoryMappingTree memoryMappingTree = null;
public synchronized IMappingProvider getMappingsProvider() { public IMappingProvider getMappingsProvider() {
if (mappingProvider == null) { if (mappingProvider == null) {
try { try {
mappingProvider = TinyRemapperHelper.create( mappingProvider = TinyRemapperHelper.create(
options.mappingsFile(), getMappingsPath(),
options.from(), getFrom(),
options.to(), getTo(),
options.remapLocals() getOptions().getRemapLocals().get()
); );
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException("Failed to read mappings from: " + options.mappingsFile(), e); throw new UncheckedIOException("Failed to read mappings from: " + getMappingsPath(), e);
} }
} }
return mappingProvider; return mappingProvider;
} }
public synchronized MemoryMappingTree getMemoryMappingTree() { public MemoryMappingTree getMemoryMappingTree() {
if (memoryMappingTree == null) { if (memoryMappingTree == null) {
memoryMappingTree = new MemoryMappingTree(); memoryMappingTree = new MemoryMappingTree();
try { try {
MappingReader.read(options.mappingsFile(), memoryMappingTree); MappingReader.read(getMappingsPath(), memoryMappingTree);
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException("Failed to read mappings from: " + options.mappingsFile(), e); throw new UncheckedIOException("Failed to read mappings from: " + getMappingsPath(), e);
} }
} }
return memoryMappingTree; return memoryMappingTree;
} }
public String getFromNamespace() { public String getFrom() {
return options.from(); return getOptions().getFrom().get();
} }
public String getToNamespace() { public String getTo() {
return options.to(); return getOptions().getTo().get();
}
public Path getMappingsPath() {
return getOptions().getMappingsFile().get().getAsFile().toPath();
} }
@Override @Override

View File

@@ -0,0 +1,203 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 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.service;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.SourceSet;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.mixin.AnnotationProcessorInvoker;
import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.gradle.GradleUtils;
import net.fabricmc.loom.util.gradle.SourceSetHelper;
import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.tinyremapper.IMappingProvider;
public class MixinAPMappingService extends Service<MixinAPMappingService.Options> {
public static final ServiceType<Options, MixinAPMappingService> TYPE = new ServiceType<>(Options.class, MixinAPMappingService.class);
// TODO look into seeing if we can make this an option, it likely breaks project isolation.
private static final boolean INCLUDE_CROSS_PROJECT_MAPPINGS = true;
// Again look into what the result of changing this would be.
private static final boolean USE_ALL_SOURCE_SETS = true;
private static final Logger LOGGER = LoggerFactory.getLogger(MixinAPMappingService.class);
public interface Options extends Service.Options {
@InputFiles // We need to depend on all the outputs, as we don't know if the mixin mapping will exist at the time of task creation
ConfigurableFileCollection getCompileOutputs();
@Input
Property<String> getMixinMappingFileName();
@Input
Property<String> getFrom();
@Input
Property<String> getTo();
}
public static Provider<List<Options>> createOptions(Project thisProject, Provider<String> from, Provider<String> to) {
final LoomGradleExtension thisExtension = LoomGradleExtension.get(thisProject);
String mappingId = thisExtension.getMappingConfiguration().mappingsIdentifier;
var providers = new ArrayList<Provider<Options>>();
Consumer<Project> processProject = project -> {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
Collection<SourceSet> sourceSets = USE_ALL_SOURCE_SETS ? SourceSetHelper.getSourceSets(project) : extension.getMixin().getMixinSourceSets();
for (SourceSet sourceSet : sourceSets) {
LOGGER.debug("Creating MixinAPMappingService for source set: {}", sourceSet.getName());
var provider = createOptions(
thisProject,
sourceSet,
from,
to
);
if (provider != null) {
providers.add(provider);
} else {
LOGGER.debug("Failed to create MixinAPMappingService for source set: {}", sourceSet.getName());
}
}
};
if (!INCLUDE_CROSS_PROJECT_MAPPINGS) {
processProject.accept(thisProject);
} else {
GradleUtils.allLoomProjects(thisProject.getGradle(), project -> {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
if (!mappingId.equals(extension.getMappingConfiguration().mappingsIdentifier)) {
// Only find mixin mappings that are from other projects with the same mapping id.
return;
}
processProject.accept(project);
});
}
return thisProject.provider(() -> providers.stream().map(Provider::get).toList());
}
@Nullable
public static Provider<Options> createOptions(Project project, SourceSet sourceSet, Provider<String> from, Provider<String> to) {
final File mixinMappings = AnnotationProcessorInvoker.getMixinMappingsForSourceSet(project, sourceSet);
final Task compileTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()); // TODO what about other languages?
if (compileTask == null) {
return null;
}
boolean containsOutput = false;
for (File file : compileTask.getOutputs().getFiles()) {
if (file.getName().equals(mixinMappings.getName())) {
containsOutput = true;
break;
}
}
if (!containsOutput) {
LOGGER.warn("Failed to find mixin mappings {} in task outputs: {}", mixinMappings.getName(), compileTask.getOutputs().getFiles());
return null;
}
return TYPE.create(project, o -> {
o.getCompileOutputs().from(compileTask.getOutputs());
o.getMixinMappingFileName().set(mixinMappings.getName());
o.getFrom().set(from);
o.getTo().set(to);
});
}
private IMappingProvider mappingProvider = null;
private boolean exists = true;
public MixinAPMappingService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
}
@Nullable
public IMappingProvider getMappingsProvider() {
if (!exists) {
return null;
}
if (mappingProvider == null) {
final Path mappingsPath = getMappingsPath();
if (!Files.exists(mappingsPath)) {
exists = false;
return null;
}
try {
mappingProvider = TinyRemapperHelper.create(
mappingsPath,
getOptions().getFrom().get(),
getOptions().getTo().get(),
false
);
} catch (IOException e) {
throw new UncheckedIOException("Failed to read mappings from: " + mappingsPath, e);
}
}
return mappingProvider;
}
// We should always find the file in the task outputs, regardless of if it exists or not.
private Path getMappingsPath() {
for (File file : getOptions().getCompileOutputs().getFiles()) {
if (file.getName().equals(getOptions().getMixinMappingFileName().get())) {
return file.toPath();
}
}
throw new RuntimeException("Failed to find mixin mappings file: " + getOptions().getMixinMappingFileName().get());
}
}

View File

@@ -0,0 +1,141 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 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.service;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.google.gson.JsonObject;
import dev.architectury.loom.extensions.ModBuildExtensions;
import org.gradle.api.Project;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.task.AbstractRemapJarTask;
import net.fabricmc.loom.task.RemapJarTask;
import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.fmj.FabricModJson;
import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
public class MixinRefmapService extends Service<MixinRefmapService.Options> {
public static final ServiceType<Options, MixinRefmapService> TYPE = new ServiceType<>(Options.class, MixinRefmapService.class);
public interface Options extends Service.Options {
@Input
ListProperty<String> getMixinConfigs();
@Input
Property<String> getRefmapName();
}
public static Provider<List<Options>> createOptions(RemapJarTask task) {
final Project project = task.getProject();
return project.provider(() -> {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
if (!extension.getMixin().getUseLegacyMixinAp().get()) {
return List.of();
}
final MixinExtension mixinExtension = extension.getMixin();
List<Provider<Options>> options = new ArrayList<>();
for (SourceSet sourceSet : mixinExtension.getMixinSourceSets()) {
MixinExtension.MixinInformationContainer container = Objects.requireNonNull(
MixinExtension.getMixinInformationContainer(sourceSet)
);
final List<String> rootPaths = AbstractRemapJarTask.getRootPaths(sourceSet.getResources().getSrcDirs());
final String refmapName = container.refmapNameProvider().get();
final List<String> mixinConfigs = container.sourceSet().getResources()
.matching(container.mixinConfigPattern())
.getFiles()
.stream()
.map(AbstractRemapJarTask.relativePath(rootPaths))
.toList();
options.add(createOptions(project, mixinConfigs, refmapName));
}
return options.stream().map(Provider::get).toList();
});
}
private static Provider<Options> createOptions(Project project, List<String> mixinConfigs, String refmapName) {
return TYPE.create(project, o -> {
o.getMixinConfigs().set(mixinConfigs);
o.getRefmapName().set(refmapName);
});
}
public MixinRefmapService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
}
public void applyToJar(Path path, boolean readConfigsFromManifest) throws IOException {
final FabricModJson fabricModJson = FabricModJsonFactory.createFromZipNullable(path);
final List<String> allMixinConfigs = new ArrayList<>();
if (fabricModJson != null) {
allMixinConfigs.addAll(fabricModJson.getMixinConfigurations());
}
if (readConfigsFromManifest) {
allMixinConfigs.addAll(ModBuildExtensions.readMixinConfigsFromManifest(path.toFile()));
}
if (allMixinConfigs.isEmpty()) {
return;
}
final List<String> mixinConfigs = getOptions().getMixinConfigs().get().stream()
.filter(allMixinConfigs::contains)
.toList();
final String refmapName = getOptions().getRefmapName().get();
if (ZipUtils.contains(path, refmapName)) {
int transformed = ZipUtils.transformJson(JsonObject.class, path, mixinConfigs.stream().collect(Collectors.toMap(s -> s, s -> json -> {
if (!json.has("refmap")) {
json.addProperty("refmap", refmapName);
}
return json;
})));
}
}
}

View File

@@ -1,140 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2021 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.service;
import java.io.Closeable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import org.gradle.api.Project;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.util.TinyRemapperHelper;
import net.fabricmc.loom.util.newService.Service;
import net.fabricmc.loom.util.newService.ServiceFactory;
import net.fabricmc.loom.util.newService.ServiceType;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
import net.fabricmc.tinyremapper.IMappingProvider;
/**
* A service that provides mappings for remapping.
*/
public final class NewMappingsService extends Service<NewMappingsService.Options> implements Closeable {
public static ServiceType<Options, NewMappingsService> TYPE = new ServiceType<>(Options.class, NewMappingsService.class);
public interface Options extends Service.Options {
@InputFile
RegularFileProperty getMappingsFile();
@Input
Property<String> getFrom();
@Input
Property<String> getTo();
@Input
Property<Boolean> getRemapLocals();
}
/**
* Returns options for creating a new mappings service, with a given mappings file.
*/
public static Provider<Options> createOptions(Project project, Path mappingsFile, String from, String to, boolean remapLocals) {
return TYPE.create(project, o -> {
o.getMappingsFile().set(project.file(mappingsFile));
o.getFrom().set(from);
o.getTo().set(to);
o.getRemapLocals().set(remapLocals);
});
}
/**
* Returns options for creating a new mappings service, using the mappings as specified in the project's mapping configuration.
*/
public static Provider<Options> createOptionsWithProjectMappings(Project project, String from, String to) {
final MappingConfiguration mappingConfiguration = LoomGradleExtension.get(project).getMappingConfiguration();
return createOptions(project, mappingConfiguration.tinyMappings, from, to, false);
}
public NewMappingsService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
}
private IMappingProvider mappingProvider = null;
private MemoryMappingTree memoryMappingTree = null;
public IMappingProvider getMappingsProvider() {
if (mappingProvider == null) {
try {
mappingProvider = TinyRemapperHelper.create(
getMappingsPath(),
getFrom(),
getTo(),
getOptions().getRemapLocals().get()
);
} catch (IOException e) {
throw new UncheckedIOException("Failed to read mappings from: " + getMappingsPath(), e);
}
}
return mappingProvider;
}
public MemoryMappingTree getMemoryMappingTree() {
if (memoryMappingTree == null) {
memoryMappingTree = new MemoryMappingTree();
try {
MappingReader.read(getMappingsPath(), memoryMappingTree);
} catch (IOException e) {
throw new UncheckedIOException("Failed to read mappings from: " + getMappingsPath(), e);
}
}
return memoryMappingTree;
}
public String getFrom() {
return getOptions().getFrom().get();
}
public String getTo() {
return getOptions().getTo().get();
}
public Path getMappingsPath() {
return getOptions().getMappingsFile().get().getAsFile().toPath();
}
@Override
public void close() {
mappingProvider = null;
}
}

View File

@@ -45,9 +45,9 @@ import net.fabricmc.loom.util.DeletingFileVisitor;
import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.newService.Service; import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.newService.ServiceFactory; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.newService.ServiceType; import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.lorenztiny.TinyMappingsReader;
public final class SourceRemapperService extends Service<SourceRemapperService.Options> { public final class SourceRemapperService extends Service<SourceRemapperService.Options> {
@@ -55,7 +55,7 @@ public final class SourceRemapperService extends Service<SourceRemapperService.O
public interface Options extends Service.Options { public interface Options extends Service.Options {
@Nested @Nested
Property<NewMappingsService.Options> getMappings(); Property<MappingsService.Options> getMappings();
@Input @Input
Property<Integer> getJavaCompileRelease(); Property<Integer> getJavaCompileRelease();
@InputFiles @InputFiles
@@ -64,10 +64,10 @@ public final class SourceRemapperService extends Service<SourceRemapperService.O
public static Provider<Options> createOptions(RemapSourcesJarTask task) { public static Provider<Options> createOptions(RemapSourcesJarTask task) {
return TYPE.create(task.getProject(), o -> { return TYPE.create(task.getProject(), o -> {
o.getMappings().set(NewMappingsService.createOptionsWithProjectMappings( o.getMappings().set(MappingsService.createOptionsWithProjectMappings(
task.getProject(), task.getProject(),
task.getSourceNamespace().get(), task.getSourceNamespace(),
task.getTargetNamespace().get() task.getTargetNamespace()
)); ));
o.getJavaCompileRelease().set(SourceRemapper.getJavaCompileRelease(task.getProject())); o.getJavaCompileRelease().set(SourceRemapper.getJavaCompileRelease(task.getProject()));
o.getClasspath().from(task.getClasspath()); o.getClasspath().from(task.getClasspath());
@@ -123,7 +123,7 @@ public final class SourceRemapperService extends Service<SourceRemapperService.O
mercury.setGracefulClasspathChecks(true); mercury.setGracefulClasspathChecks(true);
mercury.setSourceCompatibilityFromRelease(getOptions().getJavaCompileRelease().get()); mercury.setSourceCompatibilityFromRelease(getOptions().getJavaCompileRelease().get());
NewMappingsService mappingsService = getServiceFactory().get(getOptions().getMappings()); MappingsService mappingsService = getServiceFactory().get(getOptions().getMappings());
var tinyMappingsReader = new TinyMappingsReader(mappingsService.getMemoryMappingTree(), mappingsService.getFrom(), mappingsService.getTo()).read(); var tinyMappingsReader = new TinyMappingsReader(mappingsService.getMemoryMappingTree(), mappingsService.getFrom(), mappingsService.getTo()).read();
mercury.getProcessors().add(MercuryRemapper.create(tinyMappingsReader)); mercury.getProcessors().add(MercuryRemapper.create(tinyMappingsReader));

View File

@@ -24,6 +24,7 @@
package net.fabricmc.loom.task.service; package net.fabricmc.loom.task.service;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@@ -35,111 +36,83 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.StringJoiner;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.invocation.Gradle; import org.gradle.api.file.FileCollection;
import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.ListProperty;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.IntermediaryNamespaces; import net.fabricmc.loom.build.IntermediaryNamespaces;
import net.fabricmc.loom.build.mixin.AnnotationProcessorInvoker;
import net.fabricmc.loom.extension.RemapperExtensionHolder; import net.fabricmc.loom.extension.RemapperExtensionHolder;
import net.fabricmc.loom.task.AbstractRemapJarTask; import net.fabricmc.loom.task.AbstractRemapJarTask;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.gradle.GradleUtils;
import net.fabricmc.loom.util.gradle.SourceSetHelper;
import net.fabricmc.loom.util.kotlin.KotlinClasspath;
import net.fabricmc.loom.util.kotlin.KotlinClasspathService; import net.fabricmc.loom.util.kotlin.KotlinClasspathService;
import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader; import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader;
import net.fabricmc.loom.util.service.SharedService; import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
import net.fabricmc.tinyremapper.IMappingProvider; import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.InputTag; import net.fabricmc.tinyremapper.InputTag;
import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.extension.mixin.MixinExtension;
public class TinyRemapperService implements SharedService { public class TinyRemapperService extends Service<TinyRemapperService.Options> implements Closeable {
public static synchronized TinyRemapperService getOrCreate(SharedServiceManager serviceManager, AbstractRemapJarTask remapJarTask) { public static final ServiceType<Options, TinyRemapperService> TYPE = new ServiceType<>(Options.class, TinyRemapperService.class);
final Project project = remapJarTask.getProject();
final String to = remapJarTask.getTargetNamespace().get();
final String from = remapJarTask.getSourceNamespace().get();
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get();
final @Nullable KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(serviceManager, project);
// Generates an id that is used to share the remapper across projects. This tasks in the remap jar task name to handle custom remap jar tasks separately. public interface Options extends Service.Options {
final var joiner = new StringJoiner(":"); @Input
joiner.add(extension.getMappingConfiguration().getBuildServiceName("remapJarService", from, to)); Property<String> getFrom();
joiner.add(remapJarTask.getName()); @Input
Property<String> getTo();
if (kotlinClasspathService != null) { @Nested
joiner.add("kotlin-" + kotlinClasspathService.version()); ListProperty<MappingsService.Options> getMappings();
} @Input
Property<Boolean> getUselegacyMixinAP();
// TODO remove this when removing shared service manager. @Nested
joiner.add(project.getPath()); ListProperty<MixinAPMappingService.Options> getMixinApMappings();
@Nested
extension.getKnownIndyBsms().get().stream().sorted().forEach(joiner::add); @Optional
Property<KotlinClasspathService.Options> getKotlinClasspathService();
if (extension.isForgeLike()) { @InputFiles
joiner.add(extension.getPlatform().get().id()); ConfigurableFileCollection getClasspath();
} @Input
ListProperty<String> getKnownIndyBsms();
final String id = joiner.toString(); @Input
ListProperty<RemapperExtensionHolder> getRemapperExtensions();
TinyRemapperService service = serviceManager.getOrCreateService(id, () -> {
List<IMappingProvider> mappings = new ArrayList<>();
mappings.add(MappingsService.createDefault(project, serviceManager, from, to).getMappingsProvider());
if (legacyMixin) {
mappings.add(gradleMixinMappingProvider(serviceManager, project.getGradle(), extension.getMappingConfiguration().mappingsIdentifier, from, to));
}
return new TinyRemapperService(mappings, !legacyMixin, kotlinClasspathService, extension.getKnownIndyBsms().get(), extension.getRemapperExtensions().get(), from, to, project.getObjects());
});
final ConfigurationContainer configurations = project.getConfigurations();
ConfigurableFileCollection excludedMinecraftJars = project.files();
List<Path> classPath = remapJarTask.getClasspath()
.minus(configurations.getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES))
.minus(configurations.getByName(Constants.Configurations.MINECRAFT_RUNTIME_LIBRARIES))
.minus(excludedMinecraftJars)
.getFiles()
.stream()
.map(File::toPath)
.filter(Files::exists)
.toList();
service.readClasspath(classPath);
return service;
} }
// Add all of the mixin mappings from all loom projects. public static Provider<Options> createOptions(AbstractRemapJarTask remapJarTask) {
private static IMappingProvider gradleMixinMappingProvider(SharedServiceManager serviceManager, Gradle gradle, String mappingId, String from, String to) { final Project project = remapJarTask.getProject();
return out -> GradleUtils.allLoomProjects(gradle, project -> { return TYPE.create(project, options -> {
final LoomGradleExtension extension = LoomGradleExtension.get(project); final LoomGradleExtension extension = LoomGradleExtension.get(project);
final ConfigurationContainer configurations = project.getConfigurations();
final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get();
final FileCollection classpath = remapJarTask.getClasspath()
.minus(configurations.getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES))
.minus(configurations.getByName(Constants.Configurations.MINECRAFT_RUNTIME_LIBRARIES));
if (!mappingId.equals(extension.getMappingConfiguration().mappingsIdentifier)) { options.getFrom().set(remapJarTask.getSourceNamespace());
// Only find mixin mappings that are from other projects with the same mapping id. options.getTo().set(remapJarTask.getTargetNamespace());
return; options.getMappings().add(MappingsService.createOptionsWithProjectMappings(project, options.getFrom(), options.getTo()));
if (legacyMixin) {
options.getMixinApMappings().set(MixinAPMappingService.createOptions(project, options.getFrom(), options.getTo().map(to -> IntermediaryNamespaces.replaceMixinIntermediaryNamespace(project, to))));
} }
for (SourceSet sourceSet : SourceSetHelper.getSourceSets(project)) { options.getUselegacyMixinAP().set(legacyMixin);
final File mixinMappings = AnnotationProcessorInvoker.getMixinMappingsForSourceSet(project, sourceSet); options.getKotlinClasspathService().set(KotlinClasspathService.createOptions(project));
options.getClasspath().from(classpath);
if (!mixinMappings.exists()) { options.getKnownIndyBsms().set(extension.getKnownIndyBsms());
continue; options.getRemapperExtensions().set(extension.getRemapperExtensions());
}
final String newTo = IntermediaryNamespaces.replaceMixinIntermediaryNamespace(project, to);
MappingsService service = MappingsService.create(serviceManager, mixinMappings.getAbsolutePath(), mixinMappings.toPath(), from, newTo, false);
service.getMappingsProvider().load(out);
}
}); });
} }
@@ -151,30 +124,50 @@ public class TinyRemapperService implements SharedService {
// Set to true once remapping has started, once set no inputs can be read. // Set to true once remapping has started, once set no inputs can be read.
private boolean isRemapping = false; private boolean isRemapping = false;
private TinyRemapperService(List<IMappingProvider> mappings, boolean useMixinExtension, @Nullable KotlinClasspath kotlinClasspath, Set<String> knownIndyBsms, List<RemapperExtensionHolder> remapperExtensions, String sourceNamespace, String targetNamespace, ObjectFactory objectFactory) { public TinyRemapperService(Options options, ServiceFactory serviceFactory) {
TinyRemapper.Builder builder = TinyRemapper.newRemapper().withKnownIndyBsm(knownIndyBsms); super(options, serviceFactory);
tinyRemapper = createTinyRemapper();
readClasspath();
}
for (IMappingProvider provider : mappings) { private TinyRemapper createTinyRemapper() {
builder.withMappings(provider); TinyRemapper.Builder builder = TinyRemapper.newRemapper()
.withKnownIndyBsm(Set.copyOf(getOptions().getKnownIndyBsms().get()));
for (MappingsService.Options options : getOptions().getMappings().get()) {
MappingsService mappingsService = getServiceFactory().get(options);
builder.withMappings(mappingsService.getMappingsProvider());
} }
if (useMixinExtension) { if (!getOptions().getUselegacyMixinAP().get()) {
builder.extension(new net.fabricmc.tinyremapper.extension.mixin.MixinExtension()); builder.extension(new MixinExtension());
} }
if (kotlinClasspath != null) { if (getOptions().getKotlinClasspathService().isPresent()) {
kotlinRemapperClassloader = KotlinRemapperClassloader.create(kotlinClasspath); KotlinClasspathService kotlinClasspathService = getServiceFactory().get(getOptions().getKotlinClasspathService());
kotlinRemapperClassloader = KotlinRemapperClassloader.create(kotlinClasspathService);
builder.extension(kotlinRemapperClassloader.getTinyRemapperExtension()); builder.extension(kotlinRemapperClassloader.getTinyRemapperExtension());
} }
for (RemapperExtensionHolder holder : remapperExtensions) { for (RemapperExtensionHolder holder : getOptions().getRemapperExtensions().get()) {
holder.apply(builder, sourceNamespace, targetNamespace, objectFactory); holder.apply(builder, getOptions().getFrom().get(), getOptions().getTo().get());
} }
tinyRemapper = builder.build(); if (getOptions().getUselegacyMixinAP().get()) {
for (MixinAPMappingService.Options options : getOptions().getMixinApMappings().get()) {
MixinAPMappingService mixinAPMappingService = getServiceFactory().get(options);
IMappingProvider provider = mixinAPMappingService.getMappingsProvider();
if (provider != null) {
builder.withMappings(provider);
}
}
}
return builder.build();
} }
public synchronized InputTag getOrCreateTag(Path file) { public InputTag getOrCreateTag(Path file) {
InputTag tag = inputTagMap.get(file.toAbsolutePath().toString()); InputTag tag = inputTagMap.get(file.toAbsolutePath().toString());
if (tag == null) { if (tag == null) {
@@ -186,34 +179,30 @@ public class TinyRemapperService implements SharedService {
} }
public TinyRemapper getTinyRemapperForRemapping() { public TinyRemapper getTinyRemapperForRemapping() {
synchronized (this) { isRemapping = true;
isRemapping = true; return Objects.requireNonNull(tinyRemapper, "Tiny remapper has not been setup");
return Objects.requireNonNull(tinyRemapper, "Tiny remapper has not been setup");
}
} }
public synchronized TinyRemapper getTinyRemapperForInputs() { public TinyRemapper getTinyRemapperForInputs() {
synchronized (this) { if (isRemapping) {
if (isRemapping) { throw new IllegalStateException("Cannot read inputs as remapping has already started");
throw new IllegalStateException("Cannot read inputs as remapping has already started");
}
return tinyRemapper;
} }
return tinyRemapper;
} }
void readClasspath(List<Path> paths) { private void readClasspath() {
List<Path> toRead = new ArrayList<>(); List<Path> toRead = new ArrayList<>();
synchronized (classpath) { for (File file : getOptions().getClasspath().getFiles()) {
for (Path path: paths) { Path path = file.toPath();
if (classpath.contains(path)) {
continue;
}
toRead.add(path); if (classpath.contains(path) || Files.notExists(path)) {
classpath.add(path); continue;
} }
toRead.add(path);
classpath.add(path);
} }
if (toRead.isEmpty()) { if (toRead.isEmpty()) {

View File

@@ -53,24 +53,24 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.build.IntermediaryNamespaces; import net.fabricmc.loom.build.IntermediaryNamespaces;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.task.service.LorenzMappingService; import net.fabricmc.loom.task.service.LorenzMappingService;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
public class SourceRemapper { public class SourceRemapper {
private final Project project; private final Project project;
private final SharedServiceManager serviceManager; private final ServiceFactory serviceFactory;
private String from; private String from;
private String to; private String to;
private final List<Consumer<ProgressLogger>> remapTasks = new ArrayList<>(); private final List<Consumer<ProgressLogger>> remapTasks = new ArrayList<>();
private Mercury mercury; private Mercury mercury;
public SourceRemapper(Project project, SharedServiceManager serviceManager, boolean toNamed) { public SourceRemapper(Project project, ServiceFactory serviceFactory, boolean toNamed) {
this(project, serviceManager, toNamed ? IntermediaryNamespaces.runtimeIntermediary(project) : "named", !toNamed ? IntermediaryNamespaces.runtimeIntermediary(project) : "named"); this(project, serviceFactory, toNamed ? IntermediaryNamespaces.runtimeIntermediary(project) : "named", !toNamed ? IntermediaryNamespaces.runtimeIntermediary(project) : "named");
} }
public SourceRemapper(Project project, SharedServiceManager serviceManager, String from, String to) { public SourceRemapper(Project project, ServiceFactory serviceFactory, String from, String to) {
this.project = project; this.project = project;
this.serviceManager = serviceManager; this.serviceFactory = serviceFactory;
this.from = from; this.from = from;
this.to = to; this.to = to;
} }
@@ -174,11 +174,12 @@ public class SourceRemapper {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
MappingConfiguration mappingConfiguration = extension.getMappingConfiguration(); MappingConfiguration mappingConfiguration = extension.getMappingConfiguration();
MappingSet mappings = LorenzMappingService.create(serviceManager, LorenzMappingService lorenzMappingService = serviceFactory.get(LorenzMappingService.createOptions(
mappingConfiguration, project,
mappingConfiguration,
Objects.requireNonNull(MappingsNamespace.of(from)), Objects.requireNonNull(MappingsNamespace.of(from)),
Objects.requireNonNull(MappingsNamespace.of(to)) Objects.requireNonNull(MappingsNamespace.of(to))));
).mappings(); MappingSet mappings = lorenzMappingService.getMappings();
Mercury mercury = createMercuryWithClassPath(project, MappingsNamespace.of(to) == MappingsNamespace.NAMED); Mercury mercury = createMercuryWithClassPath(project, MappingsNamespace.of(to) == MappingsNamespace.NAMED);
mercury.setSourceCompatibilityFromRelease(getJavaCompileRelease(project)); mercury.setSourceCompatibilityFromRelease(getJavaCompileRelease(project));

View File

@@ -33,11 +33,12 @@ import java.util.regex.Pattern;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import dev.architectury.loom.util.MappingOption; import dev.architectury.loom.util.MappingOption;
import org.gradle.api.Project; import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.srg.InnerClassRemapper; import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.mappingio.tree.MappingTree;
@@ -64,14 +65,14 @@ public final class TinyRemapperHelper {
private TinyRemapperHelper() { private TinyRemapperHelper() {
} }
public static TinyRemapper getTinyRemapper(Project project, SharedServiceManager serviceManager, String fromM, String toM) throws IOException { public static TinyRemapper getTinyRemapper(Project project, ServiceFactory serviceFactory, String fromM, String toM) throws IOException {
return getTinyRemapper(project, serviceManager, fromM, toM, false, (builder) -> { }, Set.of()); return getTinyRemapper(project, serviceFactory, fromM, toM, false, (builder) -> { }, Set.of());
} }
public static TinyRemapper getTinyRemapper(Project project, SharedServiceManager serviceManager, String fromM, String toM, boolean fixRecords, Consumer<TinyRemapper.Builder> builderConsumer, Set<String> fromClassNames) throws IOException { public static TinyRemapper getTinyRemapper(Project project, ServiceFactory serviceFactory, String fromM, String toM, boolean fixRecords, Consumer<TinyRemapper.Builder> builderConsumer, Set<String> fromClassNames) throws IOException {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
final MappingOption mappingOption = MappingOption.forPlatform(extension); final MappingOption mappingOption = MappingOption.forPlatform(extension);
MemoryMappingTree mappingTree = extension.getMappingConfiguration().getMappingsService(serviceManager, mappingOption).getMappingTree(); MemoryMappingTree mappingTree = extension.getMappingConfiguration().getMappingsService(project, serviceFactory, mappingOption).getMappingTree();
if (fixRecords && !mappingTree.getSrcNamespace().equals(fromM)) { if (fixRecords && !mappingTree.getSrcNamespace().equals(fromM)) {
throw new IllegalStateException("Mappings src namespace must match remap src namespace, expected " + fromM + " but got " + mappingTree.getSrcNamespace()); throw new IllegalStateException("Mappings src namespace must match remap src namespace, expected " + fromM + " but got " + mappingTree.getSrcNamespace());

View File

@@ -75,6 +75,11 @@ public class GradleTypeAdapter implements TypeAdapterFactory {
@Override @Override
public void write(JsonWriter out, T property) throws IOException { public void write(JsonWriter out, T property) throws IOException {
if (!property.isPresent()) {
out.nullValue();
return;
}
final Object o = property.get(); final Object o = property.get();
final TypeAdapter adapter = gson.getAdapter(o.getClass()); final TypeAdapter adapter = gson.getAdapter(o.getClass());
adapter.write(out, o); adapter.write(out, o);
@@ -102,6 +107,11 @@ public class GradleTypeAdapter implements TypeAdapterFactory {
private static final class RegularFilePropertyTypeAdapter<T extends RegularFileProperty> extends WriteOnlyTypeAdapter<T> { private static final class RegularFilePropertyTypeAdapter<T extends RegularFileProperty> extends WriteOnlyTypeAdapter<T> {
@Override @Override
public void write(JsonWriter out, T property) throws IOException { public void write(JsonWriter out, T property) throws IOException {
if (!property.isPresent()) {
out.nullValue();
return;
}
final File file = property.get().getAsFile(); final File file = property.get().getAsFile();
out.value(file.getAbsolutePath()); out.value(file.getAbsolutePath());
} }

View File

@@ -24,6 +24,7 @@
package net.fabricmc.loom.util.kotlin; package net.fabricmc.loom.util.kotlin;
import java.io.File;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@@ -32,27 +33,40 @@ import java.util.stream.Collectors;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.jetbrains.annotations.Nullable; import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import net.fabricmc.loom.util.service.SharedService; import net.fabricmc.loom.util.service.Service;
import net.fabricmc.loom.util.service.SharedServiceManager; import net.fabricmc.loom.util.service.ServiceFactory;
import net.fabricmc.loom.util.service.ServiceType;
public record KotlinClasspathService(Set<URL> classpath, String version) implements KotlinClasspath, SharedService { public final class KotlinClasspathService extends Service<KotlinClasspathService.Options> implements KotlinClasspath {
@Nullable public static ServiceType<Options, KotlinClasspathService> TYPE = new ServiceType<>(Options.class, KotlinClasspathService.class);
public static KotlinClasspathService getOrCreateIfRequired(SharedServiceManager sharedServiceManager, Project project) {
public interface Options extends Service.Options {
@InputFiles
ConfigurableFileCollection getClasspath();
@Input
Property<String> getKotlinVersion();
}
public static Provider<Options> createOptions(Project project) {
if (!KotlinPluginUtils.hasKotlinPlugin(project)) { if (!KotlinPluginUtils.hasKotlinPlugin(project)) {
return null; // Return an empty provider
return project.getObjects().property(Options.class);
} }
return getOrCreate(sharedServiceManager, project, KotlinPluginUtils.getKotlinPluginVersion(project), KotlinPluginUtils.getKotlinMetadataVersion()); return createOptions(
project,
KotlinPluginUtils.getKotlinPluginVersion(project),
KotlinPluginUtils.getKotlinMetadataVersion()
);
} }
public static synchronized KotlinClasspathService getOrCreate(SharedServiceManager sharedServiceManager, Project project, String kotlinVersion, String kotlinMetadataVersion) { private static Provider<Options> createOptions(Project project, String kotlinVersion, String kotlinMetadataVersion) {
final String id = "kotlinclasspath:%s:%s".formatted(kotlinVersion, kotlinMetadataVersion);
return sharedServiceManager.getOrCreateService(id, () -> create(project, kotlinVersion, kotlinMetadataVersion));
}
private static KotlinClasspathService create(Project project, String kotlinVersion, String kotlinMetadataVersion) {
// Create a detached config to resolve the kotlin std lib for the provided version. // Create a detached config to resolve the kotlin std lib for the provided version.
Configuration detachedConfiguration = project.getConfigurations().detachedConfiguration( Configuration detachedConfiguration = project.getConfigurations().detachedConfiguration(
project.getDependencies().create("org.jetbrains.kotlin:kotlin-stdlib:" + kotlinVersion), project.getDependencies().create("org.jetbrains.kotlin:kotlin-stdlib:" + kotlinVersion),
@@ -60,15 +74,36 @@ public record KotlinClasspathService(Set<URL> classpath, String version) impleme
project.getDependencies().create("org.jetbrains.kotlinx:kotlinx-metadata-jvm:" + kotlinMetadataVersion) project.getDependencies().create("org.jetbrains.kotlinx:kotlinx-metadata-jvm:" + kotlinMetadataVersion)
); );
Set<URL> classpath = detachedConfiguration.getFiles().stream() return TYPE.create(project, options -> {
.map(file -> { options.getClasspath().from(detachedConfiguration);
try { options.getKotlinVersion().set(kotlinVersion);
return file.toURI().toURL(); });
} catch (MalformedURLException e) { }
throw new UncheckedIOException(e);
}
}).collect(Collectors.toSet());;
return new KotlinClasspathService(classpath, kotlinVersion); public KotlinClasspathService(Options options, ServiceFactory serviceFactory) {
super(options, serviceFactory);
}
@Override
public String version() {
return getOptions().getKotlinVersion().get();
}
@Override
public Set<URL> classpath() {
return getOptions()
.getClasspath()
.getFiles()
.stream()
.map(KotlinClasspathService::fileToUrl)
.collect(Collectors.toSet());
}
private static URL fileToUrl(File file) {
try {
return file.toURI().toURL();
} catch (MalformedURLException e) {
throw new UncheckedIOException(e);
}
} }
} }

View File

@@ -1,94 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.service;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import org.gradle.api.Task;
import org.gradle.api.provider.Provider;
import org.gradle.api.services.BuildService;
import org.gradle.api.services.BuildServiceParameters;
import org.gradle.build.event.BuildEventsListenerRegistry;
import org.gradle.tooling.events.OperationCompletionListener;
import org.gradle.tooling.events.task.TaskOperationDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class BuildSharedServiceManager implements BuildService<BuildServiceParameters.None> {
private static final Logger LOGGER = LoggerFactory.getLogger(BuildSharedServiceManager.class);
private static final String NAME = "loom:sharedServiceManager";
private SharedServiceManager sharedServiceManager = new BuildSharedServiceManagerImpl();
private final AtomicInteger refCount = new AtomicInteger(0);
public static Provider<BuildSharedServiceManager> createForTask(Task task, BuildEventsListenerRegistry buildEventsListenerRegistry) {
Provider<BuildSharedServiceManager> provider = task.getProject().getGradle().getSharedServices().registerIfAbsent(NAME, BuildSharedServiceManager.class, spec -> {
});
task.usesService(provider);
final BuildSharedServiceManager serviceManager = provider.get();
buildEventsListenerRegistry.onTaskCompletion(registerTaskCompletion(task, serviceManager::onFinish));
int count = serviceManager.refCount.incrementAndGet();
LOGGER.debug("Creating shared service manager provider for task: {} count: {}", task.getName(), count);
return provider;
}
public BuildSharedServiceManager() {
LOGGER.debug("New BuildSharedServiceManager instance");
}
public SharedServiceManager get() {
LOGGER.debug("Shared build service get");
return Objects.requireNonNull(sharedServiceManager);
}
private void onFinish() {
int count = refCount.decrementAndGet();
LOGGER.debug("Build service finish. count: {}", count);
if (count == 0) {
sharedServiceManager.onFinish();
sharedServiceManager = null;
} else if (count < 0) {
throw new IllegalStateException();
}
}
private static Provider<OperationCompletionListener> registerTaskCompletion(Task task, Runnable runnable) {
return task.getProject().provider(() -> event -> {
if (event.getDescriptor() instanceof TaskOperationDescriptor taskDescriptor) {
if (taskDescriptor.getTaskPath().equals(task.getPath())) {
runnable.run();
}
}
});
}
private static final class BuildSharedServiceManagerImpl extends SharedServiceManager {
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.util.newService; package net.fabricmc.loom.util.service;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;

View File

@@ -22,7 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.util.newService; package net.fabricmc.loom.util.service;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
@@ -51,8 +51,6 @@ public final class ScopedServiceFactory implements ServiceFactory, Closeable {
return service; return service;
} }
// TODO skip serialization if we know there is no service with the same type
// If the service is not already created, serialize the options and check the json map as it may be an equivalent service // If the service is not already created, serialize the options and check the json map as it may be an equivalent service
String key = getOptionsCacheKey(options); String key = getOptionsCacheKey(options);
//noinspection unchecked //noinspection unchecked

View File

@@ -1,35 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.service;
public final class ScopedSharedServiceManager extends SharedServiceManager implements AutoCloseable {
public ScopedSharedServiceManager() {
}
@Override
public void close() {
onFinish();
}
}

View File

@@ -22,7 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.util.newService; package net.fabricmc.loom.util.service;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;

View File

@@ -22,9 +22,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.util.newService; package net.fabricmc.loom.util.service;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider;
import org.jetbrains.annotations.Nullable;
/** /**
* A factory for creating {@link Service} instances. * A factory for creating {@link Service} instances.
@@ -38,10 +39,26 @@ public interface ServiceFactory {
* @param <S> The service type. * @param <S> The service type.
* @return The service instance. * @return The service instance.
*/ */
default <O extends Service.Options, S extends Service<O>> S get(Property<O> options) { default <O extends Service.Options, S extends Service<O>> S get(Provider<O> options) {
return get(options.get()); return get(options.get());
} }
/**
* Gets or creates a service instance with the given options, or returns null if the options are not present.
* @param options The options to use.
* @param <O> The options type.
* @param <S> The service type.
* @return The service instance, or null if the options are not present.
*/
@Nullable
default <O extends Service.Options, S extends Service<O>> S getOrNull(Provider<O> options) {
if (options.isPresent()) {
return get(options);
} else {
return null;
}
}
/** /**
* Gets or creates a service instance with the given options. * Gets or creates a service instance with the given options.
* *

View File

@@ -22,7 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.util.newService; package net.fabricmc.loom.util.service;
import org.gradle.api.Action; import org.gradle.api.Action;
import org.gradle.api.Project; import org.gradle.api.Project;

View File

@@ -1,34 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.service;
import java.io.Closeable;
import java.io.IOException;
public interface SharedService extends Closeable {
@Override
default void close() throws IOException {
}
}

View File

@@ -1,99 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A simple manager for {@link SharedService} to be used across gradle (sub) projects.
* This is a basic replacement for gradle's build service api.
*/
public abstract class SharedServiceManager {
private static final Logger LOGGER = LoggerFactory.getLogger(BuildSharedServiceManager.class);
private final Map<String, SharedService> sharedServiceMap = new HashMap<>();
private boolean shutdown = false;
SharedServiceManager() {
LOGGER.info("Creating new SharedServiceManager({})", hashCode());
}
public <S extends SharedService> S getOrCreateService(String id, Supplier<S> function) {
synchronized (sharedServiceMap) {
if (shutdown) {
throw new UnsupportedOperationException("Cannot get or create service has the manager has been shutdown.");
}
//noinspection unchecked
S sharedService = (S) sharedServiceMap.get(id);
if (sharedService == null) {
LOGGER.debug("Creating service for {}", id);
sharedService = function.get();
sharedServiceMap.put(id, sharedService);
}
return sharedService;
}
}
protected void onFinish() {
synchronized (sharedServiceMap) {
shutdown = true;
}
LOGGER.info("Closing SharedServiceManager({})", hashCode());
final List<IOException> exceptionList = new ArrayList<>();
for (SharedService sharedService : sharedServiceMap.values()) {
try {
sharedService.close();
} catch (IOException e) {
exceptionList.add(e);
}
}
sharedServiceMap.clear();
// This is required to ensure that mercury releases all of the file handles.
System.gc();
if (!exceptionList.isEmpty()) {
// Done to try and close all the services.
RuntimeException exception = new RuntimeException("Failed to close all shared services");
exceptionList.forEach(exception::addSuppressed);
throw exception;
}
}
}

View File

@@ -1,57 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.service;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.gradle.api.provider.Property;
// Massive hack to work around WorkerExecutor.noIsolation() doing isolation checks.
public final class UnsafeWorkQueueHelper {
private static final Map<String, SharedService> SERVICE_MAP = new ConcurrentHashMap<>();
private UnsafeWorkQueueHelper() {
}
public static String create(SharedService service) {
final String uuid = UUID.randomUUID().toString();
SERVICE_MAP.put(uuid, service);
return uuid;
}
public static <S> S get(Property<String> property, Class<S> clazz) {
SharedService service = SERVICE_MAP.remove(property.get());
if (service == null) {
throw new NullPointerException("Failed to get service for " + clazz);
}
//noinspection unchecked
return (S) service;
}
}

View File

@@ -44,7 +44,7 @@ class FabricAPIBenchmark implements GradleProjectTestTrait {
allowExistingRepo: true, allowExistingRepo: true,
repo: "https://github.com/FabricMC/fabric.git", repo: "https://github.com/FabricMC/fabric.git",
commit: "efa5891941a32589207dc58c2e77183d599465b8", commit: "41bc64cd617f03d49ecc4a4f7788cb65d465415c",
patch: "fabric_api" patch: "fabric_api"
) )

View File

@@ -61,6 +61,7 @@ class ConfigurationCacheTest extends Specification implements GradleProjectTestT
"jar" | _ "jar" | _
"check" | _ "check" | _
"remapSourcesJar" | _ "remapSourcesJar" | _
"build" | _
} }
// Test GradleUtils.configurationInputFile invalidates the cache when the file changes // Test GradleUtils.configurationInputFile invalidates the cache when the file changes

View File

@@ -34,7 +34,7 @@ import net.fabricmc.loom.api.remapping.RemapperExtension
import net.fabricmc.loom.api.remapping.RemapperParameters import net.fabricmc.loom.api.remapping.RemapperParameters
import net.fabricmc.loom.util.Constants import net.fabricmc.loom.util.Constants
abstract class TestRemapperExtension implements RemapperExtension<Params> { class TestRemapperExtension implements RemapperExtension<Params> {
final Params parameters final Params parameters
@Inject @Inject

View File

@@ -44,10 +44,23 @@ class GradleTypeAdapterTest extends Specification {
def json = GradleTypeAdapter.GSON.toJson(property) def json = GradleTypeAdapter.GSON.toJson(property)
then: then:
1 * property.isPresent() >> true
1 * property.get() >> "value" 1 * property.get() >> "value"
json == "\"value\"" json == "\"value\""
} }
def "Empty Property"() {
given:
def property = Mock(Property)
when:
def json = GradleTypeAdapter.GSON.toJson(property)
then:
1 * property.isPresent() >> false
json == "null"
}
@IgnoreIf({ os.windows }) @IgnoreIf({ os.windows })
def "FileCollection"() { def "FileCollection"() {
given: given:
@@ -74,11 +87,24 @@ class GradleTypeAdapterTest extends Specification {
def json = GradleTypeAdapter.GSON.toJson(regularFileProperty) def json = GradleTypeAdapter.GSON.toJson(regularFileProperty)
then: then:
1 * regularFileProperty.isPresent() >> true
1 * regularFileProperty.get() >> regularFile 1 * regularFileProperty.get() >> regularFile
1 * regularFile.getAsFile() >> file 1 * regularFile.getAsFile() >> file
json == "\"${file.getAbsolutePath()}\"" json == "\"${file.getAbsolutePath()}\""
} }
def "Empty RegularFileProperty"() {
given:
def regularFileProperty = Mock(RegularFileProperty)
when:
def json = GradleTypeAdapter.GSON.toJson(regularFileProperty)
then:
1 * regularFileProperty.isPresent() >> false
json == "null"
}
def "ListProperty"() { def "ListProperty"() {
given: given:
def listProperty = Mock(ListProperty) def listProperty = Mock(ListProperty)

View File

@@ -38,6 +38,7 @@ class LoomMocks {
def minecraftVersionProperty = GradleTestUtil.mockProperty(minecraftVersion) def minecraftVersionProperty = GradleTestUtil.mockProperty(minecraftVersion)
def intermediaryUrlProperty = GradleTestUtil.mockProperty(intermediaryUrl) def intermediaryUrlProperty = GradleTestUtil.mockProperty(intermediaryUrl)
def downloaderProperty = GradleTestUtil.mockProperty(Download.&create as Function) def downloaderProperty = GradleTestUtil.mockProperty(Download.&create as Function)
def refreshDeps = GradleTestUtil.mockProperty(false)
Objects.requireNonNull(minecraftVersionProperty.get()) Objects.requireNonNull(minecraftVersionProperty.get())
@@ -45,6 +46,7 @@ class LoomMocks {
when(mock.getMinecraftVersion()).thenReturn(minecraftVersionProperty) when(mock.getMinecraftVersion()).thenReturn(minecraftVersionProperty)
when(mock.getIntermediaryUrl()).thenReturn(intermediaryUrlProperty) when(mock.getIntermediaryUrl()).thenReturn(intermediaryUrlProperty)
when(mock.getDownloader()).thenReturn(downloaderProperty) when(mock.getDownloader()).thenReturn(downloaderProperty)
when(mock.getRefreshDeps()).thenReturn(refreshDeps)
return mock return mock
} }
} }

View File

@@ -28,13 +28,15 @@ import spock.lang.Specification
import net.fabricmc.loom.configuration.providers.BundleMetadata import net.fabricmc.loom.configuration.providers.BundleMetadata
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarSplitter import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarSplitter
import net.fabricmc.loom.test.LoomTestConstants
import net.fabricmc.loom.test.util.GradleTestUtil import net.fabricmc.loom.test.util.GradleTestUtil
import net.fabricmc.loom.util.download.Download
class MinecraftJarSplitterTest extends Specification { class MinecraftJarSplitterTest extends Specification {
public static final String CLIENT_JAR_URL = "https://launcher.mojang.com/v1/objects/7e46fb47609401970e2818989fa584fd467cd036/client.jar" public static final String CLIENT_JAR_URL = "https://launcher.mojang.com/v1/objects/7e46fb47609401970e2818989fa584fd467cd036/client.jar"
public static final String SERVER_BUNDLE_JAR_URL = "https://launcher.mojang.com/v1/objects/125e5adf40c659fd3bce3e66e67a16bb49ecc1b9/server.jar" public static final String SERVER_BUNDLE_JAR_URL = "https://launcher.mojang.com/v1/objects/125e5adf40c659fd3bce3e66e67a16bb49ecc1b9/server.jar"
public static final File mcJarDir = File.createTempDir() public static final File mcJarDir = new File(LoomTestConstants.TEST_DIR, "jar-splitter")
def "split jars"() { def "split jars"() {
given: given:
@@ -63,7 +65,9 @@ class MinecraftJarSplitterTest extends Specification {
if (!dst.exists()) { if (!dst.exists()) {
dst.parentFile.mkdirs() dst.parentFile.mkdirs()
dst << new URL(url).newInputStream() Download.create(url)
.defaultCache()
.downloadPath(dst.toPath())
} }
return dst return dst

View File

@@ -42,6 +42,7 @@ class FileMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_17_URL intermediaryUrl = INTERMEDIARY_1_17_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
mockMinecraftProvider.minecraftVersion() >> "1.17"
setupType.setup.delegate = this setupType.setup.delegate = this
def mappingFile = setupType.setup.call() def mappingFile = setupType.setup.call()
when: when:
@@ -71,6 +72,7 @@ class FileMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_17_URL intermediaryUrl = INTERMEDIARY_1_17_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
mockMinecraftProvider.minecraftVersion() >> "1.17"
def mappingsDownload = VERSION_META_1_17.download('client_mappings') def mappingsDownload = VERSION_META_1_17.download('client_mappings')
def mappingsFile = new File(tempDir, 'mappings.txt') def mappingsFile = new File(tempDir, 'mappings.txt')
Download.create(mappingsDownload.url()) Download.create(mappingsDownload.url())

View File

@@ -31,6 +31,7 @@ class IntermediaryMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_17_URL intermediaryUrl = INTERMEDIARY_1_17_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
mockMinecraftProvider.minecraftVersion() >> "1.17"
when: when:
def mappings = getSingleMapping(new IntermediaryMappingsSpec()) def mappings = getSingleMapping(new IntermediaryMappingsSpec())
def tiny = getTiny(mappings) def tiny = getTiny(mappings)

View File

@@ -24,6 +24,7 @@
package net.fabricmc.loom.test.unit.layeredmappings package net.fabricmc.loom.test.unit.layeredmappings
import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.util.function.Supplier import java.util.function.Supplier
import java.util.zip.ZipFile import java.util.zip.ZipFile
@@ -45,6 +46,7 @@ import net.fabricmc.loom.configuration.providers.mappings.extras.unpick.UnpickLa
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer
import net.fabricmc.loom.configuration.providers.mappings.utils.AddConstructorMappingVisitor import net.fabricmc.loom.configuration.providers.mappings.utils.AddConstructorMappingVisitor
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider
import net.fabricmc.loom.test.LoomTestConstants
import net.fabricmc.loom.test.unit.LoomMocks import net.fabricmc.loom.test.unit.LoomMocks
import net.fabricmc.loom.util.download.Download import net.fabricmc.loom.util.download.Download
import net.fabricmc.loom.util.download.DownloadBuilder import net.fabricmc.loom.util.download.DownloadBuilder
@@ -60,7 +62,7 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
String intermediaryUrl String intermediaryUrl
MappingContext mappingContext = new TestMappingContext() MappingContext mappingContext = new TestMappingContext()
File tempDir = File.createTempDir() File tempDir = new File(LoomTestConstants.TEST_DIR, "layered/${getClass().name}")
Map<String, File> mavenFiles = [:] Map<String, File> mavenFiles = [:]
@@ -70,8 +72,11 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
File downloadFile(String url, String name) { File downloadFile(String url, String name) {
File dst = new File(tempDir, name) File dst = new File(tempDir, name)
dst.parentFile.mkdirs() if (!dst.exists()) {
dst << new URL(url).newInputStream() Download.create(url)
.defaultCache()
.downloadPath(dst.toPath())
}
return dst return dst
} }
@@ -148,7 +153,15 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
@Override @Override
Supplier<MemoryMappingTree> intermediaryTree() { Supplier<MemoryMappingTree> intermediaryTree() {
return { return {
IntermediateMappingsService.create(LoomMocks.intermediaryMappingsProviderMock("test", intermediaryUrl), minecraftProvider(), null).memoryMappingTree def path = LoomTestConstants.TEST_DIR.toPath().resolve("intermediary").resolve(Objects.requireNonNull(minecraftVersion()) + ".tiny")
if (!Files.exists(path)) {
Files.createDirectories(path.parent)
def provider = LoomMocks.intermediaryMappingsProviderMock(minecraftVersion(), intermediaryUrl)
provider.provide(path, null)
}
return IntermediateMappingsService.createMemoryMappingTree(path, MappingsNamespace.OFFICIAL.toString())
} }
} }

View File

@@ -32,6 +32,7 @@ class MojangMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_17_URL intermediaryUrl = INTERMEDIARY_1_17_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
mockMinecraftProvider.minecraftVersion() >> "1.17"
when: when:
def mappings = getLayeredMappings( def mappings = getLayeredMappings(
new IntermediaryMappingsSpec(), new IntermediaryMappingsSpec(),
@@ -52,6 +53,7 @@ class MojangMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_17_URL intermediaryUrl = INTERMEDIARY_1_17_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
mockMinecraftProvider.minecraftVersion() >> "1.17"
when: when:
def mappings = getLayeredMappings( def mappings = getLayeredMappings(
new IntermediaryMappingsSpec(), new IntermediaryMappingsSpec(),

View File

@@ -34,6 +34,7 @@ class ParchmentMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_16_5_URL intermediaryUrl = INTERMEDIARY_1_16_5_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5
mockMinecraftProvider.minecraftVersion() >> "1.16.5"
when: when:
withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip")) withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip"))
def mappings = getLayeredMappings( def mappings = getLayeredMappings(
@@ -58,6 +59,7 @@ class ParchmentMappingLayerTest extends LayeredMappingsSpecification {
setup: setup:
intermediaryUrl = INTERMEDIARY_1_16_5_URL intermediaryUrl = INTERMEDIARY_1_16_5_URL
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5 mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5
mockMinecraftProvider.minecraftVersion() >> "1.16.5"
when: when:
withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip")) withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip"))
def mappings = getLayeredMappings( def mappings = getLayeredMappings(

View File

@@ -27,13 +27,13 @@ package net.fabricmc.loom.test.unit.service
import org.gradle.api.file.RegularFileProperty import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import net.fabricmc.loom.task.service.NewMappingsService import net.fabricmc.loom.task.service.MappingsService
import net.fabricmc.loom.test.util.GradleTestUtil import net.fabricmc.loom.test.util.GradleTestUtil
class MappingsServiceTest extends ServiceTestBase { class MappingsServiceTest extends ServiceTestBase {
def "get mapping tree"() { def "get mapping tree"() {
given: given:
NewMappingsService service = factory.get(new TestOptions( MappingsService service = factory.get(new TestOptions(
mappingsFile: GradleTestUtil.mockRegularFileProperty(new File("src/test/resources/mappings/PosInChunk.mappings")), mappingsFile: GradleTestUtil.mockRegularFileProperty(new File("src/test/resources/mappings/PosInChunk.mappings")),
from: GradleTestUtil.mockProperty("intermediary"), from: GradleTestUtil.mockProperty("intermediary"),
to: GradleTestUtil.mockProperty("named"), to: GradleTestUtil.mockProperty("named"),
@@ -49,11 +49,12 @@ class MappingsServiceTest extends ServiceTestBase {
service.to == "named" service.to == "named"
} }
static class TestOptions implements NewMappingsService.Options { static class TestOptions implements MappingsService.Options {
RegularFileProperty mappingsFile RegularFileProperty mappingsFile
Property<String> from Property<String> from
Property<String> to Property<String> to
Property<Boolean> remapLocals = GradleTestUtil.mockProperty(false) Property<Boolean> remapLocals = GradleTestUtil.mockProperty(false)
Property<String> serviceClass = serviceClassProperty(NewMappingsService.TYPE) Property<Boolean> AllowNoneExistent = GradleTestUtil.mockProperty(false)
Property<String> serviceClass = serviceClassProperty(MappingsService.TYPE)
} }
} }

View File

@@ -31,9 +31,9 @@ import org.gradle.api.tasks.Input
import spock.lang.Specification import spock.lang.Specification
import net.fabricmc.loom.test.util.GradleTestUtil import net.fabricmc.loom.test.util.GradleTestUtil
import net.fabricmc.loom.util.newService.ScopedServiceFactory import net.fabricmc.loom.util.service.ScopedServiceFactory
import net.fabricmc.loom.util.newService.Service import net.fabricmc.loom.util.service.Service
import net.fabricmc.loom.util.newService.ServiceType import net.fabricmc.loom.util.service.ServiceType
class ScopedServiceFactoryTest extends Specification { class ScopedServiceFactoryTest extends Specification {
def "create service"() { def "create service"() {

View File

@@ -28,9 +28,9 @@ import org.gradle.api.provider.Property
import spock.lang.Specification import spock.lang.Specification
import net.fabricmc.loom.test.util.GradleTestUtil import net.fabricmc.loom.test.util.GradleTestUtil
import net.fabricmc.loom.util.newService.ScopedServiceFactory import net.fabricmc.loom.util.service.ScopedServiceFactory
import net.fabricmc.loom.util.newService.Service import net.fabricmc.loom.util.service.Service
import net.fabricmc.loom.util.newService.ServiceType import net.fabricmc.loom.util.service.ServiceType
abstract class ServiceTestBase extends Specification { abstract class ServiceTestBase extends Specification {
ScopedServiceFactory factory ScopedServiceFactory factory

View File

@@ -31,7 +31,7 @@ import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import org.intellij.lang.annotations.Language import org.intellij.lang.annotations.Language
import net.fabricmc.loom.task.service.NewMappingsService import net.fabricmc.loom.task.service.MappingsService
import net.fabricmc.loom.task.service.SourceRemapperService import net.fabricmc.loom.task.service.SourceRemapperService
import net.fabricmc.loom.test.util.GradleTestUtil import net.fabricmc.loom.test.util.GradleTestUtil
import net.fabricmc.loom.util.DeletingFileVisitor import net.fabricmc.loom.util.DeletingFileVisitor
@@ -87,7 +87,7 @@ class SourceRemapperServiceTest extends ServiceTestBase {
""".trim() """.trim()
static class TestOptions implements SourceRemapperService.Options { static class TestOptions implements SourceRemapperService.Options {
Property<NewMappingsService.Options> mappings Property<MappingsService.Options> mappings
Property<Integer> javaCompileRelease = GradleTestUtil.mockProperty(17) Property<Integer> javaCompileRelease = GradleTestUtil.mockProperty(17)
ConfigurableFileCollection classpath = GradleTestUtil.mockConfigurableFileCollection() ConfigurableFileCollection classpath = GradleTestUtil.mockConfigurableFileCollection()
Property<String> serviceClass = serviceClassProperty(SourceRemapperService.TYPE) Property<String> serviceClass = serviceClassProperty(SourceRemapperService.TYPE)

View File

@@ -52,6 +52,7 @@ class GradleTestUtil {
static <T> Property<T> mockProperty(T value) { static <T> Property<T> mockProperty(T value) {
def mock = mock(Property.class) def mock = mock(Property.class)
when(mock.get()).thenReturn(Objects.requireNonNull(value)) when(mock.get()).thenReturn(Objects.requireNonNull(value))
when(mock.isPresent()).thenReturn(true)
return mock return mock
} }