Split Architectury extensions to Fabric classes into new classes (#116)

* Split custom RemapJarTask logic into a new class

* Split a lot of logic for Arch and Quilt mod metadata into new classes

* ArchitecturyCommonJson: Fix outdated error message

* Add minimal unit tests for ACJ and QMJ

* QuiltModJson: Fix error when there are no injected interfaces

* QuiltModJsonTest: Add test for mixin configs

* QuiltModJsonTest: Move to correct package

* Add tests for creating ACJ and QMJ instances
This commit is contained in:
Juuz
2023-01-07 01:51:32 +02:00
committed by GitHub
parent 8dad64dc66
commit f2c0d7a35d
10 changed files with 590 additions and 185 deletions

View File

@@ -24,46 +24,30 @@
package net.fabricmc.loom.task;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.inject.Inject;
import com.google.common.base.Suppliers;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import dev.architectury.loom.extensions.ModBuildExtensions;
import dev.architectury.loom.metadata.QuiltModJson;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import org.cadixdev.at.AccessTransformSet;
import org.cadixdev.at.io.AccessTransformFormats;
import org.cadixdev.lorenz.MappingSet;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
@@ -79,7 +63,6 @@ import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskDependency;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -87,7 +70,6 @@ import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerRemapper;
import net.fabricmc.accesswidener.AccessWidenerWriter;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.build.MixinRefmapHelper;
import net.fabricmc.loom.build.nesting.IncludedJarFactory;
import net.fabricmc.loom.build.nesting.IncludedJarFactory.LazyNestedFile;
@@ -100,16 +82,12 @@ 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.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;
import net.fabricmc.loom.util.aw2at.Aw2At;
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
import net.fabricmc.lorenztiny.TinyMappingsReader;
public abstract class RemapJarTask extends AbstractRemapJarTask {
@InputFiles
@@ -250,22 +228,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
byte[] bytes = ZipUtils.unpackNullable(getInputFile().getAsFile().get().toPath(), "quilt.mod.json");
if (bytes != null) {
JsonObject json = LoomGradlePlugin.GSON.fromJson(new InputStreamReader(new ByteArrayInputStream(bytes)), JsonObject.class);
JsonElement mixins = json.has("mixin") ? json.get("mixin") : json.get("mixins");
if (mixins != null) {
if (mixins.isJsonPrimitive()) {
allMixinConfigs = Collections.singletonList(mixins.getAsString());
} else if (mixins.isJsonArray()) {
allMixinConfigs = StreamSupport.stream(mixins.getAsJsonArray().spliterator(), false)
.map(JsonElement::getAsString)
.collect(Collectors.toList());
} else {
throw new RuntimeException("Unknown mixin type: " + mixins.getClass().getName());
}
} else {
allMixinConfigs = Collections.emptyList();
}
allMixinConfigs = QuiltModJson.of(bytes).getMixinConfigs();
}
} catch (IOException e) {
throw new RuntimeException("Cannot read file quilt.mod.json in the jar.", e);
@@ -273,7 +236,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
if (allMixinConfigs == null && getReadMixinConfigsFromManifest().get()) {
allMixinConfigs = readMixinConfigsFromManifest();
allMixinConfigs = ModBuildExtensions.readMixinConfigsFromManifest(getInputFile().get().getAsFile());
}
if (allMixinConfigs == null) {
@@ -309,27 +272,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
}
private Collection<String> readMixinConfigsFromManifest() {
File inputJar = getInputFile().get().getAsFile();
try (JarFile jar = new JarFile(inputJar)) {
@Nullable Manifest manifest = jar.getManifest();
if (manifest != null) {
Attributes attributes = manifest.getMainAttributes();
String mixinConfigs = attributes.getValue(Constants.Forge.MIXIN_CONFIGS_MANIFEST_KEY);
if (mixinConfigs != null) {
return Set.of(mixinConfigs.split(","));
}
}
return Set.of();
} catch (IOException e) {
throw new UncheckedIOException("Could not read mixin configs from input jar", e);
}
}
public interface RemapParams extends AbstractRemapParams {
ConfigurableFileCollection getNestedJars();
@@ -381,7 +323,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
addRefmaps();
addNestedJars();
convertAwToAt();
ModBuildExtensions.convertAwToAt(getParameters().getAtAccessWideners(), outputFile, getParameters().getMappingBuildServiceUuid());
if (getParameters().getPlatform().get() != ModPlatform.FORGE) {
modifyJarManifest();
@@ -455,55 +397,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
ZipUtils.replace(outputFile, accessWidenerFile.path(), remapped);
}
private void convertAwToAt() throws IOException {
if (!this.getParameters().getAtAccessWideners().isPresent()) {
return;
}
Set<String> atAccessWideners = this.getParameters().getAtAccessWideners().get();
if (atAccessWideners.isEmpty()) {
return;
}
AccessTransformSet at = AccessTransformSet.create();
File jar = outputFile.toFile();
try (FileSystemUtil.Delegate fileSystem = FileSystemUtil.getJarFileSystem(jar, false)) {
FileSystem fs = fileSystem.get();
Path atPath = fs.getPath(Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (Files.exists(atPath)) {
throw new FileAlreadyExistsException("Jar " + jar + " already contains an access transformer - cannot convert AWs!");
}
for (String aw : atAccessWideners) {
Path awPath = fs.getPath(aw);
if (Files.notExists(awPath)) {
throw new NoSuchFileException("Could not find AW '" + aw + "' to convert into AT!");
}
try (BufferedReader reader = Files.newBufferedReader(awPath, StandardCharsets.UTF_8)) {
at.merge(Aw2At.toAccessTransformSet(reader));
}
Files.delete(awPath);
}
MappingsService service = UnsafeWorkQueueHelper.get(getParameters().getMappingBuildServiceUuid(), MappingsService.class);
try (TinyMappingsReader reader = new TinyMappingsReader(service.getMemoryMappingTree(), service.getFromNamespace(), service.getToNamespace())) {
MappingSet mappingSet = reader.read();
at = at.remap(mappingSet);
}
try (Writer writer = new LfWriter(Files.newBufferedWriter(atPath))) {
AccessTransformFormats.FML.write(writer, at);
}
}
}
private byte[] remapAccessWidener(byte[] input) {
int version = AccessWidenerReader.readVersion(input);