mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-30 21:05:58 -05:00
Fix and test jar processor caching.
This commit is contained in:
@@ -42,5 +42,7 @@ public interface AccessWidenerEntry {
|
||||
@Nullable
|
||||
String mappingId();
|
||||
|
||||
String getSortKey();
|
||||
|
||||
void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -62,8 +65,14 @@ public class AccessWidenerJarProcessor implements MinecraftJarProcessor<AccessWi
|
||||
List<AccessWidenerEntry> accessWideners = new ArrayList<>();
|
||||
|
||||
if (localAccessWidenerProperty.isPresent()) {
|
||||
Path path = localAccessWidenerProperty.get().getAsFile().toPath();
|
||||
|
||||
if (Files.notExists(path)) {
|
||||
throw new UncheckedIOException(new FileNotFoundException("Could not find access widener file at {%s}".formatted(path)));
|
||||
}
|
||||
|
||||
// Add the access widener specified in the extension
|
||||
accessWideners.add(new LocalAccessWidenerEntry(localAccessWidenerProperty.get().getAsFile().toPath()));
|
||||
accessWideners.add(LocalAccessWidenerEntry.create(path));
|
||||
}
|
||||
|
||||
/* Uncomment to read all access wideners from local mods.
|
||||
@@ -84,7 +93,7 @@ public class AccessWidenerJarProcessor implements MinecraftJarProcessor<AccessWi
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Spec(Collections.unmodifiableList(accessWideners));
|
||||
return new Spec(accessWideners.stream().sorted(Comparator.comparing(AccessWidenerEntry::getSortKey)).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -32,11 +33,20 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.loom.util.fmj.ModEnvironment;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public record LocalAccessWidenerEntry(Path path) implements AccessWidenerEntry {
|
||||
public record LocalAccessWidenerEntry(Path path, String hash) implements AccessWidenerEntry {
|
||||
public static LocalAccessWidenerEntry create(Path path) {
|
||||
try {
|
||||
return new LocalAccessWidenerEntry(path, Checksum.sha1Hex(path));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to create LocalAccessWidenerEntry", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
|
||||
var reader = new AccessWidenerReader(visitor);
|
||||
@@ -52,4 +62,14 @@ public record LocalAccessWidenerEntry(Path path) implements AccessWidenerEntry {
|
||||
public @Nullable String mappingId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSortKey() {
|
||||
return "local";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ public record ModAccessWidenerEntry(FabricModJson mod, String path, ModEnvironme
|
||||
return transitiveOnly ? mod.getId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSortKey() {
|
||||
return mod.getId() + ":" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
|
||||
if (transitiveOnly) {
|
||||
|
||||
@@ -34,10 +34,13 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.processor.MappingProcessorContext;
|
||||
@@ -49,6 +52,7 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
public final class MinecraftJarProcessorManager {
|
||||
private static final String CACHE_VALUE_FILE_PATH = "META-INF/Loom-Jar-Processor-Cache";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MinecraftJarProcessorManager.class);
|
||||
|
||||
private final List<ProcessorEntry<?>> jarProcessors;
|
||||
|
||||
@@ -73,14 +77,17 @@ public final class MinecraftJarProcessorManager {
|
||||
List<ProcessorEntry<?>> entries = new ArrayList<>();
|
||||
|
||||
for (MinecraftJarProcessor<?> processor : processors) {
|
||||
LOGGER.debug("Building processor spec for {}", processor.getName());
|
||||
MinecraftJarProcessor.Spec spec = processor.buildSpec(context);
|
||||
|
||||
if (spec != null) {
|
||||
LOGGER.debug("Adding processor entry for {}", processor.getName());
|
||||
entries.add(new ProcessorEntry<>(processor, spec));
|
||||
}
|
||||
}
|
||||
|
||||
if (entries.isEmpty()) {
|
||||
LOGGER.debug("No processor entries");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -94,10 +101,23 @@ public final class MinecraftJarProcessorManager {
|
||||
.collect(Collectors.joining("::"));
|
||||
}
|
||||
|
||||
private String getDebugString() {
|
||||
final StringJoiner sj = new StringJoiner("\n");
|
||||
|
||||
for (ProcessorEntry<?> jarProcessor : jarProcessors) {
|
||||
sj.add(jarProcessor.name() + ":");
|
||||
sj.add("\tHash: " + jarProcessor.hashCode());
|
||||
sj.add("\tStr: " + jarProcessor.toString());
|
||||
}
|
||||
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
public boolean requiresProcessingJar(Path jar) {
|
||||
Objects.requireNonNull(jar);
|
||||
|
||||
if (Files.notExists(jar)) {
|
||||
LOGGER.debug("{} does not exist, generating", jar);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -110,11 +130,23 @@ public final class MinecraftJarProcessorManager {
|
||||
}
|
||||
|
||||
if (existingCache == null) {
|
||||
LOGGER.info("{} does not contain a processor cache value, regenerating", jar);
|
||||
return true;
|
||||
}
|
||||
|
||||
final String existingCacheValue = new String(existingCache, StandardCharsets.UTF_8);
|
||||
return !existingCacheValue.equals(getCacheValue());
|
||||
final String expectedCacheValue = getCacheValue();
|
||||
final boolean matches = existingCacheValue.equals(expectedCacheValue);
|
||||
|
||||
if (!matches) {
|
||||
LOGGER.info("{} has an invalid cache, got {} expected {}", jar, existingCacheValue, expectedCacheValue);
|
||||
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info("Expected state: {}", getDebugString());
|
||||
}
|
||||
}
|
||||
|
||||
return !matches;
|
||||
}
|
||||
|
||||
public void processJar(Path jar, ProcessorContext context) throws IOException {
|
||||
|
||||
@@ -62,7 +62,7 @@ public class Checksum {
|
||||
HashCode hash = Files.asByteSource(file).hash(Hashing.sha256());
|
||||
return hash.asBytes();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to get file hash");
|
||||
throw new UncheckedIOException("Failed to get file hash", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,9 @@ import java.util.Objects;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
public abstract sealed class FabricModJson permits FabricModJsonV0, FabricModJsonV1, FabricModJsonV2 {
|
||||
public abstract sealed class FabricModJson permits FabricModJsonV0, FabricModJsonV1, FabricModJsonV2, FabricModJson.Mockable {
|
||||
protected final JsonObject jsonObject;
|
||||
private final FabricModJsonSource source;
|
||||
|
||||
@@ -59,4 +60,22 @@ public abstract sealed class FabricModJson permits FabricModJsonV0, FabricModJso
|
||||
public final FabricModJsonSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return getClass().getName() + "[id=%s, version=%s, classTweakers=%s]".formatted(getId(), getVersion(), getClassTweakers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(getId(), getVersion());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public abstract non-sealed class Mockable extends FabricModJson {
|
||||
private Mockable() {
|
||||
super(null, null);
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,21 @@
|
||||
|
||||
package net.fabricmc.loom.util.fmj;
|
||||
|
||||
public enum ModEnvironment {
|
||||
UNIVERSAL(true, true),
|
||||
CLIENT(true, false),
|
||||
SERVER(false, true);
|
||||
import java.util.Objects;
|
||||
|
||||
public final class ModEnvironment {
|
||||
public static final ModEnvironment UNIVERSAL = new ModEnvironment(true, true, "universal");
|
||||
public static final ModEnvironment CLIENT = new ModEnvironment(true, false, "client");
|
||||
public static final ModEnvironment SERVER = new ModEnvironment(false, true, "server");
|
||||
|
||||
private final boolean client;
|
||||
private final boolean server;
|
||||
private final String name;
|
||||
|
||||
ModEnvironment(boolean client, boolean server) {
|
||||
private ModEnvironment(boolean client, boolean server, String name) {
|
||||
this.client = client;
|
||||
this.server = server;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isClient() {
|
||||
@@ -44,4 +48,17 @@ public enum ModEnvironment {
|
||||
public boolean isServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ModEnvironment that = (ModEnvironment) o;
|
||||
return name.equals(that.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user