From d18c109e58aacb14fb322ca648c5f8523658e8e2 Mon Sep 17 00:00:00 2001 From: modmuss Date: Fri, 6 Sep 2024 23:13:10 +0100 Subject: [PATCH] More configuration cache support for IDE tasks (#1166) --- .../configuration/ide/idea/IdeaSyncTask.java | 73 +++++++++++++------ .../loom/task/GenEclipseRunsTask.java | 2 + .../loom/task/GenVsCodeProjectTask.java | 4 +- .../integration/ConfigurationCacheTest.groovy | 10 +-- 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java b/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java index 22619765a..d7eb67bdf 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java @@ -31,6 +31,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import javax.inject.Inject; @@ -42,10 +43,17 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.apache.commons.io.FileUtils; import org.gradle.api.Project; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Nested; +import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskAction; import org.jetbrains.annotations.VisibleForTesting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -58,33 +66,32 @@ import net.fabricmc.loom.util.Constants; public abstract class IdeaSyncTask extends AbstractLoomTask { + private static final Logger LOGGER = LoggerFactory.getLogger(IdeaSyncTask.class); + + @Nested + protected abstract ListProperty getIdeaRunConfigs(); + @Inject public IdeaSyncTask() { - // Always re-run this task. - getOutputs().upToDateWhen(element -> false); setGroup(Constants.TaskGroup.IDE); - - notCompatibleWithConfigurationCache("Not yet supported"); + getIdeaRunConfigs().set(getProject().provider(this::getRunConfigs)); } @TaskAction public void runTask() throws IOException { - File projectDir = getProject().getRootProject().file(".idea"); - projectDir.mkdirs(); - - generateRunConfigs(); + for (IntelijRunConfig config : getIdeaRunConfigs().get()) { + config.writeLaunchFile(); + } } // See: https://github.com/FabricMC/fabric-loom/pull/206#issuecomment-986054254 for the reason why XML's are still used to provide the run configs - private void generateRunConfigs() throws IOException { + private List getRunConfigs() throws IOException { Project rootProject = getProject().getRootProject(); LoomGradleExtension extension = LoomGradleExtension.get(getProject()); String projectPath = getProject() == rootProject ? "" : getProject().getPath().replace(':', '_'); File runConfigsDir = new File(rootProject.file(".idea"), "runConfigurations"); - if (!runConfigsDir.exists()) { - runConfigsDir.mkdirs(); - } + List configs = new ArrayList<>(); for (RunConfigSettings settings : extension.getRunConfigs()) { if (!settings.isIdeConfigGenerated()) { @@ -94,33 +101,53 @@ private void generateRunConfigs() throws IOException { RunConfig config = RunConfig.runConfig(getProject(), settings); String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_"); - File runConfigs = new File(runConfigsDir, name + projectPath + ".xml"); + File runConfigFile = new File(runConfigsDir, name + projectPath + ".xml"); String runConfigXml = config.fromDummy("idea_run_config_template.xml", true, getProject()); + final List excludedLibraryPaths = config.getExcludedLibraryPaths(getProject()); - if (!runConfigs.exists()) { - FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8); - } + IntelijRunConfig irc = getProject().getObjects().newInstance(IntelijRunConfig.class); + irc.getRunConfigXml().set(runConfigXml); + irc.getExcludedLibraryPaths().set(excludedLibraryPaths); + irc.getLaunchFile().set(runConfigFile); + } + + return configs; + } - settings.makeRunDir(); + public interface IntelijRunConfig { + @Input + Property getRunConfigXml(); - final List excludedLibraryPaths = config.getExcludedLibraryPaths(getProject()); + @Input + ListProperty getExcludedLibraryPaths(); + + @OutputFile + RegularFileProperty getLaunchFile(); + + default void writeLaunchFile() throws IOException { + Path launchFile = getLaunchFile().get().getAsFile().toPath(); + + if (Files.notExists(launchFile)) { + Files.createDirectories(launchFile.getParent()); + Files.writeString(launchFile, getRunConfigXml().get(), StandardCharsets.UTF_8); + } try { - setClasspathModifications(runConfigs.toPath(), excludedLibraryPaths); + setClasspathModifications(launchFile, getExcludedLibraryPaths().get()); } catch (Exception e) { - getProject().getLogger().error("Failed to modify run configuration xml", e); + LOGGER.error("Failed to modify run configuration xml", e); } } } - private void setClasspathModifications(Path runConfig, List exclusions) throws IOException { + private static void setClasspathModifications(Path runConfig, List exclusions) throws IOException { final String inputXml = Files.readString(runConfig, StandardCharsets.UTF_8); final String outputXml; try { outputXml = setClasspathModificationsInXml(inputXml, exclusions); } catch (Exception e) { - getLogger().error("Failed to modify idea xml", e); + LOGGER.error("Failed to modify idea xml", e); return; } diff --git a/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java b/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java index e0a688a3a..639461ac2 100644 --- a/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java @@ -48,6 +48,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfigSettings; +import net.fabricmc.loom.util.Constants; public abstract class GenEclipseRunsTask extends AbstractLoomTask { @Nested @@ -55,6 +56,7 @@ public abstract class GenEclipseRunsTask extends AbstractLoomTask { @Inject public GenEclipseRunsTask() { + setGroup(Constants.TaskGroup.IDE); getEclipseRunConfigs().set(getProject().provider(() -> getRunConfigs(getProject()))); } diff --git a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java index 8f15ea182..444f7e579 100644 --- a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java @@ -53,6 +53,7 @@ import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfigSettings; +import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.gradle.SyncTaskBuildService; // Recommended vscode plugin pack: @@ -70,10 +71,9 @@ public abstract class GenVsCodeProjectTask extends AbstractLoomTask { @Inject public GenVsCodeProjectTask() { + setGroup(Constants.TaskGroup.IDE); getLaunchConfigurations().set(getProject().provider(this::getConfigurations)); getLaunchJson().convention(getProject().getRootProject().getLayout().getProjectDirectory().file("vscode/launch.json")); - - notCompatibleWithConfigurationCache("Not yet supported"); } private List getConfigurations() { 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 79f444a20..1a1146f7a 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/ConfigurationCacheTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/ConfigurationCacheTest.groovy @@ -47,8 +47,8 @@ class ConfigurationCacheTest extends Specification implements GradleProjectTestT } """.stripIndent() when: - def result = gradle.run(task: task, configurationCache: true, isloatedProjects: false) - def result2 = gradle.run(task: task, configurationCache: true, isloatedProjects: false) + def result = gradle.run(task: task, isloatedProjects: false) + def result2 = gradle.run(task: task, isloatedProjects: false) then: result.task(":${task}").outcome != FAILED @@ -97,10 +97,10 @@ class ConfigurationCacheTest extends Specification implements GradleProjectTestT fabricModJson.text = fmj("1.0.0") when: - def result = gradle.run(task: "testTask", configurationCache: true) - def result2 = gradle.run(task: "testTask", configurationCache: true) + def result = gradle.run(task: "testTask") + def result2 = gradle.run(task: "testTask") fabricModJson.text = fmj("2.0.0") - def result3 = gradle.run(task: "testTask", configurationCache: true) + def result3 = gradle.run(task: "testTask") then: // Test that the cache is created