Merge 1.8, part 9

This commit is contained in:
Juuz
2024-12-06 19:32:12 +02:00
20 changed files with 277 additions and 93 deletions

View File

@@ -1,6 +1,6 @@
[versions]
kotlin = "1.9.24"
asm = "9.6"
asm = "9.7.1"
commons-io = "2.15.1"
gson = "2.10.1"
guava = "33.0.0-jre"

View File

@@ -6,7 +6,7 @@ mockito = "5.13.0"
java-debug = "0.52.0"
mixin = "0.15.3+mixin.0.8.7"
gradle-nightly = "8.11-20240926001708+0000"
gradle-nightly = "8.12-20241009055624+0000"
fabric-loader = "0.16.5"
fabric-installer = "1.0.1"

View File

@@ -50,6 +50,7 @@ import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.forge.mcpconfig.McpConfigProvider;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsFactory;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMetadataProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
@@ -80,6 +81,10 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
LoomDependencyManager getDependencyManager();
MinecraftMetadataProvider getMetadataProvider();
void setMetadataProvider(MinecraftMetadataProvider metadataProvider);
MinecraftProvider getMinecraftProvider();
void setMinecraftProvider(MinecraftProvider minecraftProvider);

View File

@@ -74,7 +74,6 @@ import net.fabricmc.loom.configuration.providers.forge.mcpconfig.McpConfigProvid
import net.fabricmc.loom.configuration.providers.forge.minecraft.ForgeMinecraftProvider;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsFactory;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMetadataProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
@@ -86,7 +85,6 @@ import net.fabricmc.loom.configuration.providers.minecraft.mapped.SrgMinecraftPr
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.ExceptionUtil;
import net.fabricmc.loom.util.ProcessUtil;
import net.fabricmc.loom.util.gradle.GradleUtils;
@@ -198,13 +196,10 @@ public abstract class CompileConfiguration implements Runnable {
final LoomGradleExtension extension = configContext.extension();
final MinecraftMetadataProvider metadataProvider = MinecraftMetadataProvider.create(configContext);
extension.setMetadataProvider(metadataProvider);
var jarConfiguration = extension.getMinecraftJarConfiguration().get();
if (jarConfiguration == MinecraftJarConfiguration.MERGED && !metadataProvider.getVersionMeta().isVersionOrNewer(Constants.RELEASE_TIME_1_3)) {
jarConfiguration = MinecraftJarConfiguration.LEGACY_MERGED;
}
// Provide the vanilla mc jars
final MinecraftProvider minecraftProvider = jarConfiguration.createMinecraftProvider(metadataProvider, configContext);

View File

@@ -79,12 +79,19 @@ public final class SplitDecompileConfiguration extends DecompileConfiguration<Ma
for (DecompilerOptions options : extension.getDecompilerOptions()) {
final String decompilerName = options.getFormattedName();
var commonTask = project.getTasks().named("gen%sSourcesWith%s".formatted("Common", decompilerName));
var clientOnlyTask = project.getTasks().named("gen%sSourcesWith%s".formatted("ClientOnly", decompilerName));
clientOnlyTask.configure(task -> {
task.mustRunAfter(commonTask);
});
project.getTasks().register("genSourcesWith" + decompilerName, task -> {
task.setDescription("Decompile minecraft using %s.".formatted(decompilerName));
task.setGroup(Constants.TaskGroup.FABRIC);
task.dependsOn(project.getTasks().named("gen%sSourcesWith%s".formatted("Common", decompilerName)));
task.dependsOn(project.getTasks().named("gen%sSourcesWith%s".formatted("ClientOnly", decompilerName)));
task.dependsOn(commonTask);
task.dependsOn(clientOnlyTask);
});
}

View File

@@ -109,6 +109,7 @@ public abstract class IdeaSyncTask extends AbstractLoomTask {
irc.getRunConfigXml().set(runConfigXml);
irc.getExcludedLibraryPaths().set(excludedLibraryPaths);
irc.getLaunchFile().set(runConfigFile);
configs.add(irc);
}
return configs;

View File

@@ -116,6 +116,10 @@ public final class MinecraftJarProcessorManager {
return Checksum.sha1Hex(getCacheValue().getBytes(StandardCharsets.UTF_8)).substring(0, 10);
}
public String getSourceMappingsHash() {
return Checksum.sha1Hex(getCacheValue().getBytes(StandardCharsets.UTF_8));
}
public boolean requiresProcessingJar(Path jar) {
Objects.requireNonNull(jar);

View File

@@ -78,8 +78,10 @@ import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuil
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsFactory;
import net.fabricmc.loom.configuration.providers.minecraft.ManifestLocations;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMetadataProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DeprecationHelper;
import net.fabricmc.loom.util.MirrorUtil;
import net.fabricmc.loom.util.ModPlatform;
@@ -174,7 +176,23 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
this.minecraftJarProcessors.finalizeValueOnRead();
//noinspection unchecked
this.minecraftJarConfiguration = project.getObjects().property((Class<MinecraftJarConfiguration<?, ?, ?>>) (Class<?>) MinecraftJarConfiguration.class).convention(MinecraftJarConfiguration.MERGED);
this.minecraftJarConfiguration = project.getObjects().property((Class<MinecraftJarConfiguration<?, ?, ?>>) (Class<?>) MinecraftJarConfiguration.class)
.convention(project.provider(() -> {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final MinecraftMetadataProvider metadataProvider = extension.getMetadataProvider();
// if no configuration is selected by the user, attempt to select one
// based on the mc version and which sides are present for it
if (!metadataProvider.getVersionMeta().downloads().containsKey("server")) {
return MinecraftJarConfiguration.CLIENT_ONLY;
} else if (!metadataProvider.getVersionMeta().downloads().containsKey("client")) {
return MinecraftJarConfiguration.SERVER_ONLY;
} else if (metadataProvider.getVersionMeta().isVersionOrNewer(Constants.RELEASE_TIME_1_3)) {
return MinecraftJarConfiguration.MERGED;
} else {
return MinecraftJarConfiguration.LEGACY_MERGED;
}
}));
this.minecraftJarConfiguration.finalizeValueOnRead();
this.accessWidener.finalizeValueOnRead();

View File

@@ -56,6 +56,7 @@ import net.fabricmc.loom.configuration.providers.mappings.IntermediaryMappingsPr
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsFactory;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.configuration.providers.mappings.NoOpIntermediateMappingsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMetadataProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
@@ -75,6 +76,7 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
private final List<AccessWidenerFile> transitiveAccessWideners = new ArrayList<>();
private LoomDependencyManager dependencyManager;
private MinecraftMetadataProvider metadataProvider;
private MinecraftProvider minecraftProvider;
private MappingConfiguration mappingConfiguration;
private NamedMinecraftProvider<?> namedMinecraftProvider;
@@ -151,6 +153,16 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
return Objects.requireNonNull(dependencyManager, "Cannot get LoomDependencyManager before it has been setup");
}
@Override
public MinecraftMetadataProvider getMetadataProvider() {
return Objects.requireNonNull(metadataProvider, "Cannot get MinecraftMetadataProvider before it has been setup");
}
@Override
public void setMetadataProvider(MinecraftMetadataProvider metadataProvider) {
this.metadataProvider = metadataProvider;
}
@Override
public MinecraftProvider getMinecraftProvider() {
return Objects.requireNonNull(minecraftProvider, "Cannot get MinecraftProvider before it has been setup");

View File

@@ -73,7 +73,7 @@ public abstract class GenVsCodeProjectTask extends AbstractLoomTask {
public GenVsCodeProjectTask() {
setGroup(Constants.TaskGroup.IDE);
getLaunchConfigurations().set(getProject().provider(this::getConfigurations));
getLaunchJson().convention(getProject().getRootProject().getLayout().getProjectDirectory().file("vscode/launch.json"));
getLaunchJson().convention(getProject().getRootProject().getLayout().getProjectDirectory().file(".vscode/launch.json"));
}
private List<VsCodeConfiguration> getConfigurations() {

View File

@@ -254,6 +254,8 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
}
if (!getUseCache().get()) {
getLogger().info("Not using decompile cache.");
try (var timer = new Timer("Decompiled sources")) {
runWithoutCache();
} catch (Exception e) {
@@ -346,19 +348,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
final ClassLineNumbers existingLinenumbers = workRequest.lineNumbers();
final ClassLineNumbers lineNumbers = ClassLineNumbers.merge(existingLinenumbers, outputLineNumbers);
if (lineNumbers == null) {
getLogger().info("No line numbers to remap, skipping remapping");
return;
}
Path tempJar = Files.createTempFile("loom", "linenumber-remap.jar");
Files.delete(tempJar);
try (var timer = new Timer("Remap line numbers")) {
remapLineNumbers(lineNumbers, classesInputJar, tempJar);
}
Files.move(tempJar, classesOutputJar, StandardCopyOption.REPLACE_EXISTING);
applyLineNumbers(lineNumbers, classesInputJar, classesOutputJar);
try (var timer = new Timer("Prune cache")) {
decompileCache.prune();
@@ -366,31 +356,36 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
}
private void runWithoutCache() throws IOException {
Path inputJar = getClassesInputJar().getSingleFile().toPath();
final Path outputJar = getSourcesOutputJar().get().getAsFile().toPath();
final Path classesInputJar = getClassesInputJar().getSingleFile().toPath();
final Path sourcesOutputJar = getSourcesOutputJar().get().getAsFile().toPath();
final Path classesOutputJar = getClassesOutputJar().getSingleFile().toPath();
// The final output sources jar
Path workClassesJar = classesInputJar;
if (getUnpickDefinitions().isPresent()) {
try (var timer = new Timer("Unpick")) {
inputJar = unpickJar(inputJar, null);
workClassesJar = unpickJar(workClassesJar, null);
}
}
ClassLineNumbers lineNumbers;
try (var timer = new Timer("Decompile")) {
lineNumbers = runDecompileJob(inputJar, outputJar, null);
removeForgeInnerClassSources(sourcesJar);
lineNumbers = runDecompileJob(workClassesJar, sourcesOutputJar, null);
removeForgeInnerClassSources(sourcesOutputJar);
lineNumbers = filterForgeLineNumbers(lineNumbers);
}
if (Files.notExists(outputJar)) {
if (Files.notExists(sourcesOutputJar)) {
throw new RuntimeException("Failed to decompile sources");
}
getLogger().info("Decompiled sources written to {}", outputJar);
getLogger().info("Decompiled sources written to {}", sourcesOutputJar);
applyLineNumbers(lineNumbers, classesInputJar, classesOutputJar);
}
private void applyLineNumbers(@Nullable ClassLineNumbers lineNumbers, Path classesInputJar, Path classesOutputJar) throws IOException {
if (lineNumbers == null) {
getLogger().info("No line numbers to remap, skipping remapping");
return;
@@ -400,10 +395,10 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
Files.delete(tempJar);
try (var timer = new Timer("Remap line numbers")) {
remapLineNumbers(lineNumbers, inputJar, tempJar);
remapLineNumbers(lineNumbers, classesInputJar, tempJar);
}
Files.move(tempJar, outputJar, StandardCopyOption.REPLACE_EXISTING);
Files.move(tempJar, classesOutputJar, StandardCopyOption.REPLACE_EXISTING);
}
private String getCacheKey() {

View File

@@ -59,9 +59,9 @@ public final class LorenzMappingService extends Service<LorenzMappingService.Opt
return TYPE.create(project, options -> options.getMappings().set(
MappingsService.createOptions(
project,
mappingConfiguration.getMappingsPath(mappingOption),
to.toString(),
mappingConfiguration.getMappingsPath(mappingOption),
from.toString(),
to.toString(),
false)
));
}

View File

@@ -31,13 +31,13 @@ import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.InputFiles;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
@@ -56,6 +56,7 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree;
public class SourceMappingsService extends Service<SourceMappingsService.Options> {
public static final ServiceType<Options, SourceMappingsService> TYPE = new ServiceType<>(Options.class, SourceMappingsService.class);
private static final Logger LOGGER = LoggerFactory.getLogger(SourceMappingsService.class);
public interface Options extends Service.Options {
@InputFiles
@@ -71,64 +72,63 @@ public class SourceMappingsService extends Service<SourceMappingsService.Options
}
private static Path getMappings(Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final MinecraftJarProcessorManager jarProcessor = MinecraftJarProcessorManager.create(project);
if (jarProcessor == null) {
LOGGER.info("No jar processor found, not creating source mappings, using project mappings");
return extension.getMappingConfiguration().tinyMappings;
}
final Path dir = extension.getFiles().getProjectPersistentCache().toPath().resolve("source_mappings");
final Path path = dir.resolve(jarProcessor.getSourceMappingsHash() + ".tiny");
if (Files.exists(path) && !extension.refreshDeps()) {
LOGGER.debug("Using cached source mappings");
return path;
}
LOGGER.info("Creating source mappings for hash {}", jarProcessor.getSourceMappingsHash());
try {
Files.createDirectories(dir);
Files.deleteIfExists(path);
createMappings(project, jarProcessor, path);
} catch (IOException e) {
throw new UncheckedIOException("Failed to create source mappings", e);
}
return path;
}
private static void createMappings(Project project, MinecraftJarProcessorManager jarProcessor, Path outputMappings) throws IOException {
LoomGradleExtension extension = LoomGradleExtension.get(project);
Path inputMappings = extension.getMappingConfiguration().tinyMappings;
MemoryMappingTree mappingTree = new MemoryMappingTree();
try (Reader reader = Files.newBufferedReader(inputMappings, StandardCharsets.UTF_8)) {
MappingReader.read(reader, new MappingSourceNsSwitch(mappingTree, MappingsNamespace.INTERMEDIARY.toString()));
} catch (IOException e) {
throw new RuntimeException("Failed to read mappings", e);
}
final List<GenerateSourcesTask.MappingsProcessor> mappingsProcessors = new ArrayList<>();
MinecraftJarProcessorManager minecraftJarProcessorManager = MinecraftJarProcessorManager.create(project);
if (minecraftJarProcessorManager != null) {
mappingsProcessors.add(mappings -> {
try (var serviceFactory = new ScopedServiceFactory()) {
final var configContext = new ConfigContextImpl(project, serviceFactory, extension);
return minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl(configContext));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
if (mappingsProcessors.isEmpty()) {
return inputMappings;
}
boolean transformed = false;
for (GenerateSourcesTask.MappingsProcessor mappingsProcessor : mappingsProcessors) {
if (mappingsProcessor.transform(mappingTree)) {
transformed = true;
GenerateSourcesTask.MappingsProcessor mappingsProcessor = mappings -> {
try (var serviceFactory = new ScopedServiceFactory()) {
final var configContext = new ConfigContextImpl(project, serviceFactory, extension);
return jarProcessor.processMappings(mappings, new MappingProcessorContextImpl(configContext));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
};
boolean transformed = mappingsProcessor.transform(mappingTree);
if (!transformed) {
return inputMappings;
}
final Path outputMappings;
try {
outputMappings = Files.createTempFile("loom-transitive-mappings", ".tiny");
} catch (IOException e) {
throw new RuntimeException("Failed to create temp file", e);
LOGGER.info("No mappings processors transformed the mappings");
}
try (Writer writer = Files.newBufferedWriter(outputMappings, StandardCharsets.UTF_8)) {
var tiny2Writer = new Tiny2FileWriter(writer, false);
mappingTree.accept(new MappingSourceNsSwitch(tiny2Writer, MappingsNamespace.NAMED.toString()));
} catch (IOException e) {
throw new RuntimeException("Failed to write mappings", e);
}
return outputMappings;
}
public SourceMappingsService(Options options, ServiceFactory serviceFactory) {

View File

@@ -211,7 +211,7 @@ public class ZipUtils {
}
public static <T> int transformJson(Class<T> typeOfT, Path zip, Map<String, UnsafeUnaryOperator<T>> transforms) throws IOException {
return transformMapped(zip, transforms, bytes -> LoomGradlePlugin.GSON.fromJson(new InputStreamReader(new ByteArrayInputStream(bytes)), typeOfT),
return transformMapped(zip, transforms, bytes -> LoomGradlePlugin.GSON.fromJson(new InputStreamReader(new ByteArrayInputStream(bytes), StandardCharsets.UTF_8), typeOfT),
s -> LoomGradlePlugin.GSON.toJson(s, typeOfT).getBytes(StandardCharsets.UTF_8));
}

View File

@@ -32,12 +32,17 @@ import org.gradle.api.Project;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency;
import org.gradle.api.internal.catalog.DelegatingProjectDependency;
import org.gradle.api.invocation.Gradle;
import org.gradle.api.provider.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.util.Constants;
public final class GradleUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(GradleUtils.class);
private GradleUtils() {
}
@@ -97,14 +102,29 @@ public final class GradleUtils {
// Get the project from the field with reflection to suppress the deprecation warning.
// If you hate it find a solution yourself and make a PR, I'm getting a bit tired of chasing Gradle updates
public static Project getDependencyProject(ProjectDependency projectDependency) {
try {
final Class<DefaultProjectDependency> clazz = DefaultProjectDependency.class;
final Field dependencyProject = clazz.getDeclaredField("dependencyProject");
dependencyProject.setAccessible(true);
return (Project) dependencyProject.get(projectDependency);
} catch (NoSuchFieldException | IllegalAccessException ignored) {
// Just fallback and trigger the warning, this will break in Gradle 9
return projectDependency.getDependencyProject();
if (projectDependency instanceof DefaultProjectDependency) {
try {
final Class<DefaultProjectDependency> clazz = DefaultProjectDependency.class;
final Field dependencyProject = clazz.getDeclaredField("dependencyProject");
dependencyProject.setAccessible(true);
return (Project) dependencyProject.get(projectDependency);
} catch (NoSuchFieldException | IllegalAccessException e) {
LOGGER.warn("Failed to reflect DefaultProjectDependency", e);
}
} else if (projectDependency instanceof DelegatingProjectDependency) {
try {
final Class<DelegatingProjectDependency> clazz = DelegatingProjectDependency.class;
final Field delgeate = clazz.getDeclaredField("delegate");
delgeate.setAccessible(true);
return getDependencyProject((ProjectDependency) delgeate.get(projectDependency));
} catch (NoSuchFieldException | IllegalAccessException e) {
LOGGER.warn("Failed to reflect DelegatingProjectDependency", e);
}
}
// Just fallback and trigger the warning, this will break in Gradle 9
final Project project = projectDependency.getDependencyProject();
LOGGER.warn("Loom was unable to suppress the deprecation warning for ProjectDependency#getDependencyProject, if you are on the latest version of Loom please report this issue to the Loom developers and provide the error above, this WILL stop working in a future Gradle version.");
return project;
}
}

View File

@@ -128,6 +128,7 @@ public final class SourceSetHelper {
final List<File> classpath = getGradleClasspath(reference, project);
classpath.addAll(getIdeaClasspath(reference, project));
classpath.addAll(getIdeaModuleCompileOutput(reference));
classpath.addAll(getEclipseClasspath(reference, project));
classpath.addAll(getVscodeClasspath(reference, project));
@@ -192,6 +193,25 @@ public final class SourceSetHelper {
return Collections.singletonList(outputDir);
}
private static List<File> getIdeaModuleCompileOutput(SourceSetReference reference) {
final File dotIdea = new File(reference.project().getRootDir(), ".idea");
if (!dotIdea.exists()) {
// Not an intellij project
return Collections.emptyList();
}
final String name = reference.sourceSet().getName();
final File projectDir = reference.project().getProjectDir();
final File outDir = new File(projectDir, "out");
final File sourceSetOutDir = new File(outDir, name.equals(SourceSet.MAIN_SOURCE_SET_NAME) ? "production" : name);
return List.of(
new File(sourceSetOutDir, "classes"),
new File(sourceSetOutDir, "resources")
);
}
@Nullable
private static String evaluateXpath(File file, @Language("xpath") String expression) {
final XPath xpath = XPathFactory.newInstance().newXPath();

View File

@@ -32,6 +32,7 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.gradle.api.Transformer;
import org.gradle.process.internal.JvmOptions;
import org.gradle.workers.internal.DaemonForkOptions;
import org.gradle.workers.internal.WorkerDaemonClientsManager;
@@ -45,7 +46,7 @@ public class WorkerDaemonClientsManagerHelper {
Transformer<List<Object>, List<Object>> transformer = workerDaemonClients -> {
for (Object /* WorkerDaemonClient */ client : workerDaemonClients) {
DaemonForkOptions forkOptions = getForkOptions(client);
Map<String, Object> systemProperties = forkOptions.getJavaForkOptions().getSystemProperties();
Map<String, Object> systemProperties = getSystemProperties(forkOptions);
if (systemProperties == null || !jvmMarkerValue.equals(systemProperties.get(MARKER_PROP))) {
// Not the JVM we are looking for
@@ -70,6 +71,30 @@ public class WorkerDaemonClientsManagerHelper {
return stopped.get();
}
private static Map<String, Object> getSystemProperties(DaemonForkOptions forkOptions) {
try {
Method getJavaForkOptionsMethod = forkOptions.getClass().getDeclaredMethod("getJavaForkOptions");
getJavaForkOptionsMethod.setAccessible(true);
Object /* JavaForkOptions */ javaForkOptions = getJavaForkOptionsMethod.invoke(forkOptions);
Method getSystemPropertiesMethod = javaForkOptions.getClass().getDeclaredMethod("getSystemProperties");
getSystemPropertiesMethod.setAccessible(true);
//noinspection unchecked
return (Map<String, Object>) getSystemPropertiesMethod.invoke(javaForkOptions);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
// Gradle 8.11 and below
}
// Gradle 8.12+
try {
Method getJvmOptions = forkOptions.getClass().getDeclaredMethod("getJvmOptions");
getJvmOptions.setAccessible(true);
JvmOptions jvmOptions = (JvmOptions) getJvmOptions.invoke(forkOptions);
return jvmOptions.getMutableSystemProperties();
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException("Failed to daemon system properties", e);
}
}
private static DaemonForkOptions getForkOptions(Object /* WorkerDaemonClient */ client) {
try {
Method getForkOptionsMethod = client.getClass().getDeclaredMethod("getForkOptions");

View File

@@ -29,6 +29,7 @@ import spock.lang.Unroll
import net.fabricmc.loom.test.util.GradleProjectTestTrait
import static net.fabricmc.loom.test.LoomTestConstants.PRE_RELEASE_GRADLE
import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
@@ -48,4 +49,16 @@ class SplitProjectTest extends Specification implements GradleProjectTestTrait {
where:
version << STANDARD_TEST_VERSIONS
}
@Unroll
def "genSources (gradle #version)"() {
setup:
def gradle = gradleProject(project: "splitSources", version: PRE_RELEASE_GRADLE)
when:
def result = gradle.run(tasks: ["genSources"])
then:
result.task(":genSources").outcome == SUCCESS
}
}

View File

@@ -37,17 +37,27 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class UnpickTest extends Specification implements GradleProjectTestTrait {
static final String MAPPINGS = "21w13a-net.fabricmc.yarn.21w13a.21w13a+build.30-v2"
def "unpick decompile"() {
def "unpick decompile #version #useCache"() {
setup:
def gradle = gradleProject(project: "unpick", version: version)
when:
def result = gradle.run(task: "genSources")
def result = gradle.run(tasks: useCache ? [
"genSourcesWithVineflower",
"--info"
] : [
"genSourcesWithVineflower",
"--no-use-cache",
"--info"
])
then:
result.task(":genSources").outcome == SUCCESS
result.task(":genSourcesWithVineflower").outcome == SUCCESS
getClassSource(gradle, "net/minecraft/block/CakeBlock.java").contains("Block.DEFAULT_SET_BLOCK_STATE_FLAG")
result.output.contains(useCache ? "Using decompile cache." : "Not using decompile cache.")
where:
version << STANDARD_TEST_VERSIONS
useCache << [true, false]
}
def "unpick build"() {

View File

@@ -0,0 +1,59 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 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.unit
import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
import org.gradle.api.internal.catalog.DelegatingProjectDependency
import org.gradle.api.internal.project.ProjectInternal
import spock.lang.Specification
import net.fabricmc.loom.util.gradle.GradleUtils
class GradleUtilsTest extends Specification {
def "get default project dependency"() {
given:
def project = Mock(ProjectInternal)
def dependency = new DefaultProjectDependency(project, false)
when:
def result = GradleUtils.getDependencyProject(dependency)
then:
result == project
}
def "get delegated project dependency"() {
given:
def project = Mock(ProjectInternal)
def dependency = new DefaultProjectDependency(project, true)
def delegate = new DelegatingProjectDependency(null, dependency)
when:
def result = GradleUtils.getDependencyProject(delegate)
then:
result == project
}
}