diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java deleted file mode 100644 index cc767ce111..0000000000 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2016-2024 DiffPlug - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.diffplug.gradle.spotless; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -import com.diffplug.common.base.Errors; -import com.diffplug.common.io.ByteStreams; -import com.diffplug.spotless.DirtyState; -import com.diffplug.spotless.Formatter; - -class IdeHook { - final static String PROPERTY = "spotlessIdeHook"; - final static String USE_STD_IN = "spotlessIdeHookUseStdIn"; - final static String USE_STD_OUT = "spotlessIdeHookUseStdOut"; - - private static void dumpIsClean() { - System.err.println("IS CLEAN"); - } - - static void performHook(SpotlessTaskImpl spotlessTask) { - String path = (String) spotlessTask.getProject().property(PROPERTY); - File file = new File(path); - if (!file.isAbsolute()) { - System.err.println("Argument passed to " + PROPERTY + " must be an absolute path"); - return; - } - if (spotlessTask.getTarget().contains(file)) { - GitRatchetGradle ratchet = spotlessTask.getRatchet(); - try (Formatter formatter = spotlessTask.buildFormatter()) { - if (ratchet != null) { - if (ratchet.isClean(spotlessTask.getProjectDir().get().getAsFile(), spotlessTask.getRootTreeSha(), file)) { - dumpIsClean(); - return; - } - } - byte[] bytes; - if (spotlessTask.getProject().hasProperty(USE_STD_IN)) { - bytes = ByteStreams.toByteArray(System.in); - } else { - bytes = Files.readAllBytes(file.toPath()); - } - DirtyState dirty = DirtyState.of(formatter, file, bytes); - if (dirty.isClean()) { - dumpIsClean(); - } else if (dirty.didNotConverge()) { - System.err.println("DID NOT CONVERGE"); - System.err.println("Run 'spotlessDiagnose' for details https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md"); - } else { - System.err.println("IS DIRTY"); - if (spotlessTask.getProject().hasProperty(USE_STD_OUT)) { - dirty.writeCanonicalTo(System.out); - } else { - dirty.writeCanonicalTo(file); - } - } - } catch (IOException e) { - e.printStackTrace(System.err); - throw Errors.asRuntime(e); - } finally { - System.err.close(); - System.out.close(); - } - } - } -} diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java index 96474ffc4b..61508beba1 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ public class SpotlessExtensionImpl extends SpotlessExtension { final TaskProvider rootCheckTask, rootApplyTask, rootDiagnoseTask; + final static String PROPERTY = "spotlessIdeHook"; + public SpotlessExtensionImpl(Project project) { super(project); rootCheckTask = project.getTasks().register(EXTENSION + CHECK, task -> { @@ -48,15 +50,14 @@ public SpotlessExtensionImpl(Project project) { @Override protected void createFormatTasks(String name, FormatExtension formatExtension) { - boolean isIdeHook = project.hasProperty(IdeHook.PROPERTY); TaskContainer tasks = project.getTasks(); + String ideHookPath = (String) project.findProperty(PROPERTY); // create the SpotlessTask String taskName = EXTENSION + SpotlessPlugin.capitalize(name); TaskProvider spotlessTask = tasks.register(taskName, SpotlessTaskImpl.class, task -> { task.init(getRegisterDependenciesTask().getTaskService()); task.setGroup(TASK_GROUP); - task.setEnabled(!isIdeHook); // clean removes the SpotlessCache, so we have to run after clean task.mustRunAfter(BasePlugin.CLEAN_TASK_NAME); }); @@ -68,6 +69,12 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) { } // and now we'll setup the task formatExtension.setupTask(task); + if (ideHookPath != null) { + var ideHookFile = project.file(ideHookPath); + task.setEnabled(task.getTarget().contains(ideHookFile)); + var newTarget = task.getTarget().filter(ideHookFile::equals); + task.setTarget(newTarget); + } }); }); @@ -75,25 +82,19 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) { TaskProvider applyTask = tasks.register(taskName + APPLY, SpotlessApply.class, task -> { task.init(spotlessTask.get()); task.setGroup(TASK_GROUP); - task.setEnabled(!isIdeHook); task.dependsOn(spotlessTask); + task.setEnabled(spotlessTask.get().getEnabled()); }); rootApplyTask.configure(task -> { task.dependsOn(applyTask); - - if (isIdeHook) { - // the rootApplyTask is no longer just a marker task, now it does a bit of work itself - task.doLast(unused -> IdeHook.performHook(spotlessTask.get())); - } }); TaskProvider checkTask = tasks.register(taskName + CHECK, SpotlessCheck.class, task -> { SpotlessTaskImpl source = spotlessTask.get(); task.setGroup(TASK_GROUP); task.init(source); - task.setEnabled(!isIdeHook); task.dependsOn(source); - + task.setEnabled(spotlessTask.get().getEnabled()); // if the user runs both, make sure that apply happens first, task.mustRunAfter(applyTask); }); diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/IdeHookTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/IdeHookTest.java index f28b9f9820..553911558d 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/IdeHookTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/IdeHookTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,95 +15,37 @@ */ package com.diffplug.gradle.spotless; -import java.io.File; import java.io.IOException; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.diffplug.common.base.StringPrinter; -import com.diffplug.common.io.Files; - class IdeHookTest extends GradleIntegrationHarness { - private String output, error; - private File dirty, clean, diverge, outofbounds; - - @BeforeEach - void before() throws IOException { + @Test + void ideHookOnlyChangeSpecificFile() throws IOException { setFile("build.gradle").toLines( - "plugins {", - " id 'com.diffplug.spotless'", - "}", + "plugins { id 'com.diffplug.spotless' }", "spotless {", - " format 'misc', {", - " target 'DIRTY.md', 'CLEAN.md'", - " custom 'lowercase', { str -> str.toLowerCase(Locale.ROOT) }", - " }", - " format 'diverge', {", - " target 'DIVERGE.md'", - " custom 'diverge', { str -> str + ' ' }", + " format 'toLower', {", + " target '**/*.md'", + " custom 'lowercase', { str -> str.toLowerCase() }", " }", "}"); - dirty = new File(rootFolder(), "DIRTY.md"); - Files.write("ABC".getBytes(StandardCharsets.UTF_8), dirty); - clean = new File(rootFolder(), "CLEAN.md"); - Files.write("abc".getBytes(StandardCharsets.UTF_8), clean); - diverge = new File(rootFolder(), "DIVERGE.md"); - Files.write("ABC".getBytes(StandardCharsets.UTF_8), diverge); - outofbounds = new File(rootFolder(), "OUTOFBOUNDS.md"); - Files.write("ABC".getBytes(StandardCharsets.UTF_8), outofbounds); - } - - private void runWith(String... arguments) throws IOException { - StringBuilder output = new StringBuilder(); - StringBuilder error = new StringBuilder(); - try (Writer outputWriter = new StringPrinter(output::append).toWriter(); - Writer errorWriter = new StringPrinter(error::append).toWriter();) { - gradleRunner() - .withArguments(arguments) - .forwardStdOutput(outputWriter) - .forwardStdError(errorWriter) - .build(); - } - this.output = output.toString(); - this.error = error.toString(); - } - - @Test - void dirty() throws IOException { - runWith("spotlessApply", "--quiet", "-PspotlessIdeHook=" + dirty.getAbsolutePath(), "-PspotlessIdeHookUseStdOut"); - Assertions.assertThat(output).isEqualTo("abc"); - Assertions.assertThat(error).startsWith("IS DIRTY"); - } - - @Test - void clean() throws IOException { - runWith("spotlessApply", "--quiet", "-PspotlessIdeHook=" + clean.getAbsolutePath(), "-PspotlessIdeHookUseStdOut"); - Assertions.assertThat(output).isEmpty(); - Assertions.assertThat(error).startsWith("IS CLEAN"); - } - - @Test - void diverge() throws IOException { - runWith("spotlessApply", "--quiet", "-PspotlessIdeHook=" + diverge.getAbsolutePath(), "-PspotlessIdeHookUseStdOut"); - Assertions.assertThat(output).isEmpty(); - Assertions.assertThat(error).startsWith("DID NOT CONVERGE"); - } - - @Test - void outofbounds() throws IOException { - runWith("spotlessApply", "--quiet", "-PspotlessIdeHook=" + outofbounds.getAbsolutePath(), "-PspotlessIdeHookUseStdOut"); - Assertions.assertThat(output).isEmpty(); - Assertions.assertThat(error).isEmpty(); - } - - @Test - void notAbsolute() throws IOException { - runWith("spotlessApply", "--quiet", "-PspotlessIdeHook=build.gradle", "-PspotlessIdeHookUseStdOut"); - Assertions.assertThat(output).isEmpty(); - Assertions.assertThat(error).contains("Argument passed to spotlessIdeHook must be an absolute path"); + String content = "// Generated by Mr. Roboto, do not edit.\n" + + "A B C\n" + + "D E F\n" + + "G H I"; + setFile("test_generated.md").toContent(content); + setFile("test_manual.md").toLines( + "A B C", + "D E F", + "G H I"); + gradleRunner().withArguments("spotlessApply", "-PspotlessIdeHook=test_manual.md").build(); + // `test_generated` contains the excluding text so didn't change. + assertFile("test_generated.md").hasContent(content); + // `test_manual` does not so it changed. + assertFile("test_manual.md").hasLines( + "a b c", + "d e f", + "g h i"); } }