From 5f52e1232f94a0210693bd52d6913ef5579714f3 Mon Sep 17 00:00:00 2001 From: modmuss Date: Mon, 12 Aug 2024 13:12:29 +0100 Subject: [PATCH] Configuration cache support for SourceSetHelper.findFileInResource (#1158) * Configuration cache support for SourceSetHelper.findFileInResource * Prove that config cache is working * Misc improvements * Fix tests on windows --- .../loom/extension/LoomFilesBaseImpl.java | 6 +- .../loom/util/gradle/GradleUtils.java | 10 +++ .../loom/util/gradle/SourceSetHelper.java | 10 ++- .../integration/ConfigurationCacheTest.groovy | 72 +++++++++++++++++++ 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/extension/LoomFilesBaseImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomFilesBaseImpl.java index 8b23e4f9..7dd74d5c 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomFilesBaseImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomFilesBaseImpl.java @@ -40,11 +40,7 @@ public abstract class LoomFilesBaseImpl implements LoomFiles { private static File createFile(File parent, String child) { File file = new File(parent, child); - - if (!file.exists()) { - file.mkdirs(); - } - + file.mkdirs(); return file; } diff --git a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java index dbe91442..1166bc21 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java @@ -24,9 +24,11 @@ package net.fabricmc.loom.util.gradle; +import java.io.File; import java.util.function.Consumer; import org.gradle.api.Project; +import org.gradle.api.file.RegularFileProperty; import org.gradle.api.invocation.Gradle; import org.gradle.api.provider.Provider; @@ -78,4 +80,12 @@ public final class GradleUtils { public static boolean getBooleanProperty(Project project, String key) { return getBooleanPropertyProvider(project, key).getOrElse(false); } + + // A hack to include the given file in the configuration cache input + // this ensures that configuration cache is invalidated when the file changes + public static File configurationInputFile(Project project, File file) { + final RegularFileProperty property = project.getObjects().fileProperty(); + property.set(file); + return property.getAsFile().get(); + } } diff --git a/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java b/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java index b693a8a0..d17b3cbc 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/SourceSetHelper.java @@ -241,8 +241,14 @@ public final class SourceSetHelper { final LoomGradleExtension extension = LoomGradleExtension.get(project); if (extension.isConfigurationCacheActive()) { - // TODO config cache, figure this out - project.getLogger().warn("Unable to find resource ({}) in source set ({}) when configuration cache is active", path, sourceSet.getName()); + for (File rootDir: sourceSet.getResources().getSrcDirs()) { + final File file = GradleUtils.configurationInputFile(project, new File(rootDir, path)); + + if (file.exists()) { + return file; + } + } + return null; } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/ConfigurationCacheTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/ConfigurationCacheTest.groovy index a6af3e2d..bcd9ea88 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/ConfigurationCacheTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/ConfigurationCacheTest.groovy @@ -30,6 +30,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.FAILED class ConfigurationCacheTest extends Specification implements GradleProjectTestTrait { @@ -60,4 +61,75 @@ class ConfigurationCacheTest extends Specification implements GradleProjectTestT "jar" | _ "check" | _ } + + // Test GradleUtils.configurationInputFile invalidates the cache when the file changes + @Unroll + def "File input (#version)"() { + setup: + def gradle = gradleProject(project: "minimalBase", version: version) + gradle.buildGradle << """ + dependencies { + minecraft 'com.mojang:minecraft:1.20.4' + mappings 'net.fabricmc:yarn:1.20.4+build.3:v2' + modImplementation 'net.fabricmc:fabric-loader:0.15.6' + } + + abstract class TestTask extends DefaultTask { + @Input + abstract Property getModVersion() + + @TaskAction + void run() { + println "Version: " + modVersion.get() + } + } + + println "Configuring task testTask" + tasks.register('testTask', TestTask) { + modVersion.set(loom.getModVersion()) // loom.getModVersion() returns a String + } + """.stripIndent() + + def fabricModJson = new File(gradle.projectDir, "src/main/resources/fabric.mod.json") + fabricModJson.parentFile.mkdirs() + fabricModJson.text = fmj("1.0.0") + + when: + def result = gradle.run(task: "testTask", configurationCache: true) + def result2 = gradle.run(task: "testTask", configurationCache: true) + fabricModJson.text = fmj("2.0.0") + def result3 = gradle.run(task: "testTask", configurationCache: true) + + then: + // Test that the cache is created + result.task(":testTask").outcome != FAILED + result.output.contains("Calculating task graph as no cached configuration is available for tasks: testTask") + result.output.contains("Configuring task testTask") + result.output.contains("Version: 1.0.0") + + // Test that the cache is reused when nothing has changed + result2.task(":testTask").outcome != FAILED + !result2.output.contains("Calculating task graph") + !result2.output.contains("Configuring task testTask") + result2.output.contains("Version: 1.0.0") + + // Test that the cache is invalidated when the file changes + result3.task(":testTask").outcome != FAILED + result3.output.contains("Calculating task graph as configuration cache cannot be reused because file 'src/main/resources/fabric.mod.json' has changed.".replace("/", File.separator)) + result3.output.contains("Configuring task testTask") + result3.output.contains("Version: 2.0.0") + + where: + version << STANDARD_TEST_VERSIONS + } + + static def fmj(String version) { + return """ + { + "schemaVersion": 1, + "id": "test", + "version": "${version}" + } + """ + } }