From 31375d401ffc4bf7375b44068c2e07b25e8297f0 Mon Sep 17 00:00:00 2001 From: John Diamond Date: Tue, 2 Jun 2026 18:54:15 +0100 Subject: [PATCH 1/2] Prevent gradle from skipping the IDE hook task due to cached results --- .../spotless/SpotlessExtensionImpl.java | 7 +++++ .../diffplug/gradle/spotless/IdeHookTest.java | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+) 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 173b5a1113..34dfa13fd4 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 @@ -66,6 +66,13 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) { task.getIdeHookState().set(ideHook); // clean removes the SpotlessCache, so we have to run after clean task.mustRunAfter(BasePlugin.CLEAN_TASK_NAME); + if (ideHook.paths != null) { + // The IDE hook never writes to the declared outputs so Gradle's UP-TO-DATE check would incorrectly + // skip the task when the user reverts a file or when useStdOut is active. + task.getOutputs().upToDateWhen(t -> false); + // also disable the build cache + task.getOutputs().cacheIf("IDE hook always reruns", t -> false); + } }); project.afterEvaluate(unused -> spotlessTask.configure(task -> { // now that the task is being configured, we execute our actions 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 da24a97d1a..bf481d52a4 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 @@ -119,6 +119,33 @@ void dirty(boolean configurationCache) throws IOException { Assertions.assertThat(error).startsWith("IS DIRTY"); } + @ParameterizedTest + @MethodSource("configurationCacheProvider") + void dirtyCalledTwiceWithStdOut(boolean configurationCache) throws IOException { + // Make sure gradle doesn't cache the output of the first call, since it must be written to stdout again + runWith(configurationCache, "spotlessApply", "--quiet", "-PspotlessIdeHook=" + dirty.getAbsolutePath(), "-PspotlessIdeHookUseStdOut"); + Assertions.assertThat(output).isEqualTo("abc"); + Assertions.assertThat(error).startsWith("IS DIRTY"); + + runWith(configurationCache, "spotlessApply", "--quiet", "-PspotlessIdeHook=" + dirty.getAbsolutePath(), "-PspotlessIdeHookUseStdOut"); + Assertions.assertThat(output).isEqualTo("abc"); + Assertions.assertThat(error).startsWith("IS DIRTY"); + } + + @ParameterizedTest + @MethodSource("configurationCacheProvider") + void dirtyCalledTwiceAfterRevert(boolean configurationCache) throws IOException { + // Make sure Gradle doesn't skip writing to the file just because it was already dirty in the previous run + // - the content may have been reverted in between + runWith(configurationCache, "spotlessApply", "--quiet", "-PspotlessIdeHook=" + dirty.getAbsolutePath()); + Assertions.assertThat(error).startsWith("IS DIRTY"); + + Files.write("ABC".getBytes(StandardCharsets.UTF_8), dirty); + + runWith(configurationCache, "spotlessApply", "--quiet", "-PspotlessIdeHook=" + dirty.getAbsolutePath()); + Assertions.assertThat(error).startsWith("IS DIRTY"); + } + @ParameterizedTest @MethodSource("configurationCacheProvider") void clean(boolean configurationCache) throws IOException { From 2d82ce3548c51060dc64c8716f7d9f1bb994c37d Mon Sep 17 00:00:00 2001 From: John Diamond Date: Tue, 2 Jun 2026 20:32:15 +0100 Subject: [PATCH 2/2] Update CHANGES.md --- plugin-gradle/CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index a6492a83f4..dbd8c95491 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -4,6 +4,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] +### Fixed +- Prevent build caches from interfering when executing under the `-PspotlessIdeHook` mode. ([#2365](https://github.com/diffplug/spotless/issues/2365)) + ## [8.6.0] - 2026-05-27 ### Added - Add `cacheDirectory(...)` to `eclipse()`, `eclipseCdt()`, and `greclipse()`; the default P2 cache is `$GRADLE_USER_HOME/caches/p2-data`. ([#2944](https://github.com/diffplug/spotless/pull/2944))