Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/exp/1.4' into exp/1.4
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java
  • Loading branch information
shedaniel committed Oct 12, 2023
2 parents 352294a + b7c8013 commit 4af46aa
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 FabricMC
* Copyright (c) 2022-2023 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
Expand All @@ -25,7 +25,6 @@
package net.fabricmc.loom.configuration.processors;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -47,11 +46,10 @@
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
import net.fabricmc.loom.api.processor.ProcessorContext;
import net.fabricmc.loom.api.processor.SpecContext;
import net.fabricmc.loom.util.ZipUtils;
import net.fabricmc.loom.util.Checksum;
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;
Expand Down Expand Up @@ -102,17 +100,22 @@ private String getCacheValue() {
}

private String getDebugString() {
final StringJoiner sj = new StringJoiner("\n");
final var sj = new StringJoiner("\n");

for (ProcessorEntry<?> jarProcessor : jarProcessors) {
sj.add(jarProcessor.name() + ":");
sj.add("\tHash: " + jarProcessor.hashCode());
sj.add("\tStr: " + jarProcessor.toString());
sj.add("\tStr: " + jarProcessor.cacheValue());
}

return sj.toString();
}

public String getJarHash() {
//fabric-loom:mod-javadoc:-1289977000
return Checksum.sha1Hex(getCacheValue().getBytes(StandardCharsets.UTF_8)).substring(0, 10);
}

public boolean requiresProcessingJar(Path jar) {
Objects.requireNonNull(jar);

Expand All @@ -121,32 +124,7 @@ public boolean requiresProcessingJar(Path jar) {
return true;
}

byte[] existingCache;

try {
existingCache = ZipUtils.unpackNullable(jar, CACHE_VALUE_FILE_PATH);
} catch (IOException e) {
throw new UncheckedIOException("Failed to unpack jar: " + jar, e);
}

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);
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;
return false;
}

public void processJar(Path jar, ProcessorContext context) throws IOException {
Expand All @@ -157,8 +135,6 @@ public void processJar(Path jar, ProcessorContext context) throws IOException {
throw new IOException("Failed to process jar when running jar processor: %s".formatted(entry.name()), e);
}
}

ZipUtils.add(jar, CACHE_VALUE_FILE_PATH, getCacheValue());
}

public boolean processMappings(MemoryMappingTree mappings, MappingProcessorContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import javax.inject.Inject;

Expand All @@ -45,6 +47,7 @@
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
import net.fabricmc.loom.api.processor.ProcessorContext;
import net.fabricmc.loom.api.processor.SpecContext;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.fmj.FabricModJson;
import net.fabricmc.mappingio.MappingReader;
Expand Down Expand Up @@ -82,6 +85,7 @@ public String getName() {
return null;
}

javadocs.sort(Comparator.comparing(ModJavadoc::modId));
return new Spec(Collections.unmodifiableList(javadocs));
}

Expand All @@ -104,7 +108,7 @@ public void processJar(Path jar, Spec spec, ProcessorContext context) {
};
}

public record ModJavadoc(String modId, MemoryMappingTree mappingTree) {
public record ModJavadoc(String modId, MemoryMappingTree mappingTree, String mappingsHash) {
@Nullable
public static ModJavadoc create(FabricModJson fabricModJson) {
final String modId = fabricModJson.getId();
Expand All @@ -116,9 +120,11 @@ public static ModJavadoc create(FabricModJson fabricModJson) {

final String javaDocPath = customElement.getAsString();
final MemoryMappingTree mappings = new MemoryMappingTree();
final String mappingsHash;

try {
final byte[] data = fabricModJson.getSource().read(javaDocPath);
mappingsHash = Checksum.sha1Hex(data);

try (Reader reader = new InputStreamReader(new ByteArrayInputStream(data))) {
MappingReader.read(reader, mappings);
Expand All @@ -135,7 +141,7 @@ public static ModJavadoc create(FabricModJson fabricModJson) {
throw new IllegalStateException("Javadoc provided by mod (%s) must not contain any dst names".formatted(modId));
}

return new ModJavadoc(modId, mappings);
return new ModJavadoc(modId, mappings, mappingsHash);
}

public void apply(MemoryMappingTree target) {
Expand Down Expand Up @@ -196,5 +202,16 @@ private <T extends MappingTree.ElementMapping> void applyComment(T source, T tar
targetComment += sourceComment;
target.setComment(targetComment);
}

// Must override as not to include MemoryMappingTree
@Override
public int hashCode() {
return Objects.hash(modId, mappingsHash);
}

@Override
public String toString() {
return "ModJavadoc{modId='%s', mappingsHash='%s'}".formatted(modId, mappingsHash);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2021-2022 FabricMC
* Copyright (c) 2021-2023 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
Expand All @@ -28,14 +28,11 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.gradle.api.Project;

import net.fabricmc.loom.configuration.ConfigContext;
import net.fabricmc.loom.configuration.mods.dependency.LocalMavenHelper;
import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager;
Expand Down Expand Up @@ -129,15 +126,9 @@ private void deleteSimilarJars(Path jar) throws IOException {

@Override
protected String getName(String name) {
final Project project = getProject();
final String jarPrefix = parentMinecraftProvider.getMinecraftProvider().getJarPrefix();

if (project.getRootProject() == project) {
return jarPrefix + "minecraft-%s-project-root".formatted(name).toLowerCase(Locale.ROOT);
}

final String projectPath = project.getPath().replace(':', '@');
return jarPrefix + "minecraft-%s-project-%s".formatted(name, projectPath).toLowerCase(Locale.ROOT);
// Hash the cache value so that we don't have to process the same JAR multiple times for many projects
return jarPrefix + "minecraft-%s-%s".formatted(name, jarProcessorManager.getJarHash());
}

@Override
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/net/fabricmc/loom/util/Checksum.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
Expand Down Expand Up @@ -72,6 +73,15 @@ public static String sha1Hex(Path path) throws IOException {
return toHex(hash.asBytes());
}

public static String sha1Hex(byte[] input) {
try {
HashCode hash = ByteSource.wrap(input).hash(Hashing.sha1());
return toHex(hash.asBytes());
} catch (IOException e) {
throw new UncheckedIOException("Failed to hash", e);
}
}

public static String truncatedSha256(File file) {
try {
HashCode hash = Files.asByteSource(file).hash(Hashing.sha256());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,46 +26,37 @@ package net.fabricmc.loom.test.unit.processor

import spock.lang.Specification

import net.fabricmc.loom.api.processor.ProcessorContext
import net.fabricmc.loom.api.processor.SpecContext
import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager
import net.fabricmc.loom.test.util.processor.TestMinecraftJarProcessor

import static net.fabricmc.loom.test.util.ZipTestUtils.createZip

class MinecraftJarProcessorManagerTest extends Specification {
def "Does not require re-processing"() {
given:
def "Cache value matches"() {
when:
def specContext = Mock(SpecContext)
def processorContext = Mock(ProcessorContext)

def processor1 = new TestMinecraftJarProcessor(input: "Test1")
def processor2 = new TestMinecraftJarProcessor(input: "Test2")
def manager = MinecraftJarProcessorManager.create([processor1, processor2], specContext)

when:
def jar = createZip(["fabric.mod.json": "{}"])
manager.processJar(jar, processorContext)
def manager1 = MinecraftJarProcessorManager.create([processor1, processor2], specContext)
def manager2 = MinecraftJarProcessorManager.create([processor1, processor2], specContext)

then:
!manager.requiresProcessingJar(jar)
manager1.jarHash == manager2.jarHash
manager1.jarHash == "eb6faafa72"
}

def "Requires re-processing"() {
given:
def "Cache value does not match"() {
when:
def specContext = Mock(SpecContext)
def processorContext = Mock(ProcessorContext)

def processor1 = new TestMinecraftJarProcessor(input: "Test1")
def processor2 = new TestMinecraftJarProcessor(input: "Test2")
def manager1 = MinecraftJarProcessorManager.create([processor1], specContext)
def manager2 = MinecraftJarProcessorManager.create([processor1, processor2], specContext)

when:
def jar = createZip(["fabric.mod.json": "{}"])
manager1.processJar(jar, processorContext)

then:
manager2.requiresProcessingJar(jar)
manager1.jarHash != manager2.jarHash
manager1.jarHash == "a714eb2de6"
manager2.jarHash == "eb6faafa72"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package net.fabricmc.loom.test.util

import groovy.io.FileType
import groovy.transform.Immutable
import org.apache.commons.io.FileUtils
import org.gradle.testkit.runner.BuildResult
Expand Down Expand Up @@ -241,7 +242,20 @@ trait GradleProjectTestTrait {
}

File getGeneratedLocalSources(String mappings) {
return new File(getProjectDir(), ".gradle/loom-cache/minecraftMaven/net/minecraft/minecraft-merged-project-root/${mappings}/minecraft-merged-project-root-${mappings}-sources.jar")
File file
getProjectDir().traverse(type: FileType.FILES) {
if (it.name.startsWith("minecraft-merged-")
&& it.name.contains(mappings)
&& it.name.endsWith("-sources.jar")) {
file = it
}
}

if (file == null) {
throw new FileNotFoundException()
}

return file
}

void buildSrc(String name) {
Expand Down

0 comments on commit 4af46aa

Please sign in to comment.