Fix performance regressions in large multi-project builds. (#571)
* Perf improvements to multi-project builds. * Fixes. * More fixes. * Layered mappings fixes * Perf improvements. Undo broken fix. * Fix remap classpath being empty. * Another gradle bug? Either way this is fine and works. * Fix broken test * Final fixes? * Fix and cleanup mixin ap mappings.
This commit is contained in:
parent
6fd3d5d021
commit
d40241d75a
36 changed files with 1179 additions and 416 deletions
20
build.gradle
20
build.gradle
|
@ -114,14 +114,8 @@ jar {
|
|||
from configurations.bootstrap.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
archiveClassifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
archiveClassifier = 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
spotless {
|
||||
|
@ -197,10 +191,7 @@ publishing {
|
|||
artifactId project.archivesBaseName
|
||||
version project.version
|
||||
|
||||
from components['java']
|
||||
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
from components.java
|
||||
|
||||
pom.withXml {
|
||||
patchPom(asNode())
|
||||
|
@ -213,10 +204,7 @@ publishing {
|
|||
artifactId project.archivesBaseName
|
||||
version baseVersion + '-SNAPSHOT'
|
||||
|
||||
from components['java']
|
||||
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
from components.java
|
||||
|
||||
pom.withXml {
|
||||
patchPom(asNode())
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
package net.fabricmc.loom;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -37,7 +36,6 @@ import org.gradle.api.Project;
|
|||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
|
@ -112,10 +110,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
|||
|
||||
FileCollection getMinecraftJarsCollection(MappingsNamespace mappingsNamespace);
|
||||
|
||||
File getMixinMappings(SourceSet sourceSet);
|
||||
|
||||
FileCollection getAllMixinMappings();
|
||||
|
||||
boolean isRootProject();
|
||||
|
||||
default String getIntermediaryUrl(String minecraftVersion) {
|
||||
|
|
|
@ -37,7 +37,7 @@ public abstract class DecompilerOptions implements Named {
|
|||
/**
|
||||
* Class name for to the {@link LoomDecompiler}.
|
||||
*/
|
||||
public abstract Property<String> getDecompilerClassname();
|
||||
public abstract Property<String> getDecompilerClassName();
|
||||
|
||||
/**
|
||||
* Additional classpath entries for the decompiler jvm.
|
||||
|
@ -60,7 +60,7 @@ public abstract class DecompilerOptions implements Named {
|
|||
public abstract Property<Integer> getMaxThreads();
|
||||
|
||||
public DecompilerOptions() {
|
||||
getDecompilerClassname().finalizeValueOnRead();
|
||||
getDecompilerClassName().finalizeValueOnRead();
|
||||
getClasspath().finalizeValueOnRead();
|
||||
getOptions().finalizeValueOnRead();
|
||||
getMemory().convention(4096L).finalizeValueOnRead();
|
||||
|
@ -71,9 +71,9 @@ public abstract class DecompilerOptions implements Named {
|
|||
public record Dto(String className, Map<String, String> options, int maxThreads) implements Serializable { }
|
||||
|
||||
public Dto toDto() {
|
||||
Preconditions.checkArgument(getDecompilerClassname().isPresent(), "No decompiler classname specified for decompiler: " + getName());
|
||||
Preconditions.checkArgument(getDecompilerClassName().isPresent(), "No decompiler classname specified for decompiler: " + getName());
|
||||
return new Dto(
|
||||
getDecompilerClassname().get(),
|
||||
getDecompilerClassName().get(),
|
||||
getOptions().get(),
|
||||
getMaxThreads().get()
|
||||
);
|
||||
|
|
|
@ -25,13 +25,14 @@
|
|||
package net.fabricmc.loom.api.mappings.layered;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
@ApiStatus.Experimental /* Very Experimental and not cleanly separated from the impl atm */
|
||||
public interface MappingContext {
|
||||
|
@ -39,7 +40,7 @@ public interface MappingContext {
|
|||
|
||||
Path resolveMavenDependency(String mavenNotation);
|
||||
|
||||
MappingsProvider mappingsProvider();
|
||||
Supplier<MemoryMappingTree> intermediaryTree();
|
||||
|
||||
MinecraftProvider minecraftProvider();
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.gradle.api.tasks.SourceSet;
|
|||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||
import net.fabricmc.loom.extension.MixinExtension;
|
||||
import net.fabricmc.loom.task.service.MixinMappingsService;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
/**
|
||||
|
@ -84,7 +85,7 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
|
|||
String refmapName = Objects.requireNonNull(MixinExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
|
||||
Map<String, String> args = new HashMap<>() {{
|
||||
put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, loom.getMappingsProvider().tinyMappings.toFile().getCanonicalPath());
|
||||
put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, loom.getMixinMappings(sourceSet).getCanonicalPath());
|
||||
put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, MixinMappingsService.getMixinMappingFile(project, sourceSet).getCanonicalPath());
|
||||
put(Constants.MixinArguments.OUT_REFMAP_FILE, getRefmapDestination(task, refmapName));
|
||||
put(Constants.MixinArguments.DEFAULT_OBFUSCATION_ENV, "named:intermediary");
|
||||
}};
|
||||
|
|
|
@ -193,15 +193,15 @@ public final class CompileConfiguration {
|
|||
|
||||
boolean split = project.getProperties().get("fabric.loom.experimental.splitMcJars") != null;
|
||||
|
||||
// Provide the vanilla mc jars
|
||||
// Provide the vanilla mc jars -- TODO share across projects.
|
||||
final MinecraftProvider minecraftProvider = split ? new SplitMinecraftProvider(project) : new MergedMinecraftProvider(project);
|
||||
extension.setMinecraftProvider(minecraftProvider);
|
||||
minecraftProvider.provide();
|
||||
|
||||
// Provide the mappings
|
||||
final MappingsProviderImpl mappingsProvider = new MappingsProviderImpl(project, minecraftProvider);
|
||||
final DependencyInfo mappingsDep = DependencyInfo.create(project, Constants.Configurations.MAPPINGS);
|
||||
final MappingsProviderImpl mappingsProvider = MappingsProviderImpl.getInstance(project, mappingsDep, minecraftProvider);
|
||||
extension.setMappingsProvider(mappingsProvider);
|
||||
mappingsProvider.provide();
|
||||
mappingsProvider.applyToProject(project, mappingsDep);
|
||||
|
||||
// Provide the remapped mc jars
|
||||
final IntermediaryMinecraftProvider<?> intermediaryMinecraftProvider;
|
||||
|
|
|
@ -26,6 +26,7 @@ package net.fabricmc.loom.configuration.providers.mappings;
|
|||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
|
@ -36,6 +37,7 @@ import org.gradle.api.logging.Logger;
|
|||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public class GradleMappingContext implements MappingContext {
|
||||
private final Project project;
|
||||
|
@ -62,8 +64,8 @@ public class GradleMappingContext implements MappingContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MappingsProvider mappingsProvider() {
|
||||
return extension.getMappingsProvider();
|
||||
public Supplier<MemoryMappingTree> intermediaryTree() {
|
||||
return () -> IntermediaryService.getInstance(project, minecraftProvider()).getMemoryMappingTree();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.configuration.providers.mappings;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public final class IntermediaryService implements SharedService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(IntermediaryService.class);
|
||||
|
||||
private final Path intermediaryTiny;
|
||||
private final Supplier<MemoryMappingTree> memoryMappingTree = Suppliers.memoize(this::createMemoryMappingTree);
|
||||
|
||||
private IntermediaryService(Path intermediaryTiny) {
|
||||
this.intermediaryTiny = intermediaryTiny;
|
||||
}
|
||||
|
||||
public static synchronized IntermediaryService getInstance(Project project, MinecraftProvider minecraftProvider) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftProvider.minecraftVersion());
|
||||
final String intermediaryArtifactUrl = extension.getIntermediaryUrl(encodedMinecraftVersion);
|
||||
|
||||
return SharedServiceManager.get(project).getOrCreateService("IntermediaryService:" + intermediaryArtifactUrl,
|
||||
() -> create(intermediaryArtifactUrl, minecraftProvider));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static IntermediaryService create(String intermediaryUrl, MinecraftProvider minecraftProvider) {
|
||||
final Path intermediaryTiny = minecraftProvider.file("intermediary-v2.tiny").toPath();
|
||||
|
||||
if (!Files.exists(intermediaryTiny) || LoomGradlePlugin.refreshDeps) {
|
||||
// Download and extract intermediary
|
||||
File intermediaryJar = minecraftProvider.file("intermediary-v2.jar");
|
||||
|
||||
try {
|
||||
DownloadUtil.downloadIfChanged(new URL(intermediaryUrl), intermediaryJar, LOGGER);
|
||||
MappingsProviderImpl.extractMappings(intermediaryJar.toPath(), intermediaryTiny);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to download and extract intermediary", e);
|
||||
}
|
||||
}
|
||||
|
||||
return new IntermediaryService(intermediaryTiny);
|
||||
}
|
||||
|
||||
private MemoryMappingTree createMemoryMappingTree() {
|
||||
final MemoryMappingTree tree = new MemoryMappingTree();
|
||||
|
||||
try {
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(getIntermediaryTiny(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read intermediary mappings", e);
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
public MemoryMappingTree getMemoryMappingTree() {
|
||||
return memoryMappingTree.get();
|
||||
}
|
||||
|
||||
public Path getIntermediaryTiny() {
|
||||
return Objects.requireNonNull(intermediaryTiny, "Intermediary mappings have not been setup");
|
||||
}
|
||||
}
|
|
@ -28,107 +28,135 @@ import java.io.BufferedReader;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.tools.ant.util.StringUtils;
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.DependencyInfo;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.tiny.MappingsMerger;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.tiny.TinyJarInfo;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
import net.fabricmc.loom.util.DownloadUtil;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
import net.fabricmc.stitch.Command;
|
||||
import net.fabricmc.stitch.commands.CommandProposeFieldNames;
|
||||
|
||||
public class MappingsProviderImpl implements MappingsProvider {
|
||||
public String mappingsIdentifier;
|
||||
public class MappingsProviderImpl implements MappingsProvider, SharedService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MappingsProviderImpl.class);
|
||||
|
||||
private Path mappingsWorkingDir;
|
||||
private Path intermediaryTiny;
|
||||
private boolean hasRefreshed = false;
|
||||
private Supplier<MemoryMappingTree> mappingTree;
|
||||
public final String mappingsIdentifier;
|
||||
|
||||
private final Path mappingsWorkingDir;
|
||||
// The mappings that gradle gives us
|
||||
private Path baseTinyMappings;
|
||||
private final Path baseTinyMappings;
|
||||
// The mappings we use in practice
|
||||
public Path tinyMappings;
|
||||
public Path tinyMappingsJar;
|
||||
private Path unpickDefinitions;
|
||||
public final Path tinyMappings;
|
||||
public final Path tinyMappingsJar;
|
||||
private final Path unpickDefinitions;
|
||||
|
||||
private boolean hasUnpickDefinitions;
|
||||
private UnpickMetadata unpickMetadata;
|
||||
private MemoryMappingTree mappingTree;
|
||||
private Map<String, String> signatureFixes;
|
||||
|
||||
private final Project project;
|
||||
private final MinecraftProvider minecraftProvider;
|
||||
private final LoomGradleExtension extension;
|
||||
public MappingsProviderImpl(Project project, MinecraftProvider minecraftProvider) {
|
||||
this.project = project;
|
||||
this.minecraftProvider = minecraftProvider;
|
||||
this.extension = LoomGradleExtension.get(project);
|
||||
private final Supplier<IntermediaryService> intermediaryService;
|
||||
|
||||
private MappingsProviderImpl(String mappingsIdentifier, Path mappingsWorkingDir, Supplier<IntermediaryService> intermediaryService) {
|
||||
this.mappingsIdentifier = mappingsIdentifier;
|
||||
|
||||
this.mappingsWorkingDir = mappingsWorkingDir;
|
||||
this.baseTinyMappings = mappingsWorkingDir.resolve("mappings-base.tiny");
|
||||
this.tinyMappings = mappingsWorkingDir.resolve("mappings.tiny");
|
||||
this.tinyMappingsJar = mappingsWorkingDir.resolve("mappings.jar");
|
||||
this.unpickDefinitions = mappingsWorkingDir.resolve("mappings.unpick");
|
||||
|
||||
this.intermediaryService = intermediaryService;
|
||||
}
|
||||
|
||||
public static synchronized MappingsProviderImpl getInstance(Project project, DependencyInfo dependency, MinecraftProvider minecraftProvider) {
|
||||
return SharedServiceManager.get(project).getOrCreateService("MappingsProvider:%s:%s".formatted(dependency.getDepString(), minecraftProvider.minecraftVersion()), () -> {
|
||||
Supplier<IntermediaryService> intermediaryService = Suppliers.memoize(() -> IntermediaryService.getInstance(project, minecraftProvider));
|
||||
return create(dependency, minecraftProvider, intermediaryService);
|
||||
});
|
||||
}
|
||||
|
||||
public MemoryMappingTree getMappings() throws IOException {
|
||||
return Objects.requireNonNull(mappingTree, "Cannot get mappings before they have been read");
|
||||
return Objects.requireNonNull(mappingTree, "Cannot get mappings before they have been read").get();
|
||||
}
|
||||
|
||||
public void provide() throws Exception {
|
||||
final DependencyInfo dependency = DependencyInfo.create(project, Constants.Configurations.MAPPINGS);
|
||||
private static MappingsProviderImpl create(DependencyInfo dependency, MinecraftProvider minecraftProvider, Supplier<IntermediaryService> intermediaryService) {
|
||||
final String version = dependency.getResolvedVersion();
|
||||
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");
|
||||
|
||||
project.getLogger().info(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")");
|
||||
final TinyJarInfo jarInfo = TinyJarInfo.get(inputJar);
|
||||
jarInfo.minecraftVersionId().ifPresent(id -> {
|
||||
if (!minecraftProvider.minecraftVersion().equals(id)) {
|
||||
LOGGER.warn("The mappings (%s) were not build for minecraft version (%s) produce with caution.".formatted(dependency.getDepString(), minecraftProvider.minecraftVersion()));
|
||||
}
|
||||
});
|
||||
|
||||
String version = dependency.getResolvedVersion();
|
||||
File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency));
|
||||
final String mappingsIdentifier = createMappingsIdentifier(mappingsName, version, getMappingsClassifier(dependency, jarInfo.v2()), minecraftProvider.minecraftVersion());
|
||||
final Path workingDir = minecraftProvider.dir(mappingsIdentifier).toPath();
|
||||
|
||||
String mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");
|
||||
boolean isV2 = isV2(dependency, mappingsJar);
|
||||
this.mappingsIdentifier = createMappingsIdentifier(mappingsName, version, getMappingsClassifier(dependency, isV2));
|
||||
var mappingProvider = new MappingsProviderImpl(mappingsIdentifier, workingDir, intermediaryService);
|
||||
|
||||
initFiles();
|
||||
try {
|
||||
mappingProvider.setup(minecraftProvider, inputJar);
|
||||
} catch (IOException e) {
|
||||
cleanWorkingDirectory(workingDir);
|
||||
throw new UncheckedIOException("Failed to setup mappings: " + dependency.getDepString(), e);
|
||||
}
|
||||
|
||||
return mappingProvider;
|
||||
}
|
||||
|
||||
private void setup(MinecraftProvider minecraftProvider, Path inputJar) throws IOException {
|
||||
if (isRefreshDeps()) {
|
||||
cleanWorkingDirectory(mappingsWorkingDir);
|
||||
}
|
||||
|
||||
if (Files.notExists(tinyMappings) || isRefreshDeps()) {
|
||||
storeMappings(project, minecraftProvider, mappingsJar.toPath());
|
||||
storeMappings(minecraftProvider, inputJar);
|
||||
} else {
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) {
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(inputJar, (ClassLoader) null)) {
|
||||
extractExtras(fileSystem);
|
||||
}
|
||||
}
|
||||
|
||||
mappingTree = readMappings();
|
||||
|
||||
if (Files.notExists(tinyMappingsJar) || isRefreshDeps()) {
|
||||
Files.deleteIfExists(tinyMappingsJar);
|
||||
ZipUtils.add(tinyMappingsJar, "mappings/mappings.tiny", Files.readAllBytes(tinyMappings));
|
||||
}
|
||||
|
||||
mappingTree = Suppliers.memoize(this::readMappings);
|
||||
}
|
||||
|
||||
public void applyToProject(Project project, DependencyInfo dependency) {
|
||||
if (hasUnpickDefinitions()) {
|
||||
String notation = String.format("%s:%s:%s:constants",
|
||||
dependency.getDependency().getGroup(),
|
||||
|
@ -137,13 +165,13 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
);
|
||||
|
||||
project.getDependencies().add(Constants.Configurations.MAPPING_CONSTANTS, notation);
|
||||
populateUnpickClasspath();
|
||||
populateUnpickClasspath(project);
|
||||
}
|
||||
|
||||
project.getDependencies().add(Constants.Configurations.MAPPINGS_FINAL, project.files(tinyMappingsJar.toFile()));
|
||||
}
|
||||
|
||||
private String getMappingsClassifier(DependencyInfo dependency, boolean isV2) {
|
||||
private static String getMappingsClassifier(DependencyInfo dependency, boolean isV2) {
|
||||
String[] depStringSplit = dependency.getDepString().split(":");
|
||||
|
||||
if (depStringSplit.length >= 4) {
|
||||
|
@ -153,42 +181,22 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
return isV2 ? "-v2" : "";
|
||||
}
|
||||
|
||||
private boolean isV2(DependencyInfo dependency, File mappingsJar) throws IOException {
|
||||
String minecraftVersion = minecraftProvider.minecraftVersion();
|
||||
private void storeMappings(MinecraftProvider minecraftProvider, Path inputJar) throws IOException {
|
||||
LOGGER.info(":extracting " + inputJar.getFileName());
|
||||
|
||||
// Only do this for official yarn, there isn't really a way we can get the mc version for all mappings
|
||||
if (dependency.getDependency().getGroup() != null && dependency.getDependency().getGroup().equals("net.fabricmc") && dependency.getDependency().getName().equals("yarn") && dependency.getDependency().getVersion() != null) {
|
||||
String yarnVersion = dependency.getDependency().getVersion();
|
||||
char separator = yarnVersion.contains("+build.") ? '+' : yarnVersion.contains("-") ? '-' : '.';
|
||||
String yarnMinecraftVersion = yarnVersion.substring(0, yarnVersion.lastIndexOf(separator));
|
||||
|
||||
if (!yarnMinecraftVersion.equalsIgnoreCase(minecraftVersion)) {
|
||||
project.getLogger().warn("Minecraft Version ({}) does not match yarn's minecraft version ({})", minecraftVersion, yarnMinecraftVersion);
|
||||
}
|
||||
|
||||
// We can save reading the zip file + header by checking the file name
|
||||
return mappingsJar.getName().endsWith("-v2.jar");
|
||||
} else {
|
||||
return doesJarContainV2Mappings(mappingsJar.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar) throws IOException {
|
||||
project.getLogger().info(":extracting " + yarnJar.getFileName());
|
||||
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) {
|
||||
try (FileSystem fileSystem = FileSystems.newFileSystem(inputJar, (ClassLoader) null)) {
|
||||
extractMappings(fileSystem, baseTinyMappings);
|
||||
extractExtras(fileSystem);
|
||||
}
|
||||
|
||||
if (areMappingsV2(baseTinyMappings)) {
|
||||
// These are unmerged v2 mappings
|
||||
mergeAndSaveMappings(project, baseTinyMappings, tinyMappings);
|
||||
MappingsMerger.mergeAndSaveMappings(baseTinyMappings, tinyMappings, intermediaryService.get());
|
||||
} else {
|
||||
if (minecraftProvider instanceof MergedMinecraftProvider mergedMinecraftProvider) {
|
||||
// These are merged v1 mappings
|
||||
Files.deleteIfExists(tinyMappings);
|
||||
project.getLogger().lifecycle(":populating field names");
|
||||
LOGGER.info(":populating field names");
|
||||
suggestFieldNames(mergedMinecraftProvider, baseTinyMappings, tinyMappings);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("V1 mappings only support merged minecraft");
|
||||
|
@ -196,10 +204,14 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private MemoryMappingTree readMappings() throws IOException {
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
MappingReader.read(tinyMappings, mappingTree);
|
||||
return mappingTree;
|
||||
private MemoryMappingTree readMappings() {
|
||||
try {
|
||||
MemoryMappingTree mappingTree = new MemoryMappingTree();
|
||||
MappingReader.read(tinyMappings, mappingTree);
|
||||
return mappingTree;
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean areMappingsV2(Path path) throws IOException {
|
||||
|
@ -208,15 +220,7 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean doesJarContainV2Mappings(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) {
|
||||
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractMappings(Path jar, Path extractTo) throws IOException {
|
||||
public static void extractMappings(Path jar, Path extractTo) throws IOException {
|
||||
try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(jar, (ClassLoader) null)) {
|
||||
extractMappings(unmergedIntermediaryFs, extractTo);
|
||||
}
|
||||
|
@ -271,7 +275,7 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
);
|
||||
}
|
||||
|
||||
private void populateUnpickClasspath() {
|
||||
private void populateUnpickClasspath(Project project) {
|
||||
String unpickCliName = "unpick-cli";
|
||||
project.getDependencies().add(Constants.Configurations.UNPICK_CLASSPATH,
|
||||
String.format("%s:%s:%s", unpickMetadata.unpickGroup, unpickCliName, unpickMetadata.unpickVersion)
|
||||
|
@ -292,76 +296,6 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private void mergeAndSaveMappings(Project project, Path from, Path out) throws IOException {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
project.getLogger().info(":merging mappings");
|
||||
|
||||
MemoryMappingTree intermediaryTree = new MemoryMappingTree();
|
||||
readIntermediaryTree().accept(new MappingSourceNsSwitch(intermediaryTree, MappingsNamespace.INTERMEDIARY.toString()));
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(from, StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, intermediaryTree);
|
||||
}
|
||||
|
||||
MemoryMappingTree officialTree = new MemoryMappingTree();
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(officialTree, Map.of(MappingsNamespace.OFFICIAL.toString(), MappingsNamespace.INTERMEDIARY.toString()));
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsCompleter, MappingsNamespace.OFFICIAL.toString());
|
||||
intermediaryTree.accept(nsSwitch);
|
||||
|
||||
inheritMappedNamesOfEnclosingClasses(officialTree);
|
||||
|
||||
try (Tiny2Writer writer = new Tiny2Writer(Files.newBufferedWriter(out, StandardCharsets.UTF_8), false)) {
|
||||
officialTree.accept(writer);
|
||||
}
|
||||
|
||||
project.getLogger().info(":merged mappings in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the mapping tree for inner classes with no mapped name, whose enclosing classes have mapped names.
|
||||
* Currently, Yarn does not export mappings for these inner classes.
|
||||
*/
|
||||
private void inheritMappedNamesOfEnclosingClasses(MemoryMappingTree tree) {
|
||||
int intermediaryIdx = tree.getNamespaceId("intermediary");
|
||||
int namedIdx = tree.getNamespaceId("named");
|
||||
|
||||
// The tree does not have an index by intermediary names by default
|
||||
tree.setIndexByDstNames(true);
|
||||
|
||||
for (MappingTree.ClassMapping classEntry : tree.getClasses()) {
|
||||
String intermediaryName = classEntry.getDstName(intermediaryIdx);
|
||||
String namedName = classEntry.getDstName(namedIdx);
|
||||
|
||||
if (intermediaryName.equals(namedName) && intermediaryName.contains("$")) {
|
||||
String[] path = intermediaryName.split(Pattern.quote("$"));
|
||||
int parts = path.length;
|
||||
|
||||
for (int i = parts - 2; i >= 0; i--) {
|
||||
String currentPath = String.join("$", Arrays.copyOfRange(path, 0, i + 1));
|
||||
String namedParentClass = tree.mapClassName(currentPath, intermediaryIdx, namedIdx);
|
||||
|
||||
if (!namedParentClass.equals(currentPath)) {
|
||||
classEntry.setDstName(namedParentClass
|
||||
+ "$" + String.join("$", Arrays.copyOfRange(path, i + 1, path.length)),
|
||||
namedIdx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MemoryMappingTree readIntermediaryTree() throws IOException {
|
||||
MemoryMappingTree tree = new MemoryMappingTree();
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(getIntermediaryTiny(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void suggestFieldNames(MergedMinecraftProvider minecraftProvider, Path oldMappings, Path newMappings) {
|
||||
Command command = new CommandProposeFieldNames();
|
||||
runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(),
|
||||
|
@ -377,19 +311,7 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private void initFiles() {
|
||||
mappingsWorkingDir = minecraftProvider.dir(mappingsIdentifier).toPath();
|
||||
baseTinyMappings = mappingsWorkingDir.resolve("mappings-base.tiny");
|
||||
tinyMappings = mappingsWorkingDir.resolve("mappings.tiny");
|
||||
tinyMappingsJar = mappingsWorkingDir.resolve("mappings.jar");
|
||||
unpickDefinitions = mappingsWorkingDir.resolve("mappings.unpick");
|
||||
|
||||
if (isRefreshDeps()) {
|
||||
cleanFiles();
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanFiles() {
|
||||
private static void cleanWorkingDirectory(Path mappingsWorkingDir) {
|
||||
try {
|
||||
if (Files.exists(mappingsWorkingDir)) {
|
||||
Files.walkFileTree(mappingsWorkingDir, new DeletingFileVisitor());
|
||||
|
@ -401,34 +323,20 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
public Path getIntermediaryTiny() throws IOException {
|
||||
if (intermediaryTiny == null) {
|
||||
intermediaryTiny = minecraftProvider.file("intermediary-v2.tiny").toPath();
|
||||
|
||||
if (!Files.exists(intermediaryTiny) || (isRefreshDeps() && !hasRefreshed)) {
|
||||
hasRefreshed = true;
|
||||
|
||||
// Download and extract intermediary
|
||||
String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftProvider.minecraftVersion());
|
||||
String intermediaryArtifactUrl = extension.getIntermediaryUrl(encodedMinecraftVersion);
|
||||
File intermediaryJar = minecraftProvider.file("intermediary-v2.jar");
|
||||
DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar, project.getLogger());
|
||||
extractMappings(intermediaryJar.toPath(), intermediaryTiny);
|
||||
}
|
||||
}
|
||||
|
||||
return intermediaryTiny;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path mappingsWorkingDir() {
|
||||
return mappingsWorkingDir;
|
||||
}
|
||||
|
||||
private String createMappingsIdentifier(String mappingsName, String version, String classifier) {
|
||||
@Override
|
||||
public File intermediaryTinyFile() {
|
||||
return intermediaryService.get().getIntermediaryTiny().toFile();
|
||||
}
|
||||
|
||||
private static String createMappingsIdentifier(String mappingsName, String version, String classifier, String minecraftVersion) {
|
||||
// mappingsName . mcVersion . version classifier
|
||||
// Example: net.fabricmc.yarn . 1_16_5 . 1.16.5+build.5 -v2
|
||||
return mappingsName + "." + minecraftProvider.minecraftVersion().replace(' ', '_').replace('.', '_').replace('-', '_') + "." + version + classifier;
|
||||
return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + version + classifier;
|
||||
}
|
||||
|
||||
public String mappingsIdentifier() {
|
||||
|
@ -448,15 +356,6 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
return signatureFixes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File intermediaryTinyFile() {
|
||||
try {
|
||||
return getIntermediaryTiny().toFile();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to get intermediary", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getBuildServiceName(String name, String from, String to) {
|
||||
return "%s:%s:%s>%S".formatted(name, mappingsIdentifier(), from, to);
|
||||
}
|
||||
|
@ -464,7 +363,12 @@ public class MappingsProviderImpl implements MappingsProvider {
|
|||
public record UnpickMetadata(String unpickGroup, String unpickVersion) {
|
||||
}
|
||||
|
||||
protected boolean isRefreshDeps() {
|
||||
protected static boolean isRefreshDeps() {
|
||||
return LoomGradlePlugin.refreshDeps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
mappingTree = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,20 +24,17 @@
|
|||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.intermediary;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public record IntermediaryMappingLayer(File tinyFile) implements MappingLayer {
|
||||
public record IntermediaryMappingLayer(Supplier<MemoryMappingTree> memoryMappingTree) implements MappingLayer {
|
||||
@Override
|
||||
public MappingsNamespace getSourceNamespace() {
|
||||
return MappingsNamespace.OFFICIAL;
|
||||
|
@ -48,8 +45,6 @@ public record IntermediaryMappingLayer(File tinyFile) implements MappingLayer {
|
|||
// Populate named with intermediary and add Add a "named" namespace
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true);
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(tinyFile().toPath(), StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, nsCompleter);
|
||||
}
|
||||
memoryMappingTree.get().accept(nsCompleter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,6 @@ import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
|||
public record IntermediaryMappingsSpec() implements MappingsSpec<IntermediaryMappingLayer> {
|
||||
@Override
|
||||
public IntermediaryMappingLayer createLayer(MappingContext context) {
|
||||
return new IntermediaryMappingLayer(context.mappingsProvider().intermediaryTinyFile());
|
||||
return new IntermediaryMappingLayer(context.intermediaryTree());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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.configuration.providers.mappings.tiny;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.IntermediaryService;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.Tiny2Reader;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public final class MappingsMerger {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MappingsMerger.class);
|
||||
|
||||
public static void mergeAndSaveMappings(Path from, Path out, IntermediaryService intermediaryService) throws IOException {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
LOGGER.info(":merging mappings");
|
||||
|
||||
MemoryMappingTree intermediaryTree = new MemoryMappingTree();
|
||||
intermediaryService.getMemoryMappingTree().accept(new MappingSourceNsSwitch(intermediaryTree, MappingsNamespace.INTERMEDIARY.toString()));
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(from, StandardCharsets.UTF_8)) {
|
||||
Tiny2Reader.read(reader, intermediaryTree);
|
||||
}
|
||||
|
||||
MemoryMappingTree officialTree = new MemoryMappingTree();
|
||||
MappingNsCompleter nsCompleter = new MappingNsCompleter(officialTree, Map.of(MappingsNamespace.OFFICIAL.toString(), MappingsNamespace.INTERMEDIARY.toString()));
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsCompleter, MappingsNamespace.OFFICIAL.toString());
|
||||
intermediaryTree.accept(nsSwitch);
|
||||
|
||||
inheritMappedNamesOfEnclosingClasses(officialTree);
|
||||
|
||||
try (Tiny2Writer writer = new Tiny2Writer(Files.newBufferedWriter(out, StandardCharsets.UTF_8), false)) {
|
||||
officialTree.accept(writer);
|
||||
}
|
||||
|
||||
LOGGER.info(":merged mappings in " + stopwatch.stop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the mapping tree for inner classes with no mapped name, whose enclosing classes have mapped names.
|
||||
* Currently, Yarn does not export mappings for these inner classes.
|
||||
*/
|
||||
private static void inheritMappedNamesOfEnclosingClasses(MemoryMappingTree tree) {
|
||||
int intermediaryIdx = tree.getNamespaceId("intermediary");
|
||||
int namedIdx = tree.getNamespaceId("named");
|
||||
|
||||
// The tree does not have an index by intermediary names by default
|
||||
tree.setIndexByDstNames(true);
|
||||
|
||||
for (MappingTree.ClassMapping classEntry : tree.getClasses()) {
|
||||
String intermediaryName = classEntry.getDstName(intermediaryIdx);
|
||||
String namedName = classEntry.getDstName(namedIdx);
|
||||
|
||||
if (intermediaryName.equals(namedName) && intermediaryName.contains("$")) {
|
||||
String[] path = intermediaryName.split(Pattern.quote("$"));
|
||||
int parts = path.length;
|
||||
|
||||
for (int i = parts - 2; i >= 0; i--) {
|
||||
String currentPath = String.join("$", Arrays.copyOfRange(path, 0, i + 1));
|
||||
String namedParentClass = tree.mapClassName(currentPath, intermediaryIdx, namedIdx);
|
||||
|
||||
if (!namedParentClass.equals(currentPath)) {
|
||||
classEntry.setDstName(namedParentClass
|
||||
+ "$" + String.join("$", Arrays.copyOfRange(path, i + 1, path.length)),
|
||||
namedIdx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.configuration.providers.mappings.tiny;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
|
||||
public record TinyJarInfo(boolean v2, Optional<String> minecraftVersionId) {
|
||||
public static TinyJarInfo get(Path jar) {
|
||||
try {
|
||||
return new TinyJarInfo(doesJarContainV2Mappings(jar), Optional.empty());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read tiny jar info", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean doesJarContainV2Mappings(Path path) throws IOException {
|
||||
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) {
|
||||
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,6 +41,6 @@ public final class DecompilerConfiguration {
|
|||
}
|
||||
|
||||
private static void registerDecompiler(Project project, String name, Class<? extends LoomDecompiler> decompilerClass) {
|
||||
LoomGradleExtension.get(project).getDecompilerOptions().register(name, options -> options.getDecompilerClassname().set(decompilerClass.getName()));
|
||||
LoomGradleExtension.get(project).getDecompilerOptions().register(name, options -> options.getDecompilerClassName().set(decompilerClass.getName()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
package net.fabricmc.loom.extension;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -41,7 +40,6 @@ import org.gradle.api.Project;
|
|||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
|
@ -60,7 +58,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
|||
private final LoomFiles loomFiles;
|
||||
private final ConfigurableFileCollection unmappedMods;
|
||||
|
||||
private final ConfigurableFileCollection mixinMappings;
|
||||
private final MappingSet[] srcMappingCache = new MappingSet[2];
|
||||
private final Mercury[] srcMercuryCache = new Mercury[2];
|
||||
private final Map<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>();
|
||||
|
@ -79,7 +76,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
|||
this.project = project;
|
||||
// Initiate with newInstance to allow gradle to decorate our extension
|
||||
this.mixinApExtension = project.getObjects().newInstance(MixinExtensionImpl.class, project);
|
||||
this.mixinMappings = project.getObjects().fileCollection();
|
||||
this.loomFiles = files;
|
||||
this.unmappedMods = project.files();
|
||||
}
|
||||
|
@ -94,18 +90,6 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
|
|||
return loomFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized File getMixinMappings(SourceSet sourceSet) {
|
||||
File mixinMapping = new File(getFiles().getProjectBuildCache(), "mixin-map-" + getMappingsProvider().mappingsIdentifier() + "." + sourceSet.getName() + ".tiny");
|
||||
mixinMappings.from(getProject().files(mixinMapping));
|
||||
return mixinMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileCollection getAllMixinMappings() {
|
||||
return mixinMappings.filter(File::exists);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDependencyManager(LoomDependencyManager dependencyManager) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
|
|
108
src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java
Normal file
108
src/main/java/net/fabricmc/loom/task/PrepareJarRemapTask.java
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.task;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.workers.WorkAction;
|
||||
import org.gradle.workers.WorkParameters;
|
||||
import org.gradle.workers.WorkQueue;
|
||||
import org.gradle.workers.WorkerExecutor;
|
||||
|
||||
import net.fabricmc.loom.task.service.TinyRemapperService;
|
||||
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
/**
|
||||
* The prepare remap task runs before all other jar remap tasks, should be used to setup tiny remapper.
|
||||
*/
|
||||
public abstract class PrepareJarRemapTask extends AbstractLoomTask {
|
||||
private final RemapJarTask remapJarTask;
|
||||
@InputFile
|
||||
public abstract RegularFileProperty getInputFile();
|
||||
|
||||
@Inject
|
||||
public PrepareJarRemapTask(RemapJarTask remapJarTask) {
|
||||
this.remapJarTask = remapJarTask;
|
||||
|
||||
getInputFile().set(remapJarTask.getInputFile());
|
||||
// TODO can this be up-to-date when the main task is up-to date?
|
||||
getOutputs().upToDateWhen((o) -> false);
|
||||
|
||||
getProject().getGradle().allprojects(project -> {
|
||||
project.getTasks().configureEach(task -> {
|
||||
if (task instanceof PrepareJarRemapTask otherTask) {
|
||||
if (otherTask == this) return;
|
||||
|
||||
// Ensure that all other prepare tasks inputs have completed
|
||||
dependsOn(otherTask.getInputs());
|
||||
mustRunAfter(otherTask.getInputs());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected abstract WorkerExecutor getWorkerExecutor();
|
||||
|
||||
@TaskAction
|
||||
public void run() {
|
||||
final WorkQueue workQueue = getWorkerExecutor().noIsolation();
|
||||
|
||||
workQueue.submit(ReadInputsAction.class, params -> {
|
||||
params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), remapJarTask.getTinyRemapperService()));
|
||||
params.getInputTagName().set(remapJarTask.getInputTagName());
|
||||
params.getInputFile().set(getInputFile());
|
||||
});
|
||||
}
|
||||
|
||||
public interface ReadInputsParams extends WorkParameters {
|
||||
Property<String> getTinyRemapperBuildServiceUuid();
|
||||
Property<String> getInputTagName();
|
||||
RegularFileProperty getInputFile();
|
||||
}
|
||||
|
||||
public abstract static class ReadInputsAction implements WorkAction<ReadInputsParams> {
|
||||
private final TinyRemapperService tinyRemapperService;
|
||||
|
||||
public ReadInputsAction() {
|
||||
this.tinyRemapperService = UnsafeWorkQueueHelper.get(getParameters().getTinyRemapperBuildServiceUuid(), TinyRemapperService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final TinyRemapper tinyRemapper = tinyRemapperService.getTinyRemapperForInputs();
|
||||
final Path inputFile = getParameters().getInputFile().getAsFile().get().toPath();
|
||||
|
||||
tinyRemapper.readInputsAsync(tinyRemapperService.createTag(getParameters().getInputTagName().get()), inputFile);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@ package net.fabricmc.loom.task;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
|
@ -34,12 +33,14 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
|
@ -47,12 +48,11 @@ import org.gradle.api.file.FileCollection;
|
|||
import org.gradle.api.plugins.JavaPlugin;
|
||||
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.InputFiles;
|
||||
import org.gradle.api.tasks.Internal;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -60,20 +60,18 @@ import net.fabricmc.accesswidener.AccessWidenerReader;
|
|||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerWriter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.build.MixinRefmapHelper;
|
||||
import net.fabricmc.loom.build.nesting.IncludedJarFactory;
|
||||
import net.fabricmc.loom.build.nesting.JarNester;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
|
||||
import net.fabricmc.loom.extension.MixinExtension;
|
||||
import net.fabricmc.loom.task.service.JarManifestService;
|
||||
import net.fabricmc.loom.task.service.MappingsService;
|
||||
import net.fabricmc.loom.task.service.TinyRemapperService;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.tinyremapper.InputTag;
|
||||
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
|
||||
import net.fabricmc.tinyremapper.OutputConsumerPath;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
import net.fabricmc.tinyremapper.TinyUtils;
|
||||
|
||||
public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
|
||||
|
@ -84,6 +82,8 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
@Input
|
||||
public abstract Property<Boolean> getAddNestedDependencies();
|
||||
|
||||
private Supplier<TinyRemapperService> tinyRemapperService = Suppliers.memoize(() -> TinyRemapperService.getOrCreate(this));
|
||||
|
||||
@Inject
|
||||
public RemapJarTask() {
|
||||
super();
|
||||
|
@ -93,6 +93,25 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
|
||||
Configuration includeConfiguration = getProject().getConfigurations().getByName(Constants.Configurations.INCLUDE);
|
||||
getNestedJars().from(new IncludedJarFactory(getProject()).getNestedJars(includeConfiguration));
|
||||
|
||||
setupPreparationTask();
|
||||
}
|
||||
|
||||
private void setupPreparationTask() {
|
||||
PrepareJarRemapTask prepareJarTask = getProject().getTasks().create("prepare" + getName().substring(0, 1).toUpperCase() + getName().substring(1), PrepareJarRemapTask.class, this);
|
||||
|
||||
dependsOn(prepareJarTask);
|
||||
mustRunAfter(prepareJarTask);
|
||||
|
||||
getProject().getGradle().allprojects(project -> {
|
||||
project.getTasks().configureEach(task -> {
|
||||
if (task instanceof PrepareJarRemapTask otherTask) {
|
||||
// Ensure that all remap jars run after all prepare tasks
|
||||
dependsOn(otherTask);
|
||||
mustRunAfter(otherTask);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
|
@ -105,14 +124,14 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
}
|
||||
|
||||
params.getJarManifestService().set(JarManifestService.get(getProject()));
|
||||
params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), tinyRemapperService.get()));
|
||||
params.getRemapClasspath().from(getClasspath());
|
||||
params.getMappings().add(MappingsService.createDefault(getProject(), getSourceNamespace().get(), getTargetNamespace().get()));
|
||||
params.getInputTagName().set(getInputTagName());
|
||||
|
||||
final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get();
|
||||
params.getUseMixinExtension().set(!legacyMixin);
|
||||
|
||||
if (legacyMixin) {
|
||||
params.getMixinMappings().from(extension.getAllMixinMappings());
|
||||
setupLegacyMixinRefmapRemapping(params);
|
||||
}
|
||||
});
|
||||
|
@ -174,8 +193,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
public interface RemapParams extends AbstractRemapParams {
|
||||
ConfigurableFileCollection getNestedJars();
|
||||
ConfigurableFileCollection getRemapClasspath();
|
||||
ConfigurableFileCollection getMixinMappings();
|
||||
ListProperty<Provider<MappingsService>> getMappings();
|
||||
Property<String> getInputTagName();
|
||||
|
||||
Property<Boolean> getUseMixinExtension();
|
||||
|
||||
|
@ -183,19 +201,25 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
ListProperty<RefmapData> getMixinData();
|
||||
|
||||
Property<JarManifestService> getJarManifestService();
|
||||
Property<String> getTinyRemapperBuildServiceUuid();
|
||||
}
|
||||
|
||||
public abstract static class RemapAction extends AbstractRemapAction<RemapParams> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RemapAction.class);
|
||||
|
||||
private final TinyRemapperService tinyRemapperService;
|
||||
private TinyRemapper tinyRemapper;
|
||||
|
||||
public RemapAction() {
|
||||
this.tinyRemapperService = UnsafeWorkQueueHelper.get(getParameters().getTinyRemapperBuildServiceUuid(), TinyRemapperService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
LOGGER.info("Remapping {} to {}", inputFile, outputFile);
|
||||
|
||||
tinyRemapper = createTinyRemapper();
|
||||
tinyRemapper = tinyRemapperService.getTinyRemapperForRemapping();
|
||||
|
||||
remap();
|
||||
remapAccessWidener();
|
||||
|
@ -204,9 +228,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
modifyJarManifest();
|
||||
rewriteJar();
|
||||
|
||||
tinyRemapper.finish();
|
||||
tinyRemapper = null;
|
||||
|
||||
LOGGER.debug("Finished remapping {}", inputFile);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
|
@ -220,13 +241,9 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
}
|
||||
|
||||
private void remap() throws IOException {
|
||||
final InputTag inputTag = tinyRemapper.createInputTag();
|
||||
|
||||
tinyRemapper.readInputsAsync(inputTag, inputFile);
|
||||
|
||||
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(outputFile).build()) {
|
||||
outputConsumer.addNonClassFiles(inputFile);
|
||||
tinyRemapper.apply(outputConsumer, inputTag);
|
||||
tinyRemapper.apply(outputConsumer, tinyRemapperService.getTag(getParameters().getInputTagName().get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,21 +254,21 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
return;
|
||||
}
|
||||
|
||||
byte[] remapped = remapAccessWidener(accessWidenerFile.content(), tinyRemapper.getEnvironment().getRemapper(), MappingsNamespace.INTERMEDIARY.toString());
|
||||
byte[] remapped = remapAccessWidener(accessWidenerFile.content());
|
||||
|
||||
// Finally, replace the output with the remaped aw
|
||||
ZipUtils.replace(outputFile, accessWidenerFile.path(), remapped);
|
||||
}
|
||||
|
||||
private static byte[] remapAccessWidener(byte[] input, Remapper asmRemapper, String targetNamespace) {
|
||||
private byte[] remapAccessWidener(byte[] input) {
|
||||
int version = AccessWidenerReader.readVersion(input);
|
||||
|
||||
AccessWidenerWriter writer = new AccessWidenerWriter(version);
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(
|
||||
writer,
|
||||
asmRemapper,
|
||||
MappingsNamespace.NAMED.toString(),
|
||||
targetNamespace
|
||||
tinyRemapper.getEnvironment().getRemapper(),
|
||||
getParameters().getSourceNamespace().get(),
|
||||
getParameters().getTargetNamespace().get()
|
||||
);
|
||||
AccessWidenerReader reader = new AccessWidenerReader(remapper);
|
||||
reader.read(input);
|
||||
|
@ -300,30 +317,15 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
|||
})));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TinyRemapper createTinyRemapper() {
|
||||
TinyRemapper.Builder builder = TinyRemapper.newRemapper();
|
||||
@Internal
|
||||
public TinyRemapperService getTinyRemapperService() {
|
||||
return tinyRemapperService.get();
|
||||
}
|
||||
|
||||
for (Provider<MappingsService> provider : getParameters().getMappings().get()) {
|
||||
builder.withMappings(provider.get().getMappingsProvider());
|
||||
}
|
||||
|
||||
for (File mixinMapping : getParameters().getMixinMappings()) {
|
||||
builder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapping.toPath(), getParameters().getSourceNamespace().get(), getParameters().getTargetNamespace().get()));
|
||||
}
|
||||
|
||||
if (getParameters().getUseMixinExtension().get()) {
|
||||
builder.extension(new net.fabricmc.tinyremapper.extension.mixin.MixinExtension());
|
||||
}
|
||||
|
||||
TinyRemapper remapper = builder.build();
|
||||
|
||||
// Apply classpath
|
||||
for (File file : getParameters().getRemapClasspath()) {
|
||||
remapper.readClassPathAsync(file.toPath());
|
||||
}
|
||||
|
||||
return remapper;
|
||||
}
|
||||
@Internal
|
||||
String getInputTagName() {
|
||||
return getProject().getPath() + getName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,8 @@ import org.gradle.api.tasks.TaskAction;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.task.service.MappingsService;
|
||||
import net.fabricmc.loom.task.service.SourceRemapperService;
|
||||
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
|
||||
|
||||
public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
|
||||
@Inject
|
||||
|
@ -49,12 +49,12 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
|
|||
@TaskAction
|
||||
public void run() {
|
||||
submitWork(RemapSourcesAction.class, params -> {
|
||||
params.getSourcesRemapperService().set(SourceRemapperService.create(getProject(), MappingsService.createDefault(getProject(), getSourceNamespace().get(), getTargetNamespace().get()), getClasspath()));
|
||||
params.getSourcesRemapperServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), SourceRemapperService.create(this)));
|
||||
});
|
||||
}
|
||||
|
||||
public interface RemapSourcesParams extends AbstractRemapParams {
|
||||
Property<SourceRemapperService> getSourcesRemapperService();
|
||||
Property<String> getSourcesRemapperServiceUuid();
|
||||
}
|
||||
|
||||
public abstract static class RemapSourcesAction extends AbstractRemapAction<RemapSourcesParams> {
|
||||
|
@ -65,7 +65,7 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
|
|||
public RemapSourcesAction() {
|
||||
super();
|
||||
|
||||
sourceRemapperService = getParameters().getSourcesRemapperService().get();
|
||||
sourceRemapperService = UnsafeWorkQueueHelper.get(getParameters().getSourcesRemapperServiceUuid(), SourceRemapperService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,8 +54,8 @@ public class RemapTaskConfiguration {
|
|||
return;
|
||||
}
|
||||
|
||||
// Register the default remap jar task
|
||||
TaskProvider<RemapJarTask> remapJarTaskProvider = tasks.register(REMAP_JAR_TASK_NAME, RemapJarTask.class, task -> {
|
||||
// Register the default remap jar task - must not be lazy to ensure that the prepare tasks get setup for other projects to depend on.
|
||||
RemapJarTask remapJarTask = tasks.create(REMAP_JAR_TASK_NAME, RemapJarTask.class, task -> {
|
||||
final AbstractArchiveTask jarTask = tasks.named(JavaPlugin.JAR_TASK_NAME, AbstractArchiveTask.class).get();
|
||||
|
||||
// Basic task setup
|
||||
|
@ -76,7 +76,7 @@ public class RemapTaskConfiguration {
|
|||
task.getDestinationDirectory().set(new File(project.getBuildDir(), "devlibs"));
|
||||
});
|
||||
|
||||
tasks.named(BasePlugin.ASSEMBLE_TASK_NAME).configure(task -> task.dependsOn(remapJarTaskProvider));
|
||||
tasks.named(BasePlugin.ASSEMBLE_TASK_NAME).configure(task -> task.dependsOn(remapJarTask));
|
||||
|
||||
trySetupSourceRemapping(project);
|
||||
|
||||
|
|
|
@ -24,49 +24,45 @@
|
|||
|
||||
package net.fabricmc.loom.task.service;
|
||||
|
||||
import java.io.File;
|
||||
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.services.BuildService;
|
||||
import org.gradle.api.services.BuildServiceParameters;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
import net.fabricmc.tinyremapper.IMappingProvider;
|
||||
|
||||
public abstract class MappingsService implements BuildService<MappingsService.Params>, AutoCloseable {
|
||||
interface Params extends BuildServiceParameters {
|
||||
RegularFileProperty getMappingsFile();
|
||||
public final class MappingsService implements SharedService {
|
||||
private record Options(Path mappingsFile, String from, String to, boolean remapLocals) { }
|
||||
|
||||
Property<String> getFromNamespace();
|
||||
Property<String> getToNamespace();
|
||||
|
||||
Property<Boolean> getRemapLocals();
|
||||
public static MappingsService create(Project project, String name, Path mappingsFile, String from, String to, boolean remapLocals) {
|
||||
return create(SharedServiceManager.get(project), name, mappingsFile, from, to, remapLocals);
|
||||
}
|
||||
|
||||
public static synchronized Provider<MappingsService> create(Project project, String name, File mappingsFile, String from, String to, boolean remapLocals) {
|
||||
return project.getGradle().getSharedServices().registerIfAbsent(name, MappingsService.class, spec -> {
|
||||
spec.parameters(params -> {
|
||||
params.getMappingsFile().set(mappingsFile);
|
||||
params.getFromNamespace().set(from);
|
||||
params.getToNamespace().set(to);
|
||||
params.getRemapLocals().set(remapLocals);
|
||||
});
|
||||
});
|
||||
public static synchronized MappingsService create(SharedServiceManager sharedServiceManager, String name, Path mappingsFile, String from, String to, boolean remapLocals) {
|
||||
final Options options = new Options(mappingsFile, from, to, remapLocals);
|
||||
final String id = name + options.hashCode();
|
||||
return sharedServiceManager.getOrCreateService(id, () -> new MappingsService(options));
|
||||
}
|
||||
|
||||
public static Provider<MappingsService> createDefault(Project project, String from, String to) {
|
||||
public static MappingsService createDefault(Project project, String from, String to) {
|
||||
final MappingsProviderImpl mappingsProvider = LoomGradleExtension.get(project).getMappingsProvider();
|
||||
|
||||
final String name = mappingsProvider.getBuildServiceName("mappingsProvider", from, to);
|
||||
return MappingsService.create(project, name, mappingsProvider.tinyMappings.toFile(), from, to, false);
|
||||
return MappingsService.create(project, name, mappingsProvider.tinyMappings, from, to, false);
|
||||
}
|
||||
|
||||
private final Options options;
|
||||
|
||||
public MappingsService(Options options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
private IMappingProvider mappingProvider = null;
|
||||
|
@ -76,13 +72,13 @@ public abstract class MappingsService implements BuildService<MappingsService.Pa
|
|||
if (mappingProvider == null) {
|
||||
try {
|
||||
mappingProvider = TinyRemapperHelper.create(
|
||||
getParameters().getMappingsFile().get().getAsFile().toPath(),
|
||||
getParameters().getFromNamespace().get(),
|
||||
getParameters().getToNamespace().get(),
|
||||
getParameters().getRemapLocals().get()
|
||||
options.mappingsFile(),
|
||||
options.from(),
|
||||
options.to(),
|
||||
options.remapLocals()
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mappings from: " + getParameters().getMappingsFile().get().getAsFile().getAbsolutePath(), e);
|
||||
throw new UncheckedIOException("Failed to read mappings from: " + options.mappingsFile(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,9 +90,9 @@ public abstract class MappingsService implements BuildService<MappingsService.Pa
|
|||
memoryMappingTree = new MemoryMappingTree();
|
||||
|
||||
try {
|
||||
MappingReader.read(getParameters().getMappingsFile().get().getAsFile().toPath(), memoryMappingTree);
|
||||
MappingReader.read(options.mappingsFile(), memoryMappingTree);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mappings from: " + getParameters().getMappingsFile().get().getAsFile().getAbsolutePath(), e);
|
||||
throw new UncheckedIOException("Failed to read mappings from: " + options.mappingsFile(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,11 +100,11 @@ public abstract class MappingsService implements BuildService<MappingsService.Pa
|
|||
}
|
||||
|
||||
public String getFromNamespace() {
|
||||
return getParameters().getFromNamespace().get();
|
||||
return options.from();
|
||||
}
|
||||
|
||||
public String getToNamespace() {
|
||||
return getParameters().getToNamespace().get();
|
||||
return options.to();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.task.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.tinyremapper.IMappingProvider;
|
||||
|
||||
public final class MixinMappingsService implements SharedService {
|
||||
private final SharedServiceManager sharedServiceManager;
|
||||
private final HashSet<File> mixinMappings = new HashSet<>();
|
||||
|
||||
private MixinMappingsService(SharedServiceManager sharedServiceManager) {
|
||||
this.sharedServiceManager = sharedServiceManager;
|
||||
}
|
||||
|
||||
public static File getMixinMappingFile(Project project, SourceSet sourceSet) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
File mixinMapping = new File(extension.getFiles().getProjectBuildCache(), "mixin-map-" + extension.getMappingsProvider().mappingsIdentifier() + "." + sourceSet.getName() + ".tiny");
|
||||
|
||||
getService(SharedServiceManager.get(project)).mixinMappings.add(mixinMapping);
|
||||
|
||||
return mixinMapping;
|
||||
}
|
||||
|
||||
static MixinMappingsService getService(SharedServiceManager sharedServiceManager) {
|
||||
return sharedServiceManager.getOrCreateService("MixinMappings", () -> new MixinMappingsService(sharedServiceManager));
|
||||
}
|
||||
|
||||
IMappingProvider getMappingProvider(String from, String to) {
|
||||
return out -> {
|
||||
for (File mixinMapping : mixinMappings) {
|
||||
if (!mixinMapping.exists()) continue;
|
||||
|
||||
MappingsService service = MappingsService.create(sharedServiceManager, mixinMapping.getAbsolutePath(), mixinMapping.toPath(), from, to, false);
|
||||
service.getMappingsProvider().load(out);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -24,49 +24,57 @@
|
|||
|
||||
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.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.mercury.Mercury;
|
||||
import org.cadixdev.mercury.remapper.MercuryRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.services.BuildService;
|
||||
import org.gradle.api.services.BuildServiceParameters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.task.RemapSourcesJarTask;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
|
||||
public abstract class SourceRemapperService implements BuildService<SourceRemapperService.Params>, AutoCloseable {
|
||||
public interface Params extends BuildServiceParameters {
|
||||
Property<Provider<MappingsService>> getMappings();
|
||||
public final class SourceRemapperService implements SharedService {
|
||||
public static synchronized SourceRemapperService create(RemapSourcesJarTask task) {
|
||||
final Project project = task.getProject();
|
||||
final String to = task.getTargetNamespace().get();
|
||||
final String from = task.getSourceNamespace().get();
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final SharedServiceManager sharedServiceManager = SharedServiceManager.get(project);
|
||||
final String id = extension.getMappingsProvider().getBuildServiceName("sourceremapper", from, to);
|
||||
|
||||
ConfigurableFileCollection getClasspath();
|
||||
}
|
||||
|
||||
public static synchronized Provider<SourceRemapperService> create(Project project, Provider<MappingsService> mappings, FileCollection classpath) {
|
||||
// TODO may need a better name, im not too sure
|
||||
return project.getGradle().getSharedServices().registerIfAbsent("sourceremapper", SourceRemapperService.class, spec ->
|
||||
spec.parameters(params -> {
|
||||
params.getMappings().set(mappings);
|
||||
params.getClasspath().from(classpath);
|
||||
}
|
||||
));
|
||||
return sharedServiceManager.getOrCreateService(id, () ->
|
||||
new SourceRemapperService(MappingsService.createDefault(project, from, to), task.getClasspath()
|
||||
));
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SourceRemapperService.class);
|
||||
|
||||
private Mercury mercury;
|
||||
private final MappingsService mappingsService;
|
||||
private final ConfigurableFileCollection classpath;
|
||||
|
||||
private final Supplier<Mercury> mercury = Suppliers.memoize(this::createMercury);
|
||||
|
||||
private SourceRemapperService(MappingsService mappingsService, ConfigurableFileCollection classpath) {
|
||||
this.mappingsService = mappingsService;
|
||||
this.classpath = classpath;
|
||||
}
|
||||
|
||||
public void remapSourcesJar(Path source, Path destination) throws IOException {
|
||||
if (source.equals(destination)) {
|
||||
|
@ -99,35 +107,34 @@ public abstract class SourceRemapperService implements BuildService<SourceRemapp
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void doRemap(Path srcPath, Path dstPath, Path source) throws IOException {
|
||||
if (mercury == null) {
|
||||
mercury = new Mercury();
|
||||
mercury.setGracefulClasspathChecks(true);
|
||||
mercury.getProcessors().add(MercuryRemapper.create(getMappings()));
|
||||
|
||||
getParameters().getClasspath().forEach(file -> mercury.getClassPath().add(file.toPath()));
|
||||
}
|
||||
|
||||
private synchronized void doRemap(Path srcPath, Path dstPath, Path source) {
|
||||
try {
|
||||
// Not thread safe!!
|
||||
mercury.rewrite(srcPath, dstPath);
|
||||
synchronized (mercury) {
|
||||
mercury.get().rewrite(srcPath, dstPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not remap " + source + " fully!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private MappingSet getMappings() throws IOException {
|
||||
return new TinyMappingsReader(mappingsService().getMemoryMappingTree(), mappingsService().getFromNamespace(), mappingsService().getToNamespace()).read();
|
||||
return new TinyMappingsReader(mappingsService.getMemoryMappingTree(), mappingsService.getFromNamespace(), mappingsService.getToNamespace()).read();
|
||||
}
|
||||
|
||||
private MappingsService mappingsService() {
|
||||
return getParameters().getMappings().get().get();
|
||||
}
|
||||
private Mercury createMercury() {
|
||||
var mercury = new Mercury();
|
||||
mercury.setGracefulClasspathChecks(true);
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
mercury = null;
|
||||
// This is required (:
|
||||
System.gc();
|
||||
try {
|
||||
mercury.getProcessors().add(MercuryRemapper.create(getMappings()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mercury mappings", e);
|
||||
}
|
||||
|
||||
for (File file : classpath.getFiles()) {
|
||||
mercury.getClassPath().add(file.toPath());
|
||||
}
|
||||
|
||||
return mercury;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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.task.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.task.AbstractRemapJarTask;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.tinyremapper.IMappingProvider;
|
||||
import net.fabricmc.tinyremapper.InputTag;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public class TinyRemapperService implements SharedService {
|
||||
public static synchronized TinyRemapperService getOrCreate(AbstractRemapJarTask remapJarTask) {
|
||||
final Project project = remapJarTask.getProject();
|
||||
final String to = remapJarTask.getTargetNamespace().get();
|
||||
final String from = remapJarTask.getSourceNamespace().get();
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final SharedServiceManager sharedServiceManager = SharedServiceManager.get(project);
|
||||
final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get();
|
||||
|
||||
// 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.
|
||||
final String id = extension.getMappingsProvider().getBuildServiceName("remapJarService", from, to) + ":" + remapJarTask.getName();
|
||||
|
||||
TinyRemapperService service = sharedServiceManager.getOrCreateService(id, () -> {
|
||||
List<IMappingProvider> mappings = new ArrayList<>();
|
||||
mappings.add(MappingsService.createDefault(project, from, to).getMappingsProvider());
|
||||
|
||||
if (legacyMixin) {
|
||||
mappings.add(MixinMappingsService.getService(SharedServiceManager.get(project)).getMappingProvider(from, to));
|
||||
}
|
||||
|
||||
return new TinyRemapperService(mappings, !legacyMixin);
|
||||
});
|
||||
|
||||
service.readClasspath(remapJarTask.getClasspath().getFiles().stream().map(File::toPath).toList());
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
private TinyRemapper tinyRemapper;
|
||||
private final Map<String, InputTag> inputTagMap = new ConcurrentHashMap<>();
|
||||
private final HashSet<Path> classpath = new HashSet<>();
|
||||
// Set to true once remapping has started, once set no inputs can be read.
|
||||
private boolean isRemapping = false;
|
||||
|
||||
public TinyRemapperService(List<IMappingProvider> mappings, boolean useMixinExtension) {
|
||||
TinyRemapper.Builder builder = TinyRemapper.newRemapper();
|
||||
|
||||
for (IMappingProvider provider : mappings) {
|
||||
builder.withMappings(provider);
|
||||
}
|
||||
|
||||
if (useMixinExtension) {
|
||||
builder.extension(new net.fabricmc.tinyremapper.extension.mixin.MixinExtension());
|
||||
}
|
||||
|
||||
tinyRemapper = builder.build();
|
||||
}
|
||||
|
||||
public InputTag createTag(String key) {
|
||||
if (inputTagMap.containsKey(key)) {
|
||||
throw new IllegalStateException("Input tag already exists for key: " + key);
|
||||
}
|
||||
|
||||
return inputTagMap.put(key, tinyRemapper.createInputTag());
|
||||
}
|
||||
|
||||
public InputTag getTag(String key) {
|
||||
return Objects.requireNonNull(inputTagMap.get(key), "Input tag not found for: " + key);
|
||||
}
|
||||
|
||||
public TinyRemapper getTinyRemapperForRemapping() {
|
||||
synchronized (this) {
|
||||
isRemapping = true;
|
||||
return Objects.requireNonNull(tinyRemapper, "Tiny remapper has not been setup");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized TinyRemapper getTinyRemapperForInputs() {
|
||||
synchronized (this) {
|
||||
if (isRemapping) {
|
||||
throw new IllegalStateException("Cannot read inputs as remapping has already started");
|
||||
}
|
||||
|
||||
return tinyRemapper;
|
||||
}
|
||||
}
|
||||
|
||||
void readClasspath(List<Path> paths) {
|
||||
List<Path> toRead;
|
||||
|
||||
synchronized (classpath) {
|
||||
toRead = paths.stream().filter(path -> !classpath.contains(path)).toList();
|
||||
classpath.addAll(paths);
|
||||
}
|
||||
|
||||
tinyRemapper.readClassPathAsync(toRead.toArray(Path[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (tinyRemapper != null) {
|
||||
tinyRemapper.finish();
|
||||
tinyRemapper = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ import java.util.zip.GZIPInputStream;
|
|||
import com.google.common.io.Files;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
|
||||
|
|
|
@ -110,21 +110,31 @@ public final class TinyRemapperHelper {
|
|||
|
||||
public static IMappingProvider create(MappingTree mappings, String from, String to, boolean remapLocalVariables) {
|
||||
return (acceptor) -> {
|
||||
final int fromId = mappings.getNamespaceId(from);
|
||||
final int toId = mappings.getNamespaceId(to);
|
||||
|
||||
for (MappingTree.ClassMapping classDef : mappings.getClasses()) {
|
||||
String className = classDef.getName(from);
|
||||
acceptor.acceptClass(className, classDef.getName(to));
|
||||
String className = classDef.getName(fromId);
|
||||
String dstName = classDef.getName(toId);
|
||||
|
||||
if (dstName == null) {
|
||||
// Unsure if this is correct, should be better than crashing tho.
|
||||
dstName = className;
|
||||
}
|
||||
|
||||
acceptor.acceptClass(className, dstName);
|
||||
|
||||
for (MappingTree.FieldMapping field : classDef.getFields()) {
|
||||
acceptor.acceptField(memberOf(className, field.getName(from), field.getDesc(from)), field.getName(to));
|
||||
acceptor.acceptField(memberOf(className, field.getName(fromId), field.getDesc(fromId)), field.getName(toId));
|
||||
}
|
||||
|
||||
for (MappingTree.MethodMapping method : classDef.getMethods()) {
|
||||
IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDesc(from));
|
||||
acceptor.acceptMethod(methodIdentifier, method.getName(to));
|
||||
IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(fromId), method.getDesc(fromId));
|
||||
acceptor.acceptMethod(methodIdentifier, method.getName(toId));
|
||||
|
||||
if (remapLocalVariables) {
|
||||
for (MappingTree.MethodArgMapping parameter : method.getArgs()) {
|
||||
String name = parameter.getName(to);
|
||||
String name = parameter.getName(toId);
|
||||
|
||||
if (name == null) {
|
||||
continue;
|
||||
|
@ -136,7 +146,7 @@ public final class TinyRemapperHelper {
|
|||
for (MappingTree.MethodVarMapping localVariable : method.getVars()) {
|
||||
acceptor.acceptMethodVar(methodIdentifier, localVariable.getLvIndex(),
|
||||
localVariable.getStartOpIdx(), localVariable.getLvtRowIndex(),
|
||||
localVariable.getName(to));
|
||||
localVariable.getName(toId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.gradle.BuildResult;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.invocation.Gradle;
|
||||
|
||||
/**
|
||||
* 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 final class SharedServiceManager {
|
||||
private static final Map<Gradle, SharedServiceManager> SERVICE_FACTORY_MAP = new ConcurrentHashMap<>();
|
||||
private final Gradle gradle;
|
||||
|
||||
private final Map<String, SharedService> sharedServiceMap = new ConcurrentHashMap<>();
|
||||
|
||||
private boolean shutdown = false;
|
||||
|
||||
private SharedServiceManager(Gradle gradle) {
|
||||
this.gradle = gradle;
|
||||
this.gradle.buildFinished(this::onFinish);
|
||||
}
|
||||
|
||||
public static SharedServiceManager get(Project project) {
|
||||
return get(project.getGradle());
|
||||
}
|
||||
|
||||
public static SharedServiceManager get(Gradle gradle) {
|
||||
return SERVICE_FACTORY_MAP.computeIfAbsent(gradle, SharedServiceManager::new);
|
||||
}
|
||||
|
||||
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) {
|
||||
sharedService = function.get();
|
||||
sharedServiceMap.put(id, sharedService);
|
||||
}
|
||||
|
||||
return sharedService;
|
||||
}
|
||||
}
|
||||
|
||||
private void onFinish(BuildResult buildResult) {
|
||||
synchronized (sharedServiceMap) {
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
SERVICE_FACTORY_MAP.remove(gradle);
|
||||
|
||||
final List<IOException> exceptionList = new ArrayList<>();
|
||||
|
||||
for (SharedService sharedService : sharedServiceMap.values()) {
|
||||
try {
|
||||
sharedService.close();
|
||||
} catch (IOException e) {
|
||||
exceptionList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
sharedServiceMap.clear();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// This is required to ensure that mercury releases all of the file handles.
|
||||
System.gc();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.Project;
|
||||
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(Project project, SharedService service) {
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
SERVICE_MAP.put(uuid, service);
|
||||
|
||||
// Ensure we don't make a mess if things go wrong.
|
||||
project.getGradle().buildFinished(buildResult -> SERVICE_MAP.remove(uuid));
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ import org.gradle.util.GradleVersion
|
|||
|
||||
class LoomTestConstants {
|
||||
public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion()
|
||||
public final static String PRE_RELEASE_GRADLE = "7.5-20220101231120+0000"
|
||||
public final static String PRE_RELEASE_GRADLE = "7.5-20220110230252+0000"
|
||||
|
||||
public final static String[] STANDARD_TEST_VERSIONS = [DEFAULT_GRADLE, PRE_RELEASE_GRADLE]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.test.benchmark
|
||||
|
||||
import groovy.time.TimeCategory
|
||||
import groovy.time.TimeDuration
|
||||
import net.fabricmc.loom.test.LoomTestConstants
|
||||
import net.fabricmc.loom.test.util.GradleProjectTestTrait
|
||||
|
||||
/**
|
||||
* Run this class, passing a working dir as the first argument.
|
||||
* Allow for one warm up run before profiling, follow up runs should not be using the network.
|
||||
*/
|
||||
@Singleton
|
||||
class FabricAPIBenchmark implements GradleProjectTestTrait {
|
||||
def run(File dir) {
|
||||
def gradle = gradleProject(
|
||||
version: LoomTestConstants.PRE_RELEASE_GRADLE,
|
||||
projectDir: new File(dir, "project"),
|
||||
gradleHomeDir: new File(dir, "gradlehome"),
|
||||
allowExistingRepo: true,
|
||||
|
||||
repo: "https://github.com/FabricMC/fabric.git",
|
||||
commit: "71b634e5b7845296b11be3fa6545f4fbfacc017f",
|
||||
patch: "fabric_api"
|
||||
)
|
||||
|
||||
def timeStart = new Date()
|
||||
|
||||
def result = gradle.run(tasks: ["clean", "build"], args: ["--parallel", "-x", "check", "-x", "test", "-x", ":fabric-data-generation-api-v1:runDatagen", "-x", "javadoc"])
|
||||
|
||||
def timeStop = new Date()
|
||||
TimeDuration duration = TimeCategory.minus(timeStop, timeStart)
|
||||
println(duration)
|
||||
}
|
||||
|
||||
static void main(String[] args) {
|
||||
getInstance().run(new File(args[0]))
|
||||
System.exit(0)
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ import net.fabricmc.loom.configuration.providers.mappings.intermediary.Intermedi
|
|||
class IntermediaryMappingLayerTest extends LayeredMappingsSpecification {
|
||||
def "Read intermediary mappings" () {
|
||||
setup:
|
||||
mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_17_URL, "intermediary.jar"), "mappings/mappings.tiny")
|
||||
intermediaryUrl = INTERMEDIARY_1_17_URL
|
||||
when:
|
||||
def mappings = getSingleMapping(new IntermediaryMappingsSpec())
|
||||
def tiny = getTiny(mappings)
|
||||
|
|
|
@ -24,15 +24,14 @@
|
|||
|
||||
package net.fabricmc.loom.test.unit.layeredmappings
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsProcessor
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.IntermediaryService
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsProcessor
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider
|
||||
import net.fabricmc.mappingio.adapter.MappingDstNsReorder
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer
|
||||
|
@ -42,13 +41,13 @@ import org.gradle.api.logging.Logger
|
|||
import spock.lang.Specification
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.util.function.Supplier
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
abstract class LayeredMappingsSpecification extends Specification implements LayeredMappingsTestConstants {
|
||||
Logger mockLogger = Mock(Logger)
|
||||
MappingsProvider mockMappingsProvider = Mock(MappingsProvider)
|
||||
MinecraftProvider mockMinecraftProvider = Mock(MinecraftProvider)
|
||||
|
||||
String intermediaryUrl
|
||||
MappingContext mappingContext = new TestMappingContext()
|
||||
|
||||
File tempDir = File.createTempDir()
|
||||
|
@ -102,7 +101,12 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
|
|||
return reorderedMappings
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
def setup() {
|
||||
mockMinecraftProvider.file(_) >> { args ->
|
||||
return new File(tempDir, args[0])
|
||||
}
|
||||
}
|
||||
|
||||
class TestMappingContext implements MappingContext {
|
||||
@Override
|
||||
Path resolveDependency(Dependency dependency) {
|
||||
|
@ -116,8 +120,10 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
|
|||
}
|
||||
|
||||
@Override
|
||||
MappingsProvider mappingsProvider() {
|
||||
return mockMappingsProvider
|
||||
Supplier<MemoryMappingTree> intermediaryTree() {
|
||||
return {
|
||||
IntermediaryService.create(intermediaryUrl, minecraftProvider()).memoryMappingTree
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,7 +30,7 @@ import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsS
|
|||
class MojangMappingLayerTest extends LayeredMappingsSpecification {
|
||||
def "Read mojang mappings with synthetic field names" () {
|
||||
setup:
|
||||
mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_17_URL, "intermediary.jar"), "mappings/mappings.tiny")
|
||||
intermediaryUrl = INTERMEDIARY_1_17_URL
|
||||
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
|
||||
when:
|
||||
def mappings = getLayeredMappings(
|
||||
|
@ -50,7 +50,7 @@ class MojangMappingLayerTest extends LayeredMappingsSpecification {
|
|||
|
||||
def "Read mojang mappings without synthetic field names" () {
|
||||
setup:
|
||||
mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_17_URL, "intermediary.jar"), "mappings/mappings.tiny")
|
||||
intermediaryUrl = INTERMEDIARY_1_17_URL
|
||||
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
|
||||
when:
|
||||
def mappings = getLayeredMappings(
|
||||
|
|
|
@ -32,7 +32,7 @@ import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMap
|
|||
class ParchmentMappingLayerTest extends LayeredMappingsSpecification {
|
||||
def "Read parchment mappings" () {
|
||||
setup:
|
||||
mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_16_5_URL, "intermediary.jar"), "mappings/mappings.tiny")
|
||||
intermediaryUrl = INTERMEDIARY_1_16_5_URL
|
||||
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5
|
||||
when:
|
||||
withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip"))
|
||||
|
@ -55,7 +55,7 @@ class ParchmentMappingLayerTest extends LayeredMappingsSpecification {
|
|||
|
||||
def "Read parchment mappings remove prefix" () {
|
||||
setup:
|
||||
mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_16_5_URL, "intermediary.jar"), "mappings/mappings.tiny")
|
||||
intermediaryUrl = INTERMEDIARY_1_16_5_URL
|
||||
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5
|
||||
when:
|
||||
withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip"))
|
||||
|
|
|
@ -65,6 +65,10 @@ trait GradleProjectTestTrait {
|
|||
String repo = options.repo
|
||||
String commit = options.commit
|
||||
|
||||
if (options.allowExistingRepo && projectDir.listFiles()?.length > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
exec(projectDir, "git", "clone", repo, ".")
|
||||
exec(projectDir, "git", "checkout", commit)
|
||||
|
||||
|
@ -85,6 +89,7 @@ trait GradleProjectTestTrait {
|
|||
}
|
||||
|
||||
private void exec(File projectDir, String... args) {
|
||||
projectDir.mkdirs()
|
||||
def process = args.execute([], projectDir)
|
||||
process.consumeProcessOutput(System.out, System.err)
|
||||
|
||||
|
|
|
@ -90,9 +90,8 @@ shadowJar {
|
|||
}
|
||||
|
||||
remapJar {
|
||||
dependsOn(shadowJar)
|
||||
archiveClassifier.set("universal")
|
||||
input.fileValue(tasks["shadowJar"].outputs.files.singleFile)
|
||||
inputFile = shadowJar.archiveFile
|
||||
}
|
||||
|
||||
jar {
|
||||
|
|
Loading…
Reference in a new issue