From c3a8c822cadff1f0ff453e9a0647fd7d0da95c3f Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 2 Jan 2025 17:44:49 -0800 Subject: [PATCH 01/12] Gradle custom step test now runs with and without configuration cache. --- ...umpThisNumberIfACustomStepChangesTest.java | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java index 25a6b18bca..dbcb2cf720 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,39 @@ import java.io.IOException; +import org.gradle.testkit.runner.GradleRunner; import org.junit.jupiter.api.Test; -class BumpThisNumberIfACustomStepChangesTest extends GradleIntegrationHarness { +abstract class BumpThisNumberIfACustomStepChangesTest extends GradleIntegrationHarness { + private boolean useConfigCache; + + BumpThisNumberIfACustomStepChangesTest(boolean useConfigCache) { + this.useConfigCache = useConfigCache; + } + + static class WithConfigCache extends BumpThisNumberIfACustomStepChangesTest { + WithConfigCache() { + super(true); + } + } + + static class WithoutConfigCache extends BumpThisNumberIfACustomStepChangesTest { + WithoutConfigCache() { + super(false); + } + } + + @Override + public GradleRunner gradleRunner() throws IOException { + if (useConfigCache) { + setFile("gradle.properties").toLines("org.gradle.unsafe.configuration-cache=true", + "org.gradle.configuration-cache=true"); + return super.gradleRunner().withGradleVersion(GradleVersionSupport.CONFIGURATION_CACHE.version); + } else { + return super.gradleRunner(); + } + } + private void writeBuildFile(String toInsert) throws IOException { setFile("build.gradle").toLines( "plugins {", @@ -50,7 +80,12 @@ void customRuleNeverUpToDate() throws IOException { writeContentWithBadFormatting(); applyIsUpToDate(false); checkIsUpToDate(false); - checkIsUpToDate(false); + if (useConfigCache) { + // if the config cache is in-effect, then it's okay for custom rules to become "up-to-date" + checkIsUpToDate(true); + } else { + checkIsUpToDate(false); + } } @Test From 3572a5e8625702add941ad9e3790a1e1efaf01a3 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 2 Jan 2025 17:46:49 -0800 Subject: [PATCH 02/12] Using `custom` in a gradle script now works with and without the configuration cache. --- .../diffplug/gradle/spotless/FormatExtension.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 59898cbf56..69150724c1 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -457,12 +457,11 @@ protected Integer calculateState() throws Exception { */ public void custom(String name, Closure formatter) { requireNonNull(formatter, "formatter"); - Closure dehydrated = formatter.dehydrate(); - custom(name, new ClosureFormatterFunc(dehydrated)); + custom(name, new ClosureFormatterFunc(formatter)); } static class ClosureFormatterFunc implements FormatterFunc, Serializable { - private final Closure closure; + private Closure closure; ClosureFormatterFunc(Closure closure) { this.closure = closure; @@ -472,6 +471,14 @@ static class ClosureFormatterFunc implements FormatterFunc, Serializable { public String apply(String unixNewlines) { return closure.call(unixNewlines); } + + private void writeObject(java.io.ObjectOutputStream stream) throws java.io.IOException { + stream.writeObject(closure.dehydrate()); + } + + private void readObject(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException { + this.closure = (Closure) stream.readObject(); + } } /** From 1b7189df71560e1b3fe85e2586d2ae26a2c3fabb Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 2 Jan 2025 17:50:15 -0800 Subject: [PATCH 03/12] Update changelog. --- plugin-gradle/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index cd77663c4d..54e21d250c 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -11,6 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `ktlint` version to latest `1.4.0` -> `1.5.0`. ([#2354](https://github.com/diffplug/spotless/pull/2354)) * Bump minimum `eclipse-cdt` version to `11.0` (removed support for `10.7`). ([#2373](https://github.com/diffplug/spotless/pull/2373)) ### Fixed +* Using `custom` with a Groovy closure now works with and without configuration cache. ([#2376](https://github.com/diffplug/spotless/pull/2376)) * `toggleOffOn` now works with the configuration cache. ([#2378](https://github.com/diffplug/spotless/pull/2378) fixes [#2317](https://github.com/diffplug/spotless/issues/2317)) * You can now use `removeUnusedImports` and `googleJavaFormat` at the same time again. (fixes [#2159](https://github.com/diffplug/spotless/issues/2159)) * The default list of type annotations used by `formatAnnotations` now includes Jakarta Validation's `Valid` and constraints validations (fixes [#2334](https://github.com/diffplug/spotless/issues/2334)) From 9c9cac01a1fa27e214094814a8ce046170655846 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 08:37:58 -0800 Subject: [PATCH 04/12] If we undo the fix from #2378, then the custom steps work. Ugh. --- .../com/diffplug/spotless/ConfigurationCacheHackList.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java b/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java index 52479bf6ae..520eab3f39 100644 --- a/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java +++ b/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java @@ -16,7 +16,6 @@ package com.diffplug.spotless; import java.io.IOException; -import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -61,7 +60,7 @@ private void writeObject(java.io.ObjectOutputStream out) throws IOException { for (Object obj : backingList) { // if write out the list on its own, we'll get java's non-deterministic object-graph serialization // by writing each object to raw bytes independently, we avoid this - out.writeObject(LazyForwardingEquality.toBytes((Serializable) obj)); + out.writeObject(obj); } } @@ -71,7 +70,7 @@ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassN backingList = new ArrayList<>(); int size = in.readInt(); for (int i = 0; i < size; i++) { - backingList.add(LazyForwardingEquality.fromBytes((byte[]) in.readObject())); + backingList.add(in.readObject()); } } From e5a6f2be41bf6c5c1f3c317fd77d3d111dfa4b5a Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 08:55:21 -0800 Subject: [PATCH 05/12] Turn off the error message for requiring a certain version to use a custom step, let CI tell us how it goes. --- .../com/diffplug/gradle/spotless/FormatExtension.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 69150724c1..340953c15d 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -16,8 +16,6 @@ package com.diffplug.gradle.spotless; import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull; -import static com.diffplug.gradle.spotless.SpotlessPluginRedirect.badSemver; -import static com.diffplug.gradle.spotless.SpotlessPluginRedirect.badSemverOfGradle; import static java.util.Objects.requireNonNull; import java.io.File; @@ -46,7 +44,6 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.tasks.TaskProvider; -import org.gradle.util.GradleVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -487,12 +484,6 @@ private void readObject(java.io.ObjectInputStream stream) throws java.io.IOExcep */ public void custom(String name, FormatterFunc formatter) { requireNonNull(formatter, "formatter"); - if (badSemverOfGradle() < badSemver(SpotlessPlugin.VER_GRADLE_minVersionForCustom)) { - throw new GradleException("The 'custom' method is only available if you are using Gradle " - + SpotlessPlugin.VER_GRADLE_minVersionForCustom - + " or newer, this is " - + GradleVersion.current().getVersion()); - } addStep(FormatterStep.createLazy(name, () -> globalState, SerializedFunction.alwaysReturns(formatter))); } From 168e5978bf4036893500115ca34acf38034fed49 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 09:34:50 -0800 Subject: [PATCH 06/12] Add a sentinel step which triggers the "serialize to byte array hack" --- .../spotless/ConfigurationCacheHackList.java | 25 +++++++++-- .../yaml/SerializeToByteArrayHack.java | 42 +++++++++++++++++++ .../combined/CombinedJavaFormatStepTest.java | 4 +- 3 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java diff --git a/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java b/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java index 520eab3f39..39be0d9559 100644 --- a/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java +++ b/lib/src/main/java/com/diffplug/spotless/ConfigurationCacheHackList.java @@ -16,11 +16,14 @@ package com.diffplug.spotless; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; +import com.diffplug.spotless.yaml.SerializeToByteArrayHack; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** @@ -50,27 +53,43 @@ * to make Spotless work with all of Gradle's cache systems at once. */ public class ConfigurationCacheHackList implements java.io.Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 6914178791997323870L; + private boolean optimizeForEquality; private ArrayList backingList = new ArrayList<>(); + private boolean shouldWeSerializeToByteArrayFirst() { + return backingList.stream().anyMatch(step -> step instanceof SerializeToByteArrayHack); + } + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + boolean serializeToByteArrayFirst = shouldWeSerializeToByteArrayFirst(); + out.writeBoolean(serializeToByteArrayFirst); out.writeBoolean(optimizeForEquality); out.writeInt(backingList.size()); for (Object obj : backingList) { // if write out the list on its own, we'll get java's non-deterministic object-graph serialization // by writing each object to raw bytes independently, we avoid this - out.writeObject(obj); + if (serializeToByteArrayFirst) { + out.writeObject(LazyForwardingEquality.toBytes((Serializable) obj)); + } else { + out.writeObject(obj); + } } } @SuppressFBWarnings("MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT") private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + boolean serializeToByteArrayFirst = in.readBoolean(); optimizeForEquality = in.readBoolean(); backingList = new ArrayList<>(); int size = in.readInt(); for (int i = 0; i < size; i++) { - backingList.add(in.readObject()); + if (serializeToByteArrayFirst) { + backingList.add(LazyForwardingEquality.fromBytes((byte[]) in.readObject())); + } else { + backingList.add(in.readObject()); + } } } diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java b/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java new file mode 100644 index 0000000000..42d21c8997 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java @@ -0,0 +1,42 @@ +/* + * Copyright 2025 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.spotless.yaml; + +import java.io.File; + +import javax.annotation.Nullable; + +import com.diffplug.spotless.FormatterStep; + +public class SerializeToByteArrayHack implements FormatterStep { + private static final long serialVersionUID = 8071047581828362545L; + + @Override + public String getName() { + return "hack to force serializing objects to byte array"; + } + + @Nullable + @Override + public String format(String rawUnix, File file) throws Exception { + return null; + } + + @Override + public void close() throws Exception { + + } +} diff --git a/testlib/src/test/java/com/diffplug/spotless/combined/CombinedJavaFormatStepTest.java b/testlib/src/test/java/com/diffplug/spotless/combined/CombinedJavaFormatStepTest.java index 8d91d7ca6e..086103ce15 100644 --- a/testlib/src/test/java/com/diffplug/spotless/combined/CombinedJavaFormatStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/combined/CombinedJavaFormatStepTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 DiffPlug + * Copyright 2023-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import com.diffplug.spotless.java.GoogleJavaFormatStep; import com.diffplug.spotless.java.ImportOrderStep; import com.diffplug.spotless.java.RemoveUnusedImportsStep; +import com.diffplug.spotless.yaml.SerializeToByteArrayHack; public class CombinedJavaFormatStepTest extends ResourceHarness { @@ -45,6 +46,7 @@ void checkIssue1679() { FenceStep toggleOffOnPair = FenceStep.named(FenceStep.defaultToggleName()).openClose("formatting:off", "formatting:on"); try (StepHarness formatter = StepHarness.forSteps( toggleOffOnPair.preserveWithin(List.of( + new SerializeToByteArrayHack(), gjf, indentWithSpaces, importOrder, From e398c35b7fab516e70b7a325090811545eb4f43a Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 10:04:31 -0800 Subject: [PATCH 07/12] Yup, custom still needs Gradle 8.0+, bring that back. --- .../com/diffplug/gradle/spotless/FormatExtension.java | 9 +++++++++ .../spotless/BumpThisNumberIfACustomStepChangesTest.java | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 340953c15d..69150724c1 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -16,6 +16,8 @@ package com.diffplug.gradle.spotless; import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull; +import static com.diffplug.gradle.spotless.SpotlessPluginRedirect.badSemver; +import static com.diffplug.gradle.spotless.SpotlessPluginRedirect.badSemverOfGradle; import static java.util.Objects.requireNonNull; import java.io.File; @@ -44,6 +46,7 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.tasks.TaskProvider; +import org.gradle.util.GradleVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -484,6 +487,12 @@ private void readObject(java.io.ObjectInputStream stream) throws java.io.IOExcep */ public void custom(String name, FormatterFunc formatter) { requireNonNull(formatter, "formatter"); + if (badSemverOfGradle() < badSemver(SpotlessPlugin.VER_GRADLE_minVersionForCustom)) { + throw new GradleException("The 'custom' method is only available if you are using Gradle " + + SpotlessPlugin.VER_GRADLE_minVersionForCustom + + " or newer, this is " + + GradleVersion.current().getVersion()); + } addStep(FormatterStep.createLazy(name, () -> globalState, SerializedFunction.alwaysReturns(formatter))); } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java index dbcb2cf720..25ed3cab8b 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/BumpThisNumberIfACustomStepChangesTest.java @@ -44,7 +44,7 @@ public GradleRunner gradleRunner() throws IOException { if (useConfigCache) { setFile("gradle.properties").toLines("org.gradle.unsafe.configuration-cache=true", "org.gradle.configuration-cache=true"); - return super.gradleRunner().withGradleVersion(GradleVersionSupport.CONFIGURATION_CACHE.version); + return super.gradleRunner().withGradleVersion(GradleVersionSupport.CUSTOM_STEPS.version); } else { return super.gradleRunner(); } From 04cc97253bd5c9cbc426762feff92b51295b030d Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 10:28:12 -0800 Subject: [PATCH 08/12] Bump the req for `custom` from `8.0` to `8.4` --- .../java/com/diffplug/gradle/spotless/SpotlessPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java index 8b58e3eaca..24bea9d90b 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ public class SpotlessPlugin implements Plugin { static final String SPOTLESS_MODERN = "spotlessModern"; static final String VER_GRADLE_min = "6.1.1"; static final String VER_GRADLE_javaPluginExtension = "7.1"; - static final String VER_GRADLE_minVersionForCustom = "8.0"; + static final String VER_GRADLE_minVersionForCustom = "8.4"; private static final int MINIMUM_JRE = 11; @Override From 0c66cb027d4d190ae27676ed04afe0327c348c07 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 11:45:35 -0800 Subject: [PATCH 09/12] Zero-out the global .gitconfig to fix issue which is only happening on Java 11? --- .../com/diffplug/spotless/extra/GitAttributesLineEndings.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java index 93a95bd6ac..cf4432f2f1 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -193,6 +193,7 @@ static class RuntimeInit { ///////////////////////////////// // USER AND SYSTEM-WIDE VALUES // ///////////////////////////////// + FS.DETECTED.setGitSystemConfig(new File("no-global-git-config-for-spotless")); systemConfig = SystemReader.getInstance().openSystemConfig(null, FS.DETECTED); Errors.log().run(systemConfig::load); userConfig = SystemReader.getInstance().openUserConfig(systemConfig, FS.DETECTED); From 7408f384d9b2e0633c163ea6eba2705888784776 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 12:44:45 -0800 Subject: [PATCH 10/12] Add docs for the `SerializeToByteArrayHack`. --- .../spotless/yaml/SerializeToByteArrayHack.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java b/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java index 42d21c8997..c63b6d918b 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/SerializeToByteArrayHack.java @@ -21,6 +21,21 @@ import com.diffplug.spotless.FormatterStep; +/** + * This step is a flag which marks that `ConfigurationCacheHackList` should + * serialize each item individually into `byte[]` array, rather than using normal + * serialization. + * + * The reason to use this is if you are using `toggleOffOn` *and* two kinds of + * google-java-format (e.g. one for format and the other for imports), then + * problems with Java's handling of object graphs will cause your up-to-date checks + * to always fail. `CombinedJavaFormatStepTest` recreates this situation. By adding + * this step, it will trigger this workaround which fixes the up-to-dateness bug. + * + * But, turning it on will break all `custom` steps that use Groovy closures. So + * by default you get regular serialization. If you're using `toggleOffOn` and having + * problems with up-to-dateness, then adding this step can be a workaround. + */ public class SerializeToByteArrayHack implements FormatterStep { private static final long serialVersionUID = 8071047581828362545L; From 922c7ea4ced2347587fa7c1884c5b35f7e3cf3e3 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 12:46:27 -0800 Subject: [PATCH 11/12] Update changelog. --- plugin-gradle/CHANGES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 54e21d250c..eb789bde91 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -11,8 +11,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `ktlint` version to latest `1.4.0` -> `1.5.0`. ([#2354](https://github.com/diffplug/spotless/pull/2354)) * Bump minimum `eclipse-cdt` version to `11.0` (removed support for `10.7`). ([#2373](https://github.com/diffplug/spotless/pull/2373)) ### Fixed -* Using `custom` with a Groovy closure now works with and without configuration cache. ([#2376](https://github.com/diffplug/spotless/pull/2376)) * `toggleOffOn` now works with the configuration cache. ([#2378](https://github.com/diffplug/spotless/pull/2378) fixes [#2317](https://github.com/diffplug/spotless/issues/2317)) +* Using `custom` with a Groovy closure now works with and without configuration cache. ([#2376](https://github.com/diffplug/spotless/pull/2376)) + * Minimum required Gradle version for this to work has bumped from `8.0` to `8.4`. + * The global git system config is now ignored for line-ending purposes. + * Added `SerializeToByteArrayHack` as a flag for a limitation at the intersection of `toggleOffOn` and `custom`. * You can now use `removeUnusedImports` and `googleJavaFormat` at the same time again. (fixes [#2159](https://github.com/diffplug/spotless/issues/2159)) * The default list of type annotations used by `formatAnnotations` now includes Jakarta Validation's `Valid` and constraints validations (fixes [#2334](https://github.com/diffplug/spotless/issues/2334)) * `indentWith[Spaces|Tabs]` has been deprecated in favor of `leadingTabsToSpaces` and `leadingSpacesToTabs`. ([#2350](https://github.com/diffplug/spotless/pull/2350) fixes [#794](https://github.com/diffplug/spotless/issues/794)) From 7a985fb36f16d751921e5a620bd86360937ca98c Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 6 Jan 2025 12:48:03 -0800 Subject: [PATCH 12/12] Add an explanatory comment on why we are zeroing out the global .gitconfig. --- .../com/diffplug/spotless/extra/GitAttributesLineEndings.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java index cf4432f2f1..0e058566f2 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java @@ -193,7 +193,8 @@ static class RuntimeInit { ///////////////////////////////// // USER AND SYSTEM-WIDE VALUES // ///////////////////////////////// - FS.DETECTED.setGitSystemConfig(new File("no-global-git-config-for-spotless")); + FS.DETECTED.setGitSystemConfig(new File("no-global-git-config-for-spotless")); // this fixes a problem + // that was only occurring on Java 11. If we remove support for Java 11, we could probably remove it. systemConfig = SystemReader.getInstance().openSystemConfig(null, FS.DETECTED); Errors.log().run(systemConfig::load); userConfig = SystemReader.getInstance().openUserConfig(systemConfig, FS.DETECTED);