Merge with Fabric 0.13, stage 1

This commit is contained in:
Juuz
2022-08-09 17:18:43 +03:00
20 changed files with 222 additions and 235 deletions

View File

@@ -1,5 +1,5 @@
plugins {
id 'dev.architectury.loom' version '0.12.local'
id 'dev.architectury.loom' version '0.13.local'
}
dependencies {

View File

@@ -30,7 +30,7 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
group = "dev.architectury"
archivesBaseName = project.name
def baseVersion = '0.12.0'
def baseVersion = '0.13.0'
def runNumber = System.getenv("GITHUB_RUN_NUMBER") ?: "9999"
def isSnapshot = System.getenv("PR_NUM") != null
@@ -55,7 +55,6 @@ repositories {
excludeGroupByRegex "org\\.eclipse\\.?.*"
}
}
mavenLocal()
}
configurations {
@@ -82,7 +81,7 @@ dependencies {
// libraries
implementation ('commons-io:commons-io:2.11.0')
implementation ('com.google.code.gson:gson:2.9.0')
implementation ('com.fasterxml.jackson.core:jackson-databind:2.13.2.2')
implementation ('com.fasterxml.jackson.core:jackson-databind:2.13.3')
implementation ('com.google.guava:guava:31.1-jre')
implementation ('org.ow2.asm:asm:9.3')
implementation ('org.ow2.asm:asm-analysis:9.3')
@@ -99,6 +98,7 @@ dependencies {
// tinyfile management
implementation ('dev.architectury:tiny-remapper:1.7.19')
// TODO: implementation ('net.fabricmc:tiny-remapper:0.8.5')
implementation 'net.fabricmc:access-widener:2.1.0'
implementation 'net.fabricmc:mapping-io:0.2.1'
@@ -135,11 +135,11 @@ dependencies {
exclude module: 'groovy-all'
}
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
testImplementation ('io.javalin:javalin:4.4.0') {
testImplementation ('io.javalin:javalin:4.6.1') {
exclude group: 'org.jetbrains.kotlin'
}
testImplementation 'net.fabricmc:fabric-installer:0.9.0'
testImplementation 'org.mockito:mockito-core:4.4.0'
testImplementation 'org.mockito:mockito-core:4.6.1'
compileOnly 'org.jetbrains:annotations:23.0.0'
testCompileOnly 'org.jetbrains:annotations:23.0.0'
@@ -212,6 +212,11 @@ test {
maxHeapSize = "1536m"
useJUnitPlatform()
maxParallelForks = Runtime.runtime.availableProcessors() ?: 1
// Forward system prop onto tests.
if (System.getProperty("fabric.loom.test.homeDir")) {
systemProperty "fabric.loom.test.homeDir", System.getProperty("fabric.loom.test.homeDir")
}
}
import org.gradle.util.GradleVersion

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2018-2021 FabricMC
* Copyright (c) 2018-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
@@ -24,46 +24,21 @@
package net.fabricmc.loom.build;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradlePlugin;
public final class MixinRefmapHelper {
private MixinRefmapHelper() { }
private static final String FABRIC_MOD_JSON = "fabric.mod.json";
@Nullable
public static JsonObject readFabricModJson(File output) {
try (ZipFile zip = new ZipFile(output)) {
ZipEntry entry = zip.getEntry(FABRIC_MOD_JSON);
if (entry == null) {
return null;
}
try (InputStreamReader reader = new InputStreamReader(zip.getInputStream(entry))) {
return LoomGradlePlugin.GSON.fromJson(reader, JsonObject.class);
}
} catch (IOException e) {
throw new RuntimeException("Cannot read file fabric.mod.json in the jar.", e);
}
}
@NotNull
public static Collection<String> getMixinConfigurationFiles(JsonObject fabricModJson) {
JsonArray mixins = fabricModJson.getAsJsonArray("mixins");

View File

@@ -24,7 +24,6 @@
package net.fabricmc.loom.configuration.ide;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@@ -44,6 +43,9 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.tools.ant.util.StringUtils;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.ResolvedModuleVersion;
import org.gradle.api.tasks.SourceSet;
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import org.w3c.dom.Document;
@@ -296,14 +298,6 @@ public class RunConfig {
}
public List<String> getExcludedLibraryPaths(Project project) {
if (true) {
/*
This whole excluded libraries idea breaks down when the server library version does not match the client.
This is a quick change to disable it meanwhile a proper solution is sorted.
*/
return Collections.emptyList();
}
if (!environment.equals("server")) {
return Collections.emptyList();
}
@@ -315,19 +309,32 @@ public class RunConfig {
return Collections.emptyList();
}
final Set<File> allLibraries = project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles();
final Set<File> serverLibraries = project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES).getFiles();
final Set<ResolvedArtifact> allLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_DEPENDENCIES);
final Set<ResolvedArtifact> serverLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES);
final List<String> clientOnlyLibraries = new LinkedList<>();
for (File commonLibrary : allLibraries) {
if (!serverLibraries.contains(commonLibrary)) {
clientOnlyLibraries.add(commonLibrary.getAbsolutePath());
for (ResolvedArtifact library : allLibraries) {
if (!containsLibrary(serverLibraries, library.getModuleVersion().getId())) {
clientOnlyLibraries.add(library.getFile().getAbsolutePath());
}
}
return clientOnlyLibraries;
}
private static Set<ResolvedArtifact> getArtifacts(Project project, String configuration) {
return project.getConfigurations().getByName(configuration)
.getResolvedConfiguration()
.getResolvedArtifacts();
}
private static boolean containsLibrary(Set<ResolvedArtifact> artifacts, ModuleVersionIdentifier identifier) {
return artifacts.stream()
.map(ResolvedArtifact::getModuleVersion)
.map(ResolvedModuleVersion::getId)
.anyMatch(test -> test.getGroup().equals(identifier.getGroup()) && test.getName().equals(identifier.getName()));
}
private static String encodeEscaped(String s) {
StringBuilder ret = new StringBuilder();

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2021 FabricMC
* Copyright (c) 2016-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
@@ -67,6 +67,7 @@ import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvid
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.FileSystemUtil;
import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.service.SharedService;
import net.fabricmc.loom.util.service.SharedServiceManager;
@@ -299,9 +300,9 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService {
return;
}
try (FileSystem fileSystem = FileSystems.newFileSystem(inputJar, (ClassLoader) null)) {
extractMappings(fileSystem, baseTinyMappings);
extractExtras(fileSystem);
try (FileSystemUtil.Delegate delegate = FileSystemUtil.getJarFileSystem(inputJar)) {
extractMappings(delegate.fs(), baseTinyMappings);
extractExtras(delegate.fs());
}
if (areMappingsMergedV2(baseTinyMappings)) {
@@ -383,8 +384,8 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService {
}
public static void extractMappings(Path jar, Path extractTo) throws IOException {
try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(jar, (ClassLoader) null)) {
extractMappings(unmergedIntermediaryFs, extractTo);
try (FileSystemUtil.Delegate delegate = FileSystemUtil.getJarFileSystem(jar)) {
extractMappings(delegate.fs(), extractTo);
}
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2021 FabricMC
* 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
@@ -25,17 +25,13 @@
package net.fabricmc.loom.configuration.providers.mappings.extras.signatures;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.mappingio.MappingVisitor;
@ApiStatus.Experimental
@@ -49,14 +45,9 @@ public record SignatureFixesLayerImpl(Path mappingsFile) implements MappingLayer
@Override
public Map<String, String> getSignatureFixes() {
try (var zipFile = new ZipFile(mappingsFile().toFile())) {
ZipEntry zipFileEntry = zipFile.getEntry(SIGNATURE_FIXES_PATH);
Objects.requireNonNull(zipFileEntry, "Could not find %s in file".formatted(SIGNATURE_FIXES_PATH));
try (var reader = new InputStreamReader(zipFile.getInputStream(zipFileEntry))) {
//noinspection unchecked
return LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, Map.class);
}
try {
//noinspection unchecked
return ZipUtils.unpackJackson(mappingsFile(), SIGNATURE_FIXES_PATH, Map.class);
} catch (IOException e) {
throw new RuntimeException("Failed to extract signature fixes", e);
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2021 FabricMC
* Copyright (c) 2016-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
@@ -25,15 +25,11 @@
package net.fabricmc.loom.configuration.providers.mappings.parchment;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.mappingio.MappingVisitor;
public record ParchmentMappingLayer(Path parchmentFile, boolean removePrefix) implements MappingLayer {
@@ -51,13 +47,6 @@ public record ParchmentMappingLayer(Path parchmentFile, boolean removePrefix) im
}
private ParchmentTreeV1 getParchmentData() throws IOException {
try (var zipFile = new ZipFile(parchmentFile().toFile())) {
ZipEntry zipFileEntry = zipFile.getEntry(PARCHMENT_DATA_FILE_NAME);
Objects.requireNonNull(zipFileEntry, "Could not find %s in parchment data file".formatted(PARCHMENT_DATA_FILE_NAME));
try (var reader = new InputStreamReader(zipFile.getInputStream(zipFileEntry))) {
return LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, ParchmentTreeV1.class);
}
}
return ZipUtils.unpackJackson(parchmentFile, PARCHMENT_DATA_FILE_NAME, ParchmentTreeV1.class);
}
}

View File

@@ -27,13 +27,12 @@ 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.NoSuchFileException;
import java.nio.file.Path;
import java.util.Optional;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.format.MappingFormat;
@@ -47,8 +46,8 @@ public record TinyJarInfo(boolean v2, Optional<String> minecraftVersionId) {
}
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"))) {
try (FileSystemUtil.Delegate delegate = FileSystemUtil.getJarFileSystem(path)) {
try (BufferedReader reader = Files.newBufferedReader(delegate.fs().getPath("mappings", "mappings.tiny"))) {
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
}
} catch (NoSuchFileException e) {

View File

@@ -75,8 +75,6 @@ public class MinecraftLibraryProvider {
if (runtimeOnlyLog4j && library.name().startsWith("org.apache.logging.log4j")) {
// Make log4j a runtime only dep to force slf4j.
project.getDependencies().add(Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, library.name());
} else if (serverBundleMetadata != null && isLibraryInBundle(serverBundleMetadata, library)) {
project.getDependencies().add(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name());
} else if (jarConfiguration.getSupportedEnvironments().contains("client")) {
// Client only library, or legacy version
project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, library.name());
@@ -117,6 +115,12 @@ public class MinecraftLibraryProvider {
}
}
if (serverBundleMetadata != null) {
for (BundleMetadata.Entry library : serverBundleMetadata.libraries()) {
project.getDependencies().add(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name());
}
}
if (overrideLWJGL) {
LWJGLVersionOverride.DEPENDENCIES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, s));
LWJGLVersionOverride.NATIVES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_NATIVES, s));
@@ -132,8 +136,4 @@ public class MinecraftLibraryProvider {
project.getDependencies().add("modLocalRuntime", dependency);
}
}
private static boolean isLibraryInBundle(BundleMetadata bundleMetadata, MinecraftVersionMeta.Library library) {
return bundleMetadata.libraries().stream().anyMatch(entry -> entry.name().equals(library.name()));
}
}

View File

@@ -209,12 +209,14 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
);
});
if (project.getTasks().findByName(mainSourceSet.getSourcesJarTaskName()) == null) {
// No sources.
return;
}
// The sources task can be registered at a later time.
project.getTasks().configureEach(task -> {
if (!mainSourceSet.getSourcesJarTaskName().equals(task.getName()) || !(task instanceof Jar jar)) {
// Not the sources task we are looking for.
return;
}
project.getTasks().named(mainSourceSet.getSourcesJarTaskName(), Jar.class).configure(jar -> {
// The client only sources to the combined sources jar.
jar.from(clientOnlySourceSet.getAllSource());
});
}
@@ -224,7 +226,7 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
}
public static SourceSet getClientSourceSet(Project project) {
Preconditions.checkArgument(LoomGradleExtension.get(project).areEnvironmentSourceSetsSplit());
Preconditions.checkArgument(LoomGradleExtension.get(project).areEnvironmentSourceSetsSplit(), "Cannot get client only sourceset as project is not split");
final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class);
return javaExtension.getSourceSets().getByName(CLIENT_ONLY_SOURCE_SET_NAME);

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2020 FabricMC
* Copyright (c) 2016-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
@@ -26,11 +26,11 @@ package net.fabricmc.loom.decompilers.fernflower;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import net.fabricmc.loom.util.ZipUtils;
public class FernFlowerUtils {
public static byte[] getBytecode(String externalPath, String internalPath) throws IOException {
File file = new File(externalPath);
@@ -38,15 +38,7 @@ public class FernFlowerUtils {
if (internalPath == null) {
return InterpreterUtil.getBytes(file);
} else {
try (ZipFile archive = new ZipFile(file)) {
ZipEntry entry = archive.getEntry(internalPath);
if (entry == null) {
throw new IOException("Entry not found: " + internalPath);
}
return InterpreterUtil.getBytes(archive, entry);
}
return ZipUtils.unpack(file.toPath(), internalPath);
}
}
}

View File

@@ -24,18 +24,30 @@
package net.fabricmc.loom.task;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.jar.Manifest;
import javax.inject.Inject;
import com.google.common.base.Preconditions;
import org.gradle.api.Action;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.jvm.tasks.Jar;
import org.gradle.workers.WorkAction;
import org.gradle.workers.WorkParameters;
@@ -44,9 +56,14 @@ import org.gradle.workers.WorkerExecutor;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.build.IntermediaryNamespaces;
import net.fabricmc.loom.task.service.JarManifestService;
import net.fabricmc.loom.util.ZipReprocessorUtil;
import net.fabricmc.loom.util.ZipUtils;
public abstract class AbstractRemapJarTask extends Jar {
public static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
public static final String MANIFEST_NAMESPACE_KEY = "Fabric-Mapping-Namespace";
@InputFile
public abstract RegularFileProperty getInputFile();
@@ -68,11 +85,15 @@ public abstract class AbstractRemapJarTask extends Jar {
@Inject
protected abstract WorkerExecutor getWorkerExecutor();
@Input
public abstract Property<Boolean> getIncludesClientOnlyClasses();
@Inject
public AbstractRemapJarTask() {
getSourceNamespace().convention(MappingsNamespace.NAMED.toString()).finalizeValueOnRead();
getTargetNamespace().convention(IntermediaryNamespaces.intermediary(getProject())).finalizeValueOnRead();
getRemapperIsolation().convention(true).finalizeValueOnRead();
getIncludesClientOnlyClasses().convention(false).finalizeValueOnRead();
}
public final <P extends AbstractRemapParams> void submitWork(Class<? extends AbstractRemapAction<P>> workAction, Action<P> action) {
@@ -88,10 +109,21 @@ public abstract class AbstractRemapJarTask extends Jar {
params.getArchivePreserveFileTimestamps().set(isPreserveFileTimestamps());
params.getArchiveReproducibleFileOrder().set(isReproducibleFileOrder());
params.getJarManifestService().set(JarManifestService.get(getProject()));
if (getIncludesClientOnlyClasses().get()) {
final List<String> clientOnlyEntries = getClientOnlyEntries();
applyClientOnlyManifestAttributes(params, clientOnlyEntries);
params.getClientOnlyEntries().set(clientOnlyEntries.stream().filter(s -> s.endsWith(".class")).toList());
}
action.execute(params);
});
}
@Internal
protected abstract List<String> getClientOnlyEntries();
public interface AbstractRemapParams extends WorkParameters {
RegularFileProperty getInputFile();
RegularFileProperty getOutputFile();
@@ -101,6 +133,18 @@ public abstract class AbstractRemapJarTask extends Jar {
Property<Boolean> getArchivePreserveFileTimestamps();
Property<Boolean> getArchiveReproducibleFileOrder();
Property<JarManifestService> getJarManifestService();
MapProperty<String, String> getManifestAttributes();
ListProperty<String> getClientOnlyEntries();
}
protected void applyClientOnlyManifestAttributes(AbstractRemapParams params, List<String> entries) {
params.getManifestAttributes().set(Map.of(
"Fabric-Loom-Split-Environment", "true",
"Fabric-Loom-Client-Only-Entries", String.join(";", entries)
));
}
public abstract static class AbstractRemapAction<T extends AbstractRemapParams> implements WorkAction<T> {
@@ -113,6 +157,21 @@ public abstract class AbstractRemapJarTask extends Jar {
outputFile = getParameters().getOutputFile().getAsFile().get().toPath();
}
protected void modifyJarManifest() throws IOException {
int count = ZipUtils.transform(outputFile, Map.of(MANIFEST_PATH, bytes -> {
var manifest = new Manifest(new ByteArrayInputStream(bytes));
getParameters().getJarManifestService().get().apply(manifest, getParameters().getManifestAttributes().get());
manifest.getMainAttributes().putValue(MANIFEST_NAMESPACE_KEY, getParameters().getTargetNamespace().get());
ByteArrayOutputStream out = new ByteArrayOutputStream();
manifest.write(out);
return out.toByteArray();
}));
Preconditions.checkState(count > 0, "Did not transform any jar manifest");
}
protected void rewriteJar() throws IOException {
final boolean isReproducibleFileOrder = getParameters().getArchiveReproducibleFileOrder().get();
final boolean isPreserveFileTimestamps = getParameters().getArchivePreserveFileTimestamps().get();
@@ -128,4 +187,31 @@ public abstract class AbstractRemapJarTask extends Jar {
public RegularFileProperty getInput() {
return getInputFile();
}
protected static List<String> getRootPaths(Set<File> files) {
return files.stream()
.map(root -> {
String rootPath = root.getAbsolutePath().replace("\\", "/");
if (rootPath.charAt(rootPath.length() - 1) != '/') {
rootPath += '/';
}
return rootPath;
}).toList();
}
protected static Function<File, String> relativePath(List<String> rootPaths) {
return file -> {
String s = file.getAbsolutePath().replace("\\", "/");
for (String rootPath : rootPaths) {
if (s.startsWith(rootPath)) {
s = s.substring(rootPath.length());
}
}
return s;
};
}
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2019-2021 FabricMC
* Copyright (c) 2019-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
@@ -26,8 +26,6 @@ package net.fabricmc.loom.task;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;
@@ -51,6 +49,7 @@ import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.lorenztiny.TinyMappingsJoiner;
import net.fabricmc.mappingio.MappingReader;
@@ -117,7 +116,7 @@ public class MigrateMappingsTask extends AbstractLoomTask {
Set<File> files;
try {
if (mappings.startsWith("net.minecraft:mappings:") || mappings.startsWith("net.mojang.minecraft:mappings:")) {
if (mappings.startsWith("net.minecraft:mappings:")) {
if (!mappings.endsWith(":" + LoomGradleExtension.get(project).getMinecraftProvider().minecraftVersion())) {
throw new UnsupportedOperationException("Migrating Mojang mappings is currently only supported for the specified minecraft version");
}
@@ -149,8 +148,8 @@ public class MigrateMappingsTask extends AbstractLoomTask {
private static MemoryMappingTree getMappings(File mappings) throws IOException {
MemoryMappingTree mappingTree = new MemoryMappingTree();
try (FileSystem fileSystem = FileSystems.newFileSystem(mappings.toPath(), (ClassLoader) null)) {
MappingReader.read(fileSystem.getPath("mappings/mappings.tiny"), mappingTree);
try (FileSystemUtil.Delegate delegate = FileSystemUtil.getJarFileSystem(mappings.toPath())) {
MappingReader.read(delegate.fs().getPath("mappings/mappings.tiny"), mappingTree);
}
return mappingTree;

View File

@@ -26,7 +26,6 @@ package net.fabricmc.loom.task;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -47,7 +46,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
@@ -58,7 +56,6 @@ import java.util.stream.StreamSupport;
import javax.inject.Inject;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -73,7 +70,6 @@ import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.SetProperty;
@@ -100,7 +96,6 @@ import net.fabricmc.loom.build.nesting.JarNester;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
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;
@@ -108,6 +103,7 @@ import net.fabricmc.loom.util.ExceptionUtil;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.LfWriter;
import net.fabricmc.loom.util.ModPlatform;
import net.fabricmc.loom.util.ModUtils;
import net.fabricmc.loom.util.Pair;
import net.fabricmc.loom.util.SidedClassVisitor;
import net.fabricmc.loom.util.ZipUtils;
@@ -116,9 +112,6 @@ import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
import net.fabricmc.lorenztiny.TinyMappingsReader;
public abstract class RemapJarTask extends AbstractRemapJarTask {
public static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
public static final String MANIFEST_NAMESPACE_KEY = "Fabric-Mapping-Namespace";
@InputFiles
public abstract ConfigurableFileCollection getNestedJars();
@@ -128,9 +121,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
@Input
public abstract Property<Boolean> getAddNestedDependencies();
@Input
public abstract Property<Boolean> getIncludesClientOnlyClasses();
/**
* Gets the jar paths to the access wideners that will be converted to ATs for Forge runtime.
* If you specify multiple files, they will be merged into one.
@@ -170,7 +160,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
getClasspath().from(getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME));
getAddNestedDependencies().convention(true).finalizeValueOnRead();
getIncludesClientOnlyClasses().convention(false).finalizeValueOnRead();
getReadMixinConfigsFromManifest().convention(LoomGradleExtension.get(getProject()).isForge()).finalizeValueOnRead();
getInjectAccessWidener().convention(false);
@@ -221,7 +210,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
}
params.getJarManifestService().set(JarManifestService.get(getProject()));
params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), tinyRemapperService.get()));
params.getRemapClasspath().from(getClasspath());
@@ -246,20 +234,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
if (!getAtAccessWideners().get().isEmpty()) {
params.getMappingBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), MappingsService.createDefault(getProject(), getSourceNamespace().get(), getTargetNamespace().get())));
}
if (getIncludesClientOnlyClasses().get()) {
if (!extension.areEnvironmentSourceSetsSplit()) {
throw new UnsupportedOperationException("Jar cannot include client only classes as the sources are not split");
}
final List<String> clientOnlyJarEntries = getClientOnlyJarEntries();
params.getManifestAttributes().set(Map.of(
"Fabric-Loom-Split-Environment", "true",
"Fabric-Loom-Client-Only-Entries", String.join(";", clientOnlyJarEntries)
));
params.getClientOnlyClasses().set(clientOnlyJarEntries.stream().filter(s -> s.endsWith(".class")).toList());
}
});
}
@@ -268,7 +242,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
final MixinExtension mixinExtension = extension.getMixin();
Collection<String> allMixinConfigs = null;
final JsonObject fabricModJson = extension.getPlatform().get() == ModPlatform.FABRIC ? MixinRefmapHelper.readFabricModJson(getInputFile().getAsFile().get()) : null;
final JsonObject fabricModJson = extension.getPlatform().get() == ModPlatform.FABRIC ? ModUtils.getFabricModJson(getInputFile().getAsFile().get().toPath()) : null;
if (fabricModJson == null) {
if (extension.getPlatform().get() == ModPlatform.QUILT) {
@@ -374,12 +348,8 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
record RefmapData(List<String> mixinConfigs, String refmapName) implements Serializable { }
ListProperty<RefmapData> getMixinData();
Property<JarManifestService> getJarManifestService();
Property<String> getTinyRemapperBuildServiceUuid();
Property<String> getMappingBuildServiceUuid();
MapProperty<String, String> getManifestAttributes();
ListProperty<String> getClientOnlyClasses();
}
public abstract static class RemapAction extends AbstractRemapAction<RemapParams> {
@@ -401,7 +371,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
remap();
if (getParameters().getClientOnlyClasses().isPresent()) {
if (getParameters().getClientOnlyEntries().isPresent()) {
markClientOnlyClasses();
}
@@ -439,7 +409,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
private void markClientOnlyClasses() throws IOException {
final Stream<Pair<String, ZipUtils.UnsafeUnaryOperator<byte[]>>> tranformers = getParameters().getClientOnlyClasses().get().stream()
final Stream<Pair<String, ZipUtils.UnsafeUnaryOperator<byte[]>>> tranformers = getParameters().getClientOnlyEntries().get().stream()
.map(s -> new Pair<>(s,
(ZipUtils.AsmClassOperator) classVisitor -> SidedClassVisitor.CLIENT.insertApplyVisitor(null, classVisitor)
));
@@ -564,21 +534,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
JarNester.nestJars(jars, forgeNestedJars.getOrElse(List.of()), outputFile.toFile(), getParameters().getPlatform().get(), LOGGER);
}
private void modifyJarManifest() throws IOException {
int count = ZipUtils.transform(outputFile, Map.of(MANIFEST_PATH, bytes -> {
var manifest = new Manifest(new ByteArrayInputStream(bytes));
getParameters().getJarManifestService().get().apply(manifest, getParameters().getManifestAttributes().get());
manifest.getMainAttributes().putValue(MANIFEST_NAMESPACE_KEY, getParameters().getTargetNamespace().get());
ByteArrayOutputStream out = new ByteArrayOutputStream();
manifest.write(out);
return out.toByteArray();
}));
Preconditions.checkState(count > 0, "Did not transform any jar manifest");
}
private void addRefmaps() throws IOException {
if (getParameters().getUseMixinExtension().get()) {
return;
@@ -596,7 +551,8 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
}
private List<String> getClientOnlyJarEntries() {
@Override
protected List<String> getClientOnlyEntries() {
final SourceSet clientSourceSet = MinecraftSourceSets.Split.getClientSourceSet(getProject());
final ConfigurableFileCollection output = getProject().getObjects().fileCollection();
@@ -613,33 +569,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
.toList();
}
private static List<String> getRootPaths(Set<File> files) {
return files.stream()
.map(root -> {
String rootPath = root.getAbsolutePath().replace("\\", "/");
if (rootPath.charAt(rootPath.length() - 1) != '/') {
rootPath += '/';
}
return rootPath;
}).toList();
}
private static Function<File, String> relativePath(List<String> rootPaths) {
return file -> {
String s = file.getAbsolutePath().replace("\\", "/");
for (String rootPath : rootPaths) {
if (s.startsWith(rootPath)) {
s = s.substring(rootPath.length());
}
}
return s;
};
}
@Internal
public TinyRemapperService getTinyRemapperService() {
return tinyRemapperService.get();

View File

@@ -26,15 +26,18 @@ package net.fabricmc.loom.task;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import javax.inject.Inject;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
import net.fabricmc.loom.task.service.SourceRemapperService;
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
@@ -53,6 +56,15 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
});
}
@Override
protected List<String> getClientOnlyEntries() {
final SourceSet clientSourceSet = MinecraftSourceSets.Split.getClientSourceSet(getProject());
return clientSourceSet.getAllSource().getFiles().stream()
.map(relativePath(getRootPaths(clientSourceSet.getAllSource().getSrcDirs())))
.toList();
}
public interface RemapSourcesParams extends AbstractRemapParams {
Property<String> getSourcesRemapperServiceUuid();
}
@@ -73,6 +85,7 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
try {
sourceRemapperService.remapSourcesJar(inputFile, outputFile);
modifyJarManifest();
rewriteJar();
} catch (Exception e) {
try {

View File

@@ -150,6 +150,7 @@ public class RemapTaskConfiguration {
task.dependsOn(sourcesJarTask);
task.getInputFile().convention(sourcesJarTask.getArchiveFile());
task.getIncludesClientOnlyClasses().set(project.provider(extension::areEnvironmentSourceSetsSplit));
});
tasks.named(BasePlugin.ASSEMBLE_TASK_NAME).configure(task -> task.dependsOn(remapSourcesTask));

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2017 FabricMC
* Copyright (c) 2016-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
@@ -27,20 +27,17 @@ package net.fabricmc.loom.util;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Map;
import java.util.function.Supplier;
import net.fabricmc.tinyremapper.FileSystemReference;
public final class FileSystemUtil {
public record Delegate(FileSystem fs, boolean owner) implements AutoCloseable, Supplier<FileSystem> {
public record Delegate(FileSystemReference reference) implements AutoCloseable, Supplier<FileSystem> {
public byte[] readAllBytes(String path) throws IOException {
Path fsPath = get().getPath(path);
@@ -57,50 +54,36 @@ public final class FileSystemUtil {
@Override
public void close() throws IOException {
if (owner) {
fs.close();
}
reference.close();
}
@Override
public FileSystem get() {
return fs;
return reference.getFs();
}
// TODO cleanup
public FileSystem fs() {
return get();
}
}
private FileSystemUtil() {
}
private static final Map<String, String> jfsArgsCreate = Map.of("create", "true");
private static final Map<String, String> jfsArgsEmpty = Collections.emptyMap();
public static Delegate getJarFileSystem(File file, boolean create) throws IOException {
return getJarFileSystem(file.toURI(), create);
return new Delegate(FileSystemReference.openJar(file.toPath(), create));
}
public static Delegate getJarFileSystem(Path path, boolean create) throws IOException {
return getJarFileSystem(path.toUri(), create);
return new Delegate(FileSystemReference.openJar(path, create));
}
public static Delegate getJarFileSystem(Path path) throws IOException {
return getJarFileSystem(path, false);
return new Delegate(FileSystemReference.openJar(path));
}
public static Delegate getJarFileSystem(URI uri, boolean create) throws IOException {
URI jarUri;
try {
jarUri = new URI("jar:" + uri.getScheme(), uri.getHost(), uri.getPath(), uri.getFragment());
} catch (URISyntaxException e) {
throw new IOException(e);
}
try {
return new Delegate(FileSystems.newFileSystem(jarUri, create ? jfsArgsCreate : jfsArgsEmpty), true);
} catch (FileSystemAlreadyExistsException e) {
return new Delegate(FileSystems.getFileSystem(jarUri), false);
} catch (IOException e) {
throw new IOException("Could not create JAR file system for " + uri + " (create: " + create + ")", e);
}
return new Delegate(FileSystemReference.open(uri, create));
}
}

View File

@@ -27,15 +27,12 @@ package net.fabricmc.loom.util;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import com.google.gson.JsonObject;
import org.gradle.api.logging.Logger;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradlePlugin;
public final class ModUtils {
private ModUtils() {
}
@@ -56,19 +53,11 @@ public final class ModUtils {
@Nullable
public static JsonObject getFabricModJson(Path path) {
final byte[] modJsonBytes;
try {
modJsonBytes = ZipUtils.unpackNullable(path, "fabric.mod.json");
return ZipUtils.unpackGsonNullable(path, "fabric.mod.json", JsonObject.class);
} catch (IOException e) {
throw new UncheckedIOException("Failed to extract fabric.mod.json from " + path, e);
}
if (modJsonBytes == null) {
return null;
}
return LoomGradlePlugin.GSON.fromJson(new String(modJsonBytes, StandardCharsets.UTF_8), JsonObject.class);
}
public static boolean shouldRemapMod(Logger logger, File input, Object id, ModPlatform platform, String config) {

View File

@@ -107,6 +107,25 @@ public class ZipUtils {
}
}
public static <T> T unpackGson(Path zip, String path, Class<T> clazz) throws IOException {
final byte[] bytes = unpack(zip, path);
return LoomGradlePlugin.GSON.fromJson(new String(bytes, StandardCharsets.UTF_8), clazz);
}
@Nullable
public static <T> T unpackGsonNullable(Path zip, String path, Class<T> clazz) throws IOException {
try {
return unpackGson(zip, path, clazz);
} catch (NoSuchFileException e) {
return null;
}
}
public static <T> T unpackJackson(Path zip, String path, Class<T> clazz) throws IOException {
final byte[] bytes = unpack(zip, path);
return LoomGradlePlugin.OBJECT_MAPPER.readValue(new String(bytes, StandardCharsets.UTF_8), clazz);
}
public static void pack(Path from, Path zip) throws IOException {
Files.deleteIfExists(zip);

View File

@@ -46,6 +46,13 @@ trait GradleProjectTestTrait {
File projectDir = options.projectDir as File ?: options.sharedFiles ? sharedProjectDir : File.createTempDir()
File gradleHomeDir = options.gradleHomeDir as File ?: options.sharedFiles ? sharedGradleHomeDir : File.createTempDir()
// Useful for faster local testing.
def homeDirOverride = System.getProperty("fabric.loom.test.homeDir")
if (homeDirOverride) {
gradleHomeDir = new File(homeDirOverride)
}
setupProject(options, projectDir)
println([