From 489846224141124e13e1f3263116fc660daf78ed Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Fri, 26 Jan 2024 16:43:09 -0500 Subject: [PATCH 01/15] Stash progress --- .../diffplug/spotless/shell/ShfmtStep.java | 4 +++- .../gradle/spotless/ShellExtension.java | 2 +- .../gradle/spotless/ShellExtensionTest.java | 2 +- .../spotless/maven/shell/ShellTest.java | 2 +- testlib/build.gradle | 2 +- .../diffplug/spotless/ResourceHarness.java | 1 + .../main/resources/shell/shfmt/.editorconfig | 10 ++++++++++ .../spotless/shell/ShfmtStepTest.java | 20 ++++++++++++++++--- 8 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 testlib/src/main/resources/shell/shfmt/.editorconfig diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index cc452fce69..ab1c685b73 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -96,7 +96,9 @@ static class State implements Serializable { String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { if (args == null) { - args = List.of(exe.confirmVersionAndGetAbsolutePath(), "-i", "2", "-ci"); + // When reading from stdin, shfmt requires a filename argument + // in order for the editorconfig configuration to be resolved. + args = List.of(exe.confirmVersionAndGetAbsolutePath(), "-filename", "PLACEHOLDER.sh"); } return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8); diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/ShellExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/ShellExtension.java index 9149467eaa..6a21f2ffb4 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/ShellExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/ShellExtension.java @@ -23,7 +23,7 @@ import com.diffplug.spotless.shell.ShfmtStep; public class ShellExtension extends FormatExtension { - private static final String SHELL_FILE_EXTENSION = "*.sh"; + private static final String SHELL_FILE_EXTENSION = "**/*.sh"; static final String NAME = "shell"; diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java index 1a4f567ccb..772bd7c479 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java @@ -21,7 +21,7 @@ import com.diffplug.spotless.tag.ShfmtTest; -@ShfmtTest +//@ShfmtTest public class ShellExtensionTest extends GradleIntegrationHarness { @Test void shfmt() throws IOException { diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java index bf0e58fca6..149015896b 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java @@ -22,7 +22,7 @@ import com.diffplug.spotless.maven.MavenIntegrationHarness; import com.diffplug.spotless.tag.ShfmtTest; -@ShfmtTest +//@ShfmtTest public class ShellTest extends MavenIntegrationHarness { private static final Logger LOGGER = LoggerFactory.getLogger(ShellTest.class); diff --git a/testlib/build.gradle b/testlib/build.gradle index 38e598369e..16a9e18488 100644 --- a/testlib/build.gradle +++ b/testlib/build.gradle @@ -7,7 +7,7 @@ apply from: rootProject.file('gradle/java-setup.gradle') dependencies { api projects.lib - api files(projects.lib.dependencyProject.sourceSets.sortPom.output.classesDirs) +// api files(projects.lib.dependencyProject.sourceSets.sortPom.output.classesDirs) api "com.diffplug.durian:durian-core:${VER_DURIAN}" api "com.diffplug.durian:durian-testlib:${VER_DURIAN}" api "org.junit.jupiter:junit-jupiter:${VER_JUNIT}" diff --git a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java index 0304889e1f..5a1d5137d2 100644 --- a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java +++ b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java @@ -100,6 +100,7 @@ protected static boolean existsTestResource(String filename) { private static Optional getTestResourceUrl(String filename) { URL url = ResourceHarness.class.getResource("/" + filename); +// System.out.println(url.getPath()); return Optional.ofNullable(url); } diff --git a/testlib/src/main/resources/shell/shfmt/.editorconfig b/testlib/src/main/resources/shell/shfmt/.editorconfig new file mode 100644 index 0000000000..8a7d8d6043 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 + +[*.sh] +indent_style = space +indent_size = 2 +space_redirects = true +switch_case_indent = true diff --git a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java index 41dc38e225..57e85dd711 100644 --- a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java @@ -15,18 +15,32 @@ */ package com.diffplug.spotless.shell; +import com.diffplug.spotless.StepHarnessWithFile; + import org.junit.jupiter.api.Test; import com.diffplug.spotless.ResourceHarness; -import com.diffplug.spotless.StepHarness; import com.diffplug.spotless.tag.ShfmtTest; +import java.io.File; +import java.util.Arrays; +import java.util.List; + @ShfmtTest public class ShfmtStepTest extends ResourceHarness { @Test void test() throws Exception { - try (StepHarness harness = StepHarness.forStep(ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { - harness.testResource("shell/shfmt/shfmt.sh", "shell/shfmt/shfmt.clean").close(); + try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { + final String filedir = "shell/shfmt/"; + + setFile(".editorconfig").toResource(filedir + ".editorconfig"); + + final List files = List.of(rootFolder().listFiles()); + + final String dirtyFile = filedir + "shfmt.sh"; + final String cleanFile = filedir + "shfmt.clean"; + + harness.testResource(dirtyFile, cleanFile).close(); } } } From d95436a456cf41b756a491640ca2712020c75b2d Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Tue, 30 Jan 2024 17:10:10 -0500 Subject: [PATCH 02/15] Add .editorconfig support for shfmt --- .../diffplug/spotless/shell/ShfmtStep.java | 35 ++++++++++++------ .../gradle/spotless/ShellExtensionTest.java | 36 +++++++++++++++---- .../spotless/maven/shell/ShellTest.java | 23 +++++++++--- testlib/build.gradle | 2 +- .../diffplug/spotless/ResourceHarness.java | 4 +-- .../shfmt/{ => with-config}/.editorconfig | 0 .../shell/shfmt/{ => with-config}/shfmt.clean | 0 .../shell/shfmt/{ => with-config}/shfmt.sh | 0 .../shell/shfmt/without-config/shfmt.clean | 17 +++++++++ .../shell/shfmt/without-config/shfmt.sh | 18 ++++++++++ .../spotless/shell/ShfmtStepTest.java | 23 ++++++------ 11 files changed, 124 insertions(+), 34 deletions(-) rename testlib/src/main/resources/shell/shfmt/{ => with-config}/.editorconfig (100%) rename testlib/src/main/resources/shell/shfmt/{ => with-config}/shfmt.clean (100%) rename testlib/src/main/resources/shell/shfmt/{ => with-config}/shfmt.sh (100%) create mode 100644 testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean create mode 100644 testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index ab1c685b73..f4434bb41f 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -86,27 +86,40 @@ static class State implements Serializable { // used for up-to-date checks and caching final String version; final transient ForeignExe exe; - // used for executing - private transient @Nullable List args; State(ShfmtStep step, ForeignExe pathToExe) { this.version = step.version; this.exe = Objects.requireNonNull(pathToExe); } + FormatterFunc.Closeable toFunc() { + ProcessRunner runner = new ProcessRunner(); + return FormatterFunc.Closeable.ofDangerous(runner, new ShfmtFilePathPassingFormatterFunc(runner, exe)); + } + } + + private static class ShfmtFilePathPassingFormatterFunc implements FormatterFunc.NeedsFile { + // used for executing + private transient @Nullable List args; + final transient ForeignExe exe; + final transient ProcessRunner runner; + + ShfmtFilePathPassingFormatterFunc(ProcessRunner runner, ForeignExe exe) { + this.runner = runner; + this.exe = exe; + } + + @Override + public String applyWithFile(String unix, File file) throws Exception { + return format(runner, unix, file); + } + String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { if (args == null) { - // When reading from stdin, shfmt requires a filename argument - // in order for the editorconfig configuration to be resolved. - args = List.of(exe.confirmVersionAndGetAbsolutePath(), "-filename", "PLACEHOLDER.sh"); + args = List.of(exe.confirmVersionAndGetAbsolutePath(), file.getAbsolutePath()); } - return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8); - } - - FormatterFunc.Closeable toFunc() { - ProcessRunner runner = new ProcessRunner(); - return FormatterFunc.Closeable.of(runner, this::format); + return runner.exec(args).assertExitZero(StandardCharsets.UTF_8); } } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java index 772bd7c479..55929ccfbb 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java @@ -21,21 +21,45 @@ import com.diffplug.spotless.tag.ShfmtTest; -//@ShfmtTest +@ShfmtTest public class ShellExtensionTest extends GradleIntegrationHarness { @Test - void shfmt() throws IOException { - setFile("build.gradle").toLines( + void shfmtWithEditorconfig() throws IOException { + String fileDir = "shell/shfmt/with-config/"; + setFile(".editorconfig").toResource(fileDir + ".editorconfig"); + setFile("build.gradle.kts").toLines( "plugins {", - " id 'com.diffplug.spotless'", + " id(\"com.diffplug.spotless\")", "}", + "repositories { mavenCentral() }", "spotless {", " shell {", " shfmt()", " }", "}"); - setFile("shfmt.sh").toResource("shell/shfmt/shfmt.sh"); + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + + gradleRunner().withArguments("spotlessApply").build(); + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + } + + @Test + void shfmtWithoutEditorconfig() throws IOException { + String fileDir = "shell/shfmt/without-config/"; + + setFile("build.gradle.kts").toLines( + "plugins {", + " id(\"com.diffplug.spotless\")", + "}", + "repositories { mavenCentral() }", + "spotless {", + " shell {", + " shfmt()", + " }", + "}"); + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + gradleRunner().withArguments("spotlessApply").build(); - assertFile("shfmt.sh").sameAsResource("shell/shfmt/shfmt.clean"); + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java index 149015896b..f3746d843d 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java @@ -22,15 +22,30 @@ import com.diffplug.spotless.maven.MavenIntegrationHarness; import com.diffplug.spotless.tag.ShfmtTest; -//@ShfmtTest +@ShfmtTest public class ShellTest extends MavenIntegrationHarness { private static final Logger LOGGER = LoggerFactory.getLogger(ShellTest.class); @Test - public void testFormatShell() throws Exception { + public void testFormatShellWithEditorconfig() throws Exception { + String fileDir = "shell/shfmt/with-config/"; + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + setFile(".editorconfig").toResource(fileDir + ".editorconfig"); + writePomWithShellSteps(""); - setFile("shfmt.sh").toResource("shell/shfmt/shfmt.sh"); mavenRunner().withArguments("spotless:apply").runNoError(); - assertFile("shfmt.sh").sameAsResource("shell/shfmt/shfmt.clean"); + + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + } + + @Test + public void testFormatShellWithoutEditorconfig() throws Exception { + String fileDir = "shell/shfmt/without-config/"; + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + + writePomWithShellSteps(""); + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); } } diff --git a/testlib/build.gradle b/testlib/build.gradle index 16a9e18488..5aad81bae2 100644 --- a/testlib/build.gradle +++ b/testlib/build.gradle @@ -7,7 +7,7 @@ apply from: rootProject.file('gradle/java-setup.gradle') dependencies { api projects.lib -// api files(projects.lib.dependencyProject.sourceSets.sortPom.output.classesDirs) + // api files(projects.lib.dependencyProject.sourceSets.sortPom.output.classesDirs) api "com.diffplug.durian:durian-core:${VER_DURIAN}" api "com.diffplug.durian:durian-testlib:${VER_DURIAN}" api "org.junit.jupiter:junit-jupiter:${VER_JUNIT}" diff --git a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java index 5a1d5137d2..88295a3346 100644 --- a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java +++ b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 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. @@ -100,7 +100,7 @@ protected static boolean existsTestResource(String filename) { private static Optional getTestResourceUrl(String filename) { URL url = ResourceHarness.class.getResource("/" + filename); -// System.out.println(url.getPath()); + // System.out.println(url.getPath()); return Optional.ofNullable(url); } diff --git a/testlib/src/main/resources/shell/shfmt/.editorconfig b/testlib/src/main/resources/shell/shfmt/with-config/.editorconfig similarity index 100% rename from testlib/src/main/resources/shell/shfmt/.editorconfig rename to testlib/src/main/resources/shell/shfmt/with-config/.editorconfig diff --git a/testlib/src/main/resources/shell/shfmt/shfmt.clean b/testlib/src/main/resources/shell/shfmt/with-config/shfmt.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/shfmt.clean rename to testlib/src/main/resources/shell/shfmt/with-config/shfmt.clean diff --git a/testlib/src/main/resources/shell/shfmt/shfmt.sh b/testlib/src/main/resources/shell/shfmt/with-config/shfmt.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/shfmt.sh rename to testlib/src/main/resources/shell/shfmt/with-config/shfmt.sh diff --git a/testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean new file mode 100644 index 0000000000..80386d472e --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +function foo() { + if [ -x $file ]; then + myArray=(item1 item2 item3) + elif [ $file1 -nt $file2 ]; then + unset myArray + else + echo "Usage: $0 file ..." + fi +} + +for ((i = 0; i < 5; i++)); do + read -p r + print -n $r + wait $! +done diff --git a/testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh new file mode 100644 index 0000000000..9d15c477d4 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +function foo() { + if [ -x $file ]; then + myArray=(item1 item2 item3) + elif [ $file1 -nt $file2 ] + then + unset myArray + else +echo "Usage: $0 file ..." + fi +} + +for ((i = 0; i < 5; i++)); do + read -p r + print -n $r + wait $! +done diff --git a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java index 57e85dd711..821af2468b 100644 --- a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java @@ -15,32 +15,35 @@ */ package com.diffplug.spotless.shell; -import com.diffplug.spotless.StepHarnessWithFile; - import org.junit.jupiter.api.Test; import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.StepHarnessWithFile; import com.diffplug.spotless.tag.ShfmtTest; -import java.io.File; -import java.util.Arrays; -import java.util.List; - @ShfmtTest public class ShfmtStepTest extends ResourceHarness { @Test - void test() throws Exception { + void testWithEditorconfig() throws Exception { try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { - final String filedir = "shell/shfmt/"; + final String filedir = "shell/shfmt/with-config/"; + final String dirtyFile = filedir + "shfmt.sh"; + final String cleanFile = filedir + "shfmt.clean"; setFile(".editorconfig").toResource(filedir + ".editorconfig"); - final List files = List.of(rootFolder().listFiles()); + harness.testResource(dirtyFile, cleanFile); + } + } + @Test + void testWithoutEditorconfig() throws Exception { + try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { + final String filedir = "shell/shfmt/without-config/"; final String dirtyFile = filedir + "shfmt.sh"; final String cleanFile = filedir + "shfmt.clean"; - harness.testResource(dirtyFile, cleanFile).close(); + harness.testResource(dirtyFile, cleanFile); } } } From 4ae13c97820491600625de7104b09bbc5c14bf24 Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Tue, 30 Jan 2024 17:25:37 -0500 Subject: [PATCH 03/15] Revert unnecessary changes --- testlib/build.gradle | 2 +- .../src/main/java/com/diffplug/spotless/ResourceHarness.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/testlib/build.gradle b/testlib/build.gradle index 5aad81bae2..38e598369e 100644 --- a/testlib/build.gradle +++ b/testlib/build.gradle @@ -7,7 +7,7 @@ apply from: rootProject.file('gradle/java-setup.gradle') dependencies { api projects.lib - // api files(projects.lib.dependencyProject.sourceSets.sortPom.output.classesDirs) + api files(projects.lib.dependencyProject.sourceSets.sortPom.output.classesDirs) api "com.diffplug.durian:durian-core:${VER_DURIAN}" api "com.diffplug.durian:durian-testlib:${VER_DURIAN}" api "org.junit.jupiter:junit-jupiter:${VER_JUNIT}" diff --git a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java index 88295a3346..0304889e1f 100644 --- a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java +++ b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -100,7 +100,6 @@ protected static boolean existsTestResource(String filename) { private static Optional getTestResourceUrl(String filename) { URL url = ResourceHarness.class.getResource("/" + filename); - // System.out.println(url.getPath()); return Optional.ofNullable(url); } From 1b3335d28b3cccf868d7ec03a4ff004077179dab Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Tue, 30 Jan 2024 20:25:15 -0500 Subject: [PATCH 04/15] Update change logs and documentation for shell formatting --- CHANGES.md | 2 ++ plugin-gradle/CHANGES.md | 3 ++ plugin-gradle/README.md | 6 +++- plugin-maven/CHANGES.md | 3 ++ plugin-maven/README.md | 31 ++++++++++++++++++- .../diffplug/spotless/maven/shell/Shell.java | 5 +-- .../diffplug/spotless/maven/shell/Shfmt.java | 1 - 7 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index cb8bf9706e..b0d80fd7ff 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * `FileSignature.Promised` and `JarState.Promised` to facilitate round-trip serialization for the Gradle configuration cache. ([#1945](https://github.com/diffplug/spotless/pull/1945)) +* Respect `.editorconfig` settings for formatting shell via `shfmt` ([#2031](https://github.com/diffplug/spotless/pull/2031)) + ### Removed * **BREAKING** Remove `JarState.getMavenCoordinate(String prefix)`. ([#1945](https://github.com/diffplug/spotless/pull/1945)) * **BREAKING** Replace `PipeStepPair` with `FenceStep`. ([#1954](https://github.com/diffplug/spotless/pull/1954)) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 5e7d8823b9..7ce10e1edc 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -6,6 +6,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Fixed * Ignore system git config when running tests ([#1990](https://github.com/diffplug/spotless/issues/1990)) +### Added +* Respect `.editorconfig` settings for formatting shell via `shfmt` ([#2031](https://github.com/diffplug/spotless/pull/2031)) + ## [6.25.0] - 2024-01-23 ### Added * Maven / Gradle - Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009)) diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 060b900bdc..4f2d0e6930 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -992,7 +992,7 @@ spotless { ```gradle spotless { shell { - target 'scripts/**/*.sh' // default: '*.sh' + target 'scripts/**/*.sh' // default: '**/*.sh' shfmt() // has its own section below } @@ -1003,11 +1003,15 @@ spotless { [homepage](https://github.com/mvdan/sh). [changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md). +When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.editorconfig`. +Refer to the `shfmt` man page for `.editorconfig` settings. + ```gradle shfmt('3.7.0') // version is optional // if shfmt is not on your path, you must specify its location manually shfmt().pathToExe('/opt/homebrew/bin/shfmt') + // Spotless always checks the version of the shfmt it is using // and will fail with an error if it does not match the expected version // (whether manually specified or default). If there is a problem, Spotless diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 37cc1de12e..3e3cc975b3 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -6,6 +6,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Fixed * Ignore system git config when running tests ([#1990](https://github.com/diffplug/spotless/issues/1990)) +### Added +* Respect `.editorconfig` settings for formatting shell via `shfmt` ([#2031](https://github.com/diffplug/spotless/pull/2031)) + ## [2.43.0] - 2024-01-23 ### Added * Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1998](https://github.com/diffplug/spotless/issues/1998)) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 1063f3ad12..fbe4248b7b 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -1021,11 +1021,40 @@ Uses Jackson and YAMLFactory to pretty print objects: ``` +## Shell + +- `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](./src/main/java/com/diffplug/spotless/maven/shell/Shell.java) + +```xml + + + + scripts/**/*.sh + + + + + +``` + +### shfmt + +[homepage](https://github.com/mvdan/sh). [changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md). + +When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.editorconfig`. + +```xml + + 3.7.0 + /opt/homebrew/bin/shfmt + +``` + ## Gherkin - `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/gherkin/Gherkin.java) -```gradle +```xml diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shell.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shell.java index 6285bfc410..0626c5ceb9 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shell.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shell.java @@ -15,7 +15,6 @@ */ package com.diffplug.spotless.maven.shell; -import java.util.Collections; import java.util.Set; import org.apache.maven.project.MavenProject; @@ -30,9 +29,11 @@ * and shell-specific (e.g. {@link Shfmt}) steps. */ public class Shell extends FormatterFactory { + private static final Set DEFAULT_INCLUDES = Set.of("**/*.sh"); + @Override public Set defaultIncludes(MavenProject project) { - return Collections.emptySet(); + return DEFAULT_INCLUDES; } @Override diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shfmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shfmt.java index 09b83240b0..4bab77ecd6 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shfmt.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/shell/Shfmt.java @@ -23,7 +23,6 @@ import com.diffplug.spotless.shell.ShfmtStep; public class Shfmt implements FormatterStepFactory { - @Parameter private String version; From 733f7dae3fe7b354bb7bb35d64781797d621b4ec Mon Sep 17 00:00:00 2001 From: Tyler Crawford <91682066+tcrawford-figure@users.noreply.github.com> Date: Thu, 1 Feb 2024 09:27:04 -0500 Subject: [PATCH 05/15] Make files private Co-authored-by: Zongle Wang --- lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index f4434bb41f..d1a9934a4c 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -101,8 +101,8 @@ FormatterFunc.Closeable toFunc() { private static class ShfmtFilePathPassingFormatterFunc implements FormatterFunc.NeedsFile { // used for executing private transient @Nullable List args; - final transient ForeignExe exe; - final transient ProcessRunner runner; + private final transient ForeignExe exe; + private final transient ProcessRunner runner; ShfmtFilePathPassingFormatterFunc(ProcessRunner runner, ForeignExe exe) { this.runner = runner; From 3c2701d5eb0189e380754894818feca14bd66c50 Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Thu, 1 Feb 2024 13:51:47 -0500 Subject: [PATCH 06/15] Fix formatting multiple shell files at the same time --- .../diffplug/spotless/shell/ShfmtStep.java | 35 ++++-------- .../gradle/spotless/ShellExtensionTest.java | 55 +++++++++++++++++-- .../spotless/maven/shell/ShellTest.java | 4 +- .../{ => multifile}/with-config/.editorconfig | 0 .../shfmt/multifile/with-config/other.clean | 20 +++++++ .../shfmt/multifile/with-config/other.sh | 20 +++++++ .../{ => multifile}/with-config/shfmt.clean | 0 .../{ => multifile}/with-config/shfmt.sh | 0 .../multifile/without-config/other.clean | 20 +++++++ .../shfmt/multifile/without-config/other.sh | 20 +++++++ .../without-config/shfmt.clean | 0 .../{ => multifile}/without-config/shfmt.sh | 0 .../singlefile/with-config/.editorconfig | 10 ++++ .../shfmt/singlefile/with-config/shfmt.clean | 17 ++++++ .../shfmt/singlefile/with-config/shfmt.sh | 18 ++++++ .../singlefile/without-config/shfmt.clean | 17 ++++++ .../shfmt/singlefile/without-config/shfmt.sh | 18 ++++++ .../spotless/shell/ShfmtStepTest.java | 14 ++--- 18 files changed, 231 insertions(+), 37 deletions(-) rename testlib/src/main/resources/shell/shfmt/{ => multifile}/with-config/.editorconfig (100%) create mode 100644 testlib/src/main/resources/shell/shfmt/multifile/with-config/other.clean create mode 100644 testlib/src/main/resources/shell/shfmt/multifile/with-config/other.sh rename testlib/src/main/resources/shell/shfmt/{ => multifile}/with-config/shfmt.clean (100%) rename testlib/src/main/resources/shell/shfmt/{ => multifile}/with-config/shfmt.sh (100%) create mode 100644 testlib/src/main/resources/shell/shfmt/multifile/without-config/other.clean create mode 100644 testlib/src/main/resources/shell/shfmt/multifile/without-config/other.sh rename testlib/src/main/resources/shell/shfmt/{ => multifile}/without-config/shfmt.clean (100%) rename testlib/src/main/resources/shell/shfmt/{ => multifile}/without-config/shfmt.sh (100%) create mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig create mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean create mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh create mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean create mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index d1a9934a4c..b92c55c686 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -83,43 +83,30 @@ private State createState() throws IOException, InterruptedException { @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") static class State implements Serializable { private static final long serialVersionUID = -1825662356883926318L; + // used for up-to-date checks and caching final String version; final transient ForeignExe exe; - State(ShfmtStep step, ForeignExe pathToExe) { - this.version = step.version; - this.exe = Objects.requireNonNull(pathToExe); - } - - FormatterFunc.Closeable toFunc() { - ProcessRunner runner = new ProcessRunner(); - return FormatterFunc.Closeable.ofDangerous(runner, new ShfmtFilePathPassingFormatterFunc(runner, exe)); - } - } - - private static class ShfmtFilePathPassingFormatterFunc implements FormatterFunc.NeedsFile { // used for executing private transient @Nullable List args; - private final transient ForeignExe exe; - private final transient ProcessRunner runner; - - ShfmtFilePathPassingFormatterFunc(ProcessRunner runner, ForeignExe exe) { - this.runner = runner; - this.exe = exe; - } - @Override - public String applyWithFile(String unix, File file) throws Exception { - return format(runner, unix, file); + State(ShfmtStep step, ForeignExe pathToExe) { + this.version = step.version; + this.exe = Objects.requireNonNull(pathToExe); } String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { if (args == null) { - args = List.of(exe.confirmVersionAndGetAbsolutePath(), file.getAbsolutePath()); + args = List.of(exe.confirmVersionAndGetAbsolutePath(), "--filename", file.getPath()); } - return runner.exec(args).assertExitZero(StandardCharsets.UTF_8); + return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8); + } + + FormatterFunc.Closeable toFunc() { + ProcessRunner runner = new ProcessRunner(); + return FormatterFunc.Closeable.of(runner, this::format); } } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java index 55929ccfbb..6e75b5b17d 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java @@ -25,41 +25,88 @@ public class ShellExtensionTest extends GradleIntegrationHarness { @Test void shfmtWithEditorconfig() throws IOException { - String fileDir = "shell/shfmt/with-config/"; + String fileDir = "shell/shfmt/singlefile/with-config/"; setFile(".editorconfig").toResource(fileDir + ".editorconfig"); setFile("build.gradle.kts").toLines( "plugins {", " id(\"com.diffplug.spotless\")", "}", - "repositories { mavenCentral() }", "spotless {", " shell {", " shfmt()", " }", "}"); + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); gradleRunner().withArguments("spotlessApply").build(); assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); } + @Test + void shfmtMultipleFilesWithEditorconfig() throws IOException { + String fileDir = "shell/shfmt/multifile/with-config/"; + + setFile(".editorconfig").toResource(fileDir + ".editorconfig"); + setFile("build.gradle.kts").toLines( + "plugins {", + " id(\"com.diffplug.spotless\")", + "}", + "spotless {", + " shell {", + " shfmt()", + " }", + "}"); + + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + setFile("other.sh").toResource(fileDir + "other.sh"); + + gradleRunner().withArguments("spotlessApply").build(); + + assertFile("other.sh").sameAsResource(fileDir + "other.clean"); + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + } + @Test void shfmtWithoutEditorconfig() throws IOException { - String fileDir = "shell/shfmt/without-config/"; + String fileDir = "shell/shfmt/singlefile/without-config/"; setFile("build.gradle.kts").toLines( "plugins {", " id(\"com.diffplug.spotless\")", "}", - "repositories { mavenCentral() }", "spotless {", " shell {", " shfmt()", " }", "}"); + + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + + gradleRunner().withArguments("spotlessApply").build(); + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + } + + @Test + void shfmtMultipleFilesWithoutEditorconfig() throws IOException { + String fileDir = "shell/shfmt/multifile/without-config/"; + + setFile("build.gradle.kts").toLines( + "plugins {", + " id(\"com.diffplug.spotless\")", + "}", + "spotless {", + " shell {", + " shfmt()", + " }", + "}"); + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + setFile("other.sh").toResource(fileDir + "other.sh"); gradleRunner().withArguments("spotlessApply").build(); + + assertFile("other.sh").sameAsResource(fileDir + "other.clean"); assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java index f3746d843d..723e39ba4e 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java @@ -28,7 +28,7 @@ public class ShellTest extends MavenIntegrationHarness { @Test public void testFormatShellWithEditorconfig() throws Exception { - String fileDir = "shell/shfmt/with-config/"; + String fileDir = "shell/shfmt/singlefile/with-config/"; setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); setFile(".editorconfig").toResource(fileDir + ".editorconfig"); @@ -40,7 +40,7 @@ public void testFormatShellWithEditorconfig() throws Exception { @Test public void testFormatShellWithoutEditorconfig() throws Exception { - String fileDir = "shell/shfmt/without-config/"; + String fileDir = "shell/shfmt/singlefile/without-config/"; setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); writePomWithShellSteps(""); diff --git a/testlib/src/main/resources/shell/shfmt/with-config/.editorconfig b/testlib/src/main/resources/shell/shfmt/multifile/with-config/.editorconfig similarity index 100% rename from testlib/src/main/resources/shell/shfmt/with-config/.editorconfig rename to testlib/src/main/resources/shell/shfmt/multifile/with-config/.editorconfig diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.clean b/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.clean new file mode 100644 index 0000000000..ba84ece688 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.clean @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +fruit="apple" + +case $fruit in + "apple") + echo "This is a red fruit." + ;; + "banana") + echo "This is a yellow fruit." + ;; + "orange") + echo "This is an orange fruit." + ;; + *) + echo "Unknown fruit." + ;; +esac + +echo "This is some text." > output.txt diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.sh b/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.sh new file mode 100644 index 0000000000..58f97b8276 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +fruit="apple" + +case $fruit in + "apple") + echo "This is a red fruit." + ;; + "banana") + echo "This is a yellow fruit." +;; + "orange") + echo "This is an orange fruit." + ;; + *) + echo "Unknown fruit." + ;; +esac + + echo "This is some text." > output.txt diff --git a/testlib/src/main/resources/shell/shfmt/with-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/with-config/shfmt.clean rename to testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.clean diff --git a/testlib/src/main/resources/shell/shfmt/with-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/with-config/shfmt.sh rename to testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.sh diff --git a/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.clean b/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.clean new file mode 100644 index 0000000000..cba42806aa --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.clean @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +fruit="apple" + +case $fruit in +"apple") + echo "This is a red fruit." + ;; +"banana") + echo "This is a yellow fruit." + ;; +"orange") + echo "This is an orange fruit." + ;; +*) + echo "Unknown fruit." + ;; +esac + +echo "This is some text." >output.txt diff --git a/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.sh b/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.sh new file mode 100644 index 0000000000..58f97b8276 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +fruit="apple" + +case $fruit in + "apple") + echo "This is a red fruit." + ;; + "banana") + echo "This is a yellow fruit." +;; + "orange") + echo "This is an orange fruit." + ;; + *) + echo "Unknown fruit." + ;; +esac + + echo "This is some text." > output.txt diff --git a/testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean rename to testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.clean diff --git a/testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh rename to testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.sh diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig new file mode 100644 index 0000000000..8a7d8d6043 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 + +[*.sh] +indent_style = space +indent_size = 2 +space_redirects = true +switch_case_indent = true diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean new file mode 100644 index 0000000000..c1b9b25064 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +function foo() { + if [ -x $file ]; then + myArray=(item1 item2 item3) + elif [ $file1 -nt $file2 ]; then + unset myArray + else + echo "Usage: $0 file ..." + fi +} + +for ((i = 0; i < 5; i++)); do + read -p r + print -n $r + wait $! +done diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh new file mode 100644 index 0000000000..9d15c477d4 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +function foo() { + if [ -x $file ]; then + myArray=(item1 item2 item3) + elif [ $file1 -nt $file2 ] + then + unset myArray + else +echo "Usage: $0 file ..." + fi +} + +for ((i = 0; i < 5; i++)); do + read -p r + print -n $r + wait $! +done diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean new file mode 100644 index 0000000000..80386d472e --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +function foo() { + if [ -x $file ]; then + myArray=(item1 item2 item3) + elif [ $file1 -nt $file2 ]; then + unset myArray + else + echo "Usage: $0 file ..." + fi +} + +for ((i = 0; i < 5; i++)); do + read -p r + print -n $r + wait $! +done diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh new file mode 100644 index 0000000000..9d15c477d4 --- /dev/null +++ b/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +function foo() { + if [ -x $file ]; then + myArray=(item1 item2 item3) + elif [ $file1 -nt $file2 ] + then + unset myArray + else +echo "Usage: $0 file ..." + fi +} + +for ((i = 0; i < 5; i++)); do + read -p r + print -n $r + wait $! +done diff --git a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java index 821af2468b..c2d8edd15b 100644 --- a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java @@ -26,11 +26,11 @@ public class ShfmtStepTest extends ResourceHarness { @Test void testWithEditorconfig() throws Exception { try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { - final String filedir = "shell/shfmt/with-config/"; - final String dirtyFile = filedir + "shfmt.sh"; - final String cleanFile = filedir + "shfmt.clean"; + final String fileDir = "shell/shfmt/singlefile/with-config/"; + final String dirtyFile = fileDir + "shfmt.sh"; + final String cleanFile = fileDir + "shfmt.clean"; - setFile(".editorconfig").toResource(filedir + ".editorconfig"); + setFile(".editorconfig").toResource(fileDir + ".editorconfig"); harness.testResource(dirtyFile, cleanFile); } @@ -39,9 +39,9 @@ void testWithEditorconfig() throws Exception { @Test void testWithoutEditorconfig() throws Exception { try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { - final String filedir = "shell/shfmt/without-config/"; - final String dirtyFile = filedir + "shfmt.sh"; - final String cleanFile = filedir + "shfmt.clean"; + final String fileDir = "shell/shfmt/singlefile/without-config/"; + final String dirtyFile = fileDir + "shfmt.sh"; + final String cleanFile = fileDir + "shfmt.clean"; harness.testResource(dirtyFile, cleanFile); } From 8bf8d8fd5b5b10ed5138d8a3d6108ba740f8340c Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Thu, 1 Feb 2024 14:02:37 -0500 Subject: [PATCH 07/15] Add multi-file shfmt tests for maven --- .../spotless/maven/shell/ShellTest.java | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java index 723e39ba4e..a8ac7305e3 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java @@ -27,7 +27,7 @@ public class ShellTest extends MavenIntegrationHarness { private static final Logger LOGGER = LoggerFactory.getLogger(ShellTest.class); @Test - public void testFormatShellWithEditorconfig() throws Exception { + public void testSingleFileFormatShellWithEditorconfig() throws Exception { String fileDir = "shell/shfmt/singlefile/with-config/"; setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); setFile(".editorconfig").toResource(fileDir + ".editorconfig"); @@ -39,7 +39,7 @@ public void testFormatShellWithEditorconfig() throws Exception { } @Test - public void testFormatShellWithoutEditorconfig() throws Exception { + public void testSingleFileFormatShellWithoutEditorconfig() throws Exception { String fileDir = "shell/shfmt/singlefile/without-config/"; setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); @@ -48,4 +48,31 @@ public void testFormatShellWithoutEditorconfig() throws Exception { assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); } + + @Test + public void testMultiFileFormatShellWithEditorconfig() throws Exception { + String fileDir = "shell/shfmt/multifile/with-config/"; + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + setFile("other.sh").toResource(fileDir + "other.sh"); + setFile(".editorconfig").toResource(fileDir + ".editorconfig"); + + writePomWithShellSteps(""); + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + assertFile("other.sh").sameAsResource(fileDir + "other.clean"); + } + + @Test + public void testMultiFileFormatShellWithoutEditorconfig() throws Exception { + String fileDir = "shell/shfmt/multifile/without-config/"; + setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); + setFile("other.sh").toResource(fileDir + "other.sh"); + + writePomWithShellSteps(""); + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + assertFile("other.sh").sameAsResource(fileDir + "other.clean"); + } } From 4c4b7bce005b2b3d84c45958500068ba4cc1f370 Mon Sep 17 00:00:00 2001 From: Tyler Crawford <91682066+tcrawford-figure@users.noreply.github.com> Date: Fri, 2 Feb 2024 09:00:04 -0500 Subject: [PATCH 08/15] Fix plugin-gradle/README.md typo Co-authored-by: Zongle Wang --- plugin-gradle/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 4f2d0e6930..89d72e034b 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -1004,7 +1004,7 @@ spotless { [homepage](https://github.com/mvdan/sh). [changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md). When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.editorconfig`. -Refer to the `shfmt` man page for `.editorconfig` settings. +Refer to the `shfmt` main page for `.editorconfig` settings. ```gradle shfmt('3.7.0') // version is optional From 2c382477ba80e22adb612194727671726c37f805 Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Mon, 5 Feb 2024 11:46:04 -0500 Subject: [PATCH 09/15] Fix how Shfmt args are constructed, tidy tests --- .../diffplug/spotless/shell/ShfmtStep.java | 12 ++++- .../gradle/spotless/ShellExtensionTest.java | 54 +++---------------- .../spotless/maven/shell/ShellTest.java | 43 +++------------ .../singlefile/with-config/.editorconfig | 10 ---- .../shfmt/singlefile/with-config/shfmt.clean | 17 ------ .../shfmt/singlefile/with-config/shfmt.sh | 18 ------- .../singlefile/without-config/shfmt.clean | 17 ------ .../shfmt/singlefile/without-config/shfmt.sh | 18 ------- .../{multifile => }/with-config/.editorconfig | 0 .../{multifile => }/with-config/other.clean | 0 .../{multifile => }/with-config/other.sh | 0 .../{multifile => }/with-config/shfmt.clean | 0 .../{multifile => }/with-config/shfmt.sh | 0 .../without-config/other.clean | 0 .../{multifile => }/without-config/other.sh | 0 .../without-config/shfmt.clean | 0 .../{multifile => }/without-config/shfmt.sh | 0 .../spotless/shell/ShfmtStepTest.java | 4 +- 18 files changed, 28 insertions(+), 165 deletions(-) delete mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig delete mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean delete mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh delete mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean delete mode 100644 testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh rename testlib/src/main/resources/shell/shfmt/{multifile => }/with-config/.editorconfig (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/with-config/other.clean (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/with-config/other.sh (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/with-config/shfmt.clean (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/with-config/shfmt.sh (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/without-config/other.clean (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/without-config/other.sh (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/without-config/shfmt.clean (100%) rename testlib/src/main/resources/shell/shfmt/{multifile => }/without-config/shfmt.sh (100%) diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index b92c55c686..4203a8ed7f 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nullable; @@ -98,10 +100,16 @@ static class State implements Serializable { String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { if (args == null) { - args = List.of(exe.confirmVersionAndGetAbsolutePath(), "--filename", file.getPath()); + // args will be reused during a single spotless task execution, + // so this "prefix" is being "cached" for each spotless task. + args = List.of(exe.confirmVersionAndGetAbsolutePath(), "--filename"); } - return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8); + // This will ensure that the next file name is retrieved on every format + final List finalArgs = Stream.concat(args.stream(), Stream.of(file.getAbsolutePath())) + .collect(Collectors.toList()); + + return runner.exec(input.getBytes(StandardCharsets.UTF_8), finalArgs).assertExitZero(StandardCharsets.UTF_8); } FormatterFunc.Closeable toFunc() { diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java index 6e75b5b17d..2860325132 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ShellExtensionTest.java @@ -23,10 +23,11 @@ @ShfmtTest public class ShellExtensionTest extends GradleIntegrationHarness { + @Test void shfmtWithEditorconfig() throws IOException { - String fileDir = "shell/shfmt/singlefile/with-config/"; - setFile(".editorconfig").toResource(fileDir + ".editorconfig"); + String fileDir = "shell/shfmt/with-config/"; + setFile("build.gradle.kts").toLines( "plugins {", " id(\"com.diffplug.spotless\")", @@ -37,59 +38,20 @@ void shfmtWithEditorconfig() throws IOException { " }", "}"); - setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - - gradleRunner().withArguments("spotlessApply").build(); - assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); - } - - @Test - void shfmtMultipleFilesWithEditorconfig() throws IOException { - String fileDir = "shell/shfmt/multifile/with-config/"; - setFile(".editorconfig").toResource(fileDir + ".editorconfig"); - setFile("build.gradle.kts").toLines( - "plugins {", - " id(\"com.diffplug.spotless\")", - "}", - "spotless {", - " shell {", - " shfmt()", - " }", - "}"); setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - setFile("other.sh").toResource(fileDir + "other.sh"); + setFile("scripts/other.sh").toResource(fileDir + "other.sh"); gradleRunner().withArguments("spotlessApply").build(); - assertFile("other.sh").sameAsResource(fileDir + "other.clean"); assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + assertFile("scripts/other.sh").sameAsResource(fileDir + "other.clean"); } @Test void shfmtWithoutEditorconfig() throws IOException { - String fileDir = "shell/shfmt/singlefile/without-config/"; - - setFile("build.gradle.kts").toLines( - "plugins {", - " id(\"com.diffplug.spotless\")", - "}", - "spotless {", - " shell {", - " shfmt()", - " }", - "}"); - - setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - - gradleRunner().withArguments("spotlessApply").build(); - assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); - } - - @Test - void shfmtMultipleFilesWithoutEditorconfig() throws IOException { - String fileDir = "shell/shfmt/multifile/without-config/"; + String fileDir = "shell/shfmt/without-config/"; setFile("build.gradle.kts").toLines( "plugins {", @@ -102,11 +64,11 @@ void shfmtMultipleFilesWithoutEditorconfig() throws IOException { "}"); setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - setFile("other.sh").toResource(fileDir + "other.sh"); + setFile("scripts/other.sh").toResource(fileDir + "other.sh"); gradleRunner().withArguments("spotlessApply").build(); - assertFile("other.sh").sameAsResource(fileDir + "other.clean"); assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); + assertFile("scripts/other.sh").sameAsResource(fileDir + "other.clean"); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java index a8ac7305e3..534835c644 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/shell/ShellTest.java @@ -16,63 +16,36 @@ package com.diffplug.spotless.maven.shell; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.diffplug.spotless.maven.MavenIntegrationHarness; import com.diffplug.spotless.tag.ShfmtTest; @ShfmtTest public class ShellTest extends MavenIntegrationHarness { - private static final Logger LOGGER = LoggerFactory.getLogger(ShellTest.class); - - @Test - public void testSingleFileFormatShellWithEditorconfig() throws Exception { - String fileDir = "shell/shfmt/singlefile/with-config/"; - setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - setFile(".editorconfig").toResource(fileDir + ".editorconfig"); - - writePomWithShellSteps(""); - mavenRunner().withArguments("spotless:apply").runNoError(); - - assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); - } - - @Test - public void testSingleFileFormatShellWithoutEditorconfig() throws Exception { - String fileDir = "shell/shfmt/singlefile/without-config/"; - setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - - writePomWithShellSteps(""); - mavenRunner().withArguments("spotless:apply").runNoError(); - - assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); - } - @Test - public void testMultiFileFormatShellWithEditorconfig() throws Exception { - String fileDir = "shell/shfmt/multifile/with-config/"; + public void testFormatShellWithEditorconfig() throws Exception { + String fileDir = "shell/shfmt/with-config/"; setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - setFile("other.sh").toResource(fileDir + "other.sh"); + setFile("scripts/other.sh").toResource(fileDir + "other.sh"); setFile(".editorconfig").toResource(fileDir + ".editorconfig"); writePomWithShellSteps(""); mavenRunner().withArguments("spotless:apply").runNoError(); assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); - assertFile("other.sh").sameAsResource(fileDir + "other.clean"); + assertFile("scripts/other.sh").sameAsResource(fileDir + "other.clean"); } @Test - public void testMultiFileFormatShellWithoutEditorconfig() throws Exception { - String fileDir = "shell/shfmt/multifile/without-config/"; + public void testFormatShellWithoutEditorconfig() throws Exception { + String fileDir = "shell/shfmt/without-config/"; setFile("shfmt.sh").toResource(fileDir + "shfmt.sh"); - setFile("other.sh").toResource(fileDir + "other.sh"); + setFile("scripts/other.sh").toResource(fileDir + "other.sh"); writePomWithShellSteps(""); mavenRunner().withArguments("spotless:apply").runNoError(); assertFile("shfmt.sh").sameAsResource(fileDir + "shfmt.clean"); - assertFile("other.sh").sameAsResource(fileDir + "other.clean"); + assertFile("scripts/other.sh").sameAsResource(fileDir + "other.clean"); } } diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig deleted file mode 100644 index 8a7d8d6043..0000000000 --- a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -root = true - -[*] -charset = utf-8 - -[*.sh] -indent_style = space -indent_size = 2 -space_redirects = true -switch_case_indent = true diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean deleted file mode 100644 index c1b9b25064..0000000000 --- a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.clean +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -function foo() { - if [ -x $file ]; then - myArray=(item1 item2 item3) - elif [ $file1 -nt $file2 ]; then - unset myArray - else - echo "Usage: $0 file ..." - fi -} - -for ((i = 0; i < 5; i++)); do - read -p r - print -n $r - wait $! -done diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh deleted file mode 100644 index 9d15c477d4..0000000000 --- a/testlib/src/main/resources/shell/shfmt/singlefile/with-config/shfmt.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -function foo() { - if [ -x $file ]; then - myArray=(item1 item2 item3) - elif [ $file1 -nt $file2 ] - then - unset myArray - else -echo "Usage: $0 file ..." - fi -} - -for ((i = 0; i < 5; i++)); do - read -p r - print -n $r - wait $! -done diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean deleted file mode 100644 index 80386d472e..0000000000 --- a/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.clean +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -function foo() { - if [ -x $file ]; then - myArray=(item1 item2 item3) - elif [ $file1 -nt $file2 ]; then - unset myArray - else - echo "Usage: $0 file ..." - fi -} - -for ((i = 0; i < 5; i++)); do - read -p r - print -n $r - wait $! -done diff --git a/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh deleted file mode 100644 index 9d15c477d4..0000000000 --- a/testlib/src/main/resources/shell/shfmt/singlefile/without-config/shfmt.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -function foo() { - if [ -x $file ]; then - myArray=(item1 item2 item3) - elif [ $file1 -nt $file2 ] - then - unset myArray - else -echo "Usage: $0 file ..." - fi -} - -for ((i = 0; i < 5; i++)); do - read -p r - print -n $r - wait $! -done diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/.editorconfig b/testlib/src/main/resources/shell/shfmt/with-config/.editorconfig similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/with-config/.editorconfig rename to testlib/src/main/resources/shell/shfmt/with-config/.editorconfig diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.clean b/testlib/src/main/resources/shell/shfmt/with-config/other.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/with-config/other.clean rename to testlib/src/main/resources/shell/shfmt/with-config/other.clean diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/other.sh b/testlib/src/main/resources/shell/shfmt/with-config/other.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/with-config/other.sh rename to testlib/src/main/resources/shell/shfmt/with-config/other.sh diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/with-config/shfmt.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.clean rename to testlib/src/main/resources/shell/shfmt/with-config/shfmt.clean diff --git a/testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/with-config/shfmt.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/with-config/shfmt.sh rename to testlib/src/main/resources/shell/shfmt/with-config/shfmt.sh diff --git a/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.clean b/testlib/src/main/resources/shell/shfmt/without-config/other.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/without-config/other.clean rename to testlib/src/main/resources/shell/shfmt/without-config/other.clean diff --git a/testlib/src/main/resources/shell/shfmt/multifile/without-config/other.sh b/testlib/src/main/resources/shell/shfmt/without-config/other.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/without-config/other.sh rename to testlib/src/main/resources/shell/shfmt/without-config/other.sh diff --git a/testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.clean b/testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.clean rename to testlib/src/main/resources/shell/shfmt/without-config/shfmt.clean diff --git a/testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.sh b/testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh similarity index 100% rename from testlib/src/main/resources/shell/shfmt/multifile/without-config/shfmt.sh rename to testlib/src/main/resources/shell/shfmt/without-config/shfmt.sh diff --git a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java index c2d8edd15b..2d764d877f 100644 --- a/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/shell/ShfmtStepTest.java @@ -26,7 +26,7 @@ public class ShfmtStepTest extends ResourceHarness { @Test void testWithEditorconfig() throws Exception { try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { - final String fileDir = "shell/shfmt/singlefile/with-config/"; + final String fileDir = "shell/shfmt/with-config/"; final String dirtyFile = fileDir + "shfmt.sh"; final String cleanFile = fileDir + "shfmt.clean"; @@ -39,7 +39,7 @@ void testWithEditorconfig() throws Exception { @Test void testWithoutEditorconfig() throws Exception { try (StepHarnessWithFile harness = StepHarnessWithFile.forStep(this, ShfmtStep.withVersion(ShfmtStep.defaultVersion()).create())) { - final String fileDir = "shell/shfmt/singlefile/without-config/"; + final String fileDir = "shell/shfmt/without-config/"; final String dirtyFile = fileDir + "shfmt.sh"; final String cleanFile = fileDir + "shfmt.clean"; From 28b079cf42d2b2cc3b0f6847b4a0aeef86e548be Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Mon, 5 Feb 2024 16:30:58 -0500 Subject: [PATCH 10/15] Include shfmt check in ci build --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a767bc2bb..ba6d40388f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: pull_request: push: - branches: [main] + branches: [ main ] workflow_dispatch: concurrency: @@ -23,17 +23,21 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Install JDK 11 uses: actions/setup-java@v4 with: distribution: "temurin" java-version: 11 + - name: gradle caching uses: gradle/actions/setup-gradle@v3 with: gradle-home-cache-cleanup: true + - name: spotlessCheck run: ./gradlew spotlessCheck + - name: assemble testClasses run: ./gradlew assemble testClasses build: @@ -41,10 +45,10 @@ jobs: strategy: fail-fast: false matrix: - kind: [maven, gradle] + kind: [ maven, gradle ] # Test on the latest Java version once Gradle & Maven support it. - jre: [11, 17, 21] - os: [ubuntu-latest] + jre: [ 11, 17, 21 ] + os: [ ubuntu-latest ] include: # test windows at the diagonals of the above matrix - kind: maven @@ -57,28 +61,48 @@ jobs: - kind: npm jre: 11 os: ubuntu-latest + - kind: shfmt + jre: 11 + os: ubuntu-latest + shfmt-version: 3.7.0 runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 + - name: Install JDK ${{ matrix.distribution }} ${{ matrix.java_version }} uses: actions/setup-java@v4 with: distribution: "temurin" java-version: ${{ matrix.jre }} + - name: gradle caching uses: gradle/actions/setup-gradle@v3 with: gradle-home-cache-cleanup: true + - name: build (maven-only) if: matrix.kind == 'maven' run: ./gradlew :plugin-maven:build -x spotlessCheck + - name: build (everything-but-maven) if: matrix.kind == 'gradle' run: ./gradlew build -x spotlessCheck -PSPOTLESS_EXCLUDE_MAVEN=true + - name: test npm if: matrix.kind == 'npm' run: ./gradlew testNpm + + - name: Install shfmt + if: matrix.kind == 'shfmt' + run: | + curl -sSfL "https://github.com/mvdan/sh/releases/download/v${{ matrix.shfmt-version }}/shfmt_v${{ matrix.shfmt-version }}_linux_amd64" -o /usr/local/bin/shfmt + chmod +x /usr/local/bin/shfmt + + - name: Test shfmt + if: matrix.kind == 'shfmt' + run: ./gradlew testShfmt + - name: junit result uses: mikepenz/action-junit-report@v4 if: always() # always run even if the previous step fails From 62f27ca84ec8c89094057b2850a9fdaba24fc8ae Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Mon, 5 Feb 2024 16:58:54 -0500 Subject: [PATCH 11/15] Fix version regex to only match digits and '.' --- .github/workflows/ci.yml | 4 ++-- lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba6d40388f..58b3e9bd8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,8 +96,8 @@ jobs: - name: Install shfmt if: matrix.kind == 'shfmt' run: | - curl -sSfL "https://github.com/mvdan/sh/releases/download/v${{ matrix.shfmt-version }}/shfmt_v${{ matrix.shfmt-version }}_linux_amd64" -o /usr/local/bin/shfmt - chmod +x /usr/local/bin/shfmt + sudo curl -sSfL "https://github.com/mvdan/sh/releases/download/v${{ matrix.shfmt-version }}/shfmt_v${{ matrix.shfmt-version }}_linux_amd64" -o /usr/local/bin/shfmt + sudo chmod +x /usr/local/bin/shfmt - name: Test shfmt if: matrix.kind == 'shfmt' diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index 4203a8ed7f..971dce6b03 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -74,7 +74,7 @@ private State createState() throws IOException, InterruptedException { "\n github issue to handle this better: https://github.com/diffplug/spotless/issues/673"; final ForeignExe exe = ForeignExe.nameAndVersion("shfmt", version) .pathToExe(pathToExe) - .versionRegex(Pattern.compile("(\\S*)")) + .versionRegex(Pattern.compile("([\\d.]+)")) .fixCantFind(howToInstall) .fixWrongVersion( "You can tell Spotless to use the version you already have with {@code shfmt('{versionFound}')}" + From 42b43dc2eac7891178411274b80cf8364623d6b0 Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Mon, 5 Feb 2024 16:59:21 -0500 Subject: [PATCH 12/15] Remove sudo, it should be unnecessary --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58b3e9bd8a..ba6d40388f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,8 +96,8 @@ jobs: - name: Install shfmt if: matrix.kind == 'shfmt' run: | - sudo curl -sSfL "https://github.com/mvdan/sh/releases/download/v${{ matrix.shfmt-version }}/shfmt_v${{ matrix.shfmt-version }}_linux_amd64" -o /usr/local/bin/shfmt - sudo chmod +x /usr/local/bin/shfmt + curl -sSfL "https://github.com/mvdan/sh/releases/download/v${{ matrix.shfmt-version }}/shfmt_v${{ matrix.shfmt-version }}_linux_amd64" -o /usr/local/bin/shfmt + chmod +x /usr/local/bin/shfmt - name: Test shfmt if: matrix.kind == 'shfmt' From fc82b24c1381f47d5f70b5a1acae68b9de99c33c Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Mon, 5 Feb 2024 17:05:33 -0500 Subject: [PATCH 13/15] Fix comment --- lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index 971dce6b03..9580a4876a 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -101,7 +101,7 @@ static class State implements Serializable { String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { if (args == null) { // args will be reused during a single spotless task execution, - // so this "prefix" is being "cached" for each spotless task. + // so this "prefix" is being "cached" for each spotless format with shfmt. args = List.of(exe.confirmVersionAndGetAbsolutePath(), "--filename"); } From 06325f8f8246172c0c5f691ec3c039f07bc83572 Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Mon, 5 Feb 2024 17:12:23 -0500 Subject: [PATCH 14/15] Add shfmt man page link to gradle readme --- plugin-gradle/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 89d72e034b..c7feb3559e 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -1004,7 +1004,7 @@ spotless { [homepage](https://github.com/mvdan/sh). [changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md). When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.editorconfig`. -Refer to the `shfmt` main page for `.editorconfig` settings. +Refer to the `shfmt` [man page](https://github.com/mvdan/sh/blob/master/cmd/shfmt/shfmt.1.scd) for `.editorconfig` settings. ```gradle shfmt('3.7.0') // version is optional From 6e52d6e8e7d8eea5a20568b6f4fefe5683c217b2 Mon Sep 17 00:00:00 2001 From: Tyler Crawford Date: Thu, 8 Feb 2024 08:49:13 -0500 Subject: [PATCH 15/15] Undo yaml formatting changes, update spotless to Spotless --- .github/workflows/ci.yml | 20 ++++--------------- .../diffplug/spotless/shell/ShfmtStep.java | 4 ++-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba6d40388f..5d4cfb57e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: pull_request: push: - branches: [ main ] + branches: [main] workflow_dispatch: concurrency: @@ -23,21 +23,17 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Install JDK 11 uses: actions/setup-java@v4 with: distribution: "temurin" java-version: 11 - - name: gradle caching uses: gradle/actions/setup-gradle@v3 with: gradle-home-cache-cleanup: true - - name: spotlessCheck run: ./gradlew spotlessCheck - - name: assemble testClasses run: ./gradlew assemble testClasses build: @@ -45,10 +41,10 @@ jobs: strategy: fail-fast: false matrix: - kind: [ maven, gradle ] + kind: [maven, gradle] # Test on the latest Java version once Gradle & Maven support it. - jre: [ 11, 17, 21 ] - os: [ ubuntu-latest ] + jre: [11, 17, 21] + os: [ubuntu-latest] include: # test windows at the diagonals of the above matrix - kind: maven @@ -69,40 +65,32 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Install JDK ${{ matrix.distribution }} ${{ matrix.java_version }} uses: actions/setup-java@v4 with: distribution: "temurin" java-version: ${{ matrix.jre }} - - name: gradle caching uses: gradle/actions/setup-gradle@v3 with: gradle-home-cache-cleanup: true - - name: build (maven-only) if: matrix.kind == 'maven' run: ./gradlew :plugin-maven:build -x spotlessCheck - - name: build (everything-but-maven) if: matrix.kind == 'gradle' run: ./gradlew build -x spotlessCheck -PSPOTLESS_EXCLUDE_MAVEN=true - - name: test npm if: matrix.kind == 'npm' run: ./gradlew testNpm - - name: Install shfmt if: matrix.kind == 'shfmt' run: | curl -sSfL "https://github.com/mvdan/sh/releases/download/v${{ matrix.shfmt-version }}/shfmt_v${{ matrix.shfmt-version }}_linux_amd64" -o /usr/local/bin/shfmt chmod +x /usr/local/bin/shfmt - - name: Test shfmt if: matrix.kind == 'shfmt' run: ./gradlew testShfmt - - name: junit result uses: mikepenz/action-junit-report@v4 if: always() # always run even if the previous step fails diff --git a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java index 9580a4876a..46f833bd0d 100644 --- a/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java @@ -100,8 +100,8 @@ static class State implements Serializable { String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { if (args == null) { - // args will be reused during a single spotless task execution, - // so this "prefix" is being "cached" for each spotless format with shfmt. + // args will be reused during a single Spotless task execution, + // so this "prefix" is being "cached" for each Spotless format with shfmt. args = List.of(exe.confirmVersionAndGetAbsolutePath(), "--filename"); }