diff --git a/CHANGES.md b/CHANGES.md index 7f6160b600..bed2af6281 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ This document is intended for Spotless developers. We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +* Clang and Black no longer break the build when the binary is unavailable, if they will not be run during that build ([#1257](https://github.com/diffplug/spotless/pull/1257)). ## [2.27.0] - 2022-06-30 ### Added diff --git a/lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java b/lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java index 5256739004..2bff28e64e 100644 --- a/lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 DiffPlug + * Copyright 2020-2022 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import javax.annotation.Nullable; @@ -75,14 +76,13 @@ private State createState() throws IOException, InterruptedException { "\n mac: brew install clang-format (TODO: how to specify version?)" + "\n linux: apt install clang-format (try clang-format-{version} with dropped minor versions)" + "\n github issue to handle this better: https://github.com/diffplug/spotless/issues/673"; - String exeAbsPath = ForeignExe.nameAndVersion("clang-format", version) + final ForeignExe exe = ForeignExe.nameAndVersion("clang-format", version) .pathToExe(pathToExe) .fixCantFind(howToInstall) .fixWrongVersion( "You can tell Spotless to use the version you already have with {@code clangFormat('{versionFound}')}" + - "or you can download the currently specified version, {version}.\n" + howToInstall) - .confirmVersionAndGetAbsolutePath(); - return new State(this, exeAbsPath); + "or you can download the currently specified version, {version}.\n" + howToInstall); + return new State(this, exe); } @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") @@ -91,24 +91,28 @@ static class State implements Serializable { // used for up-to-date checks and caching final String version; final @Nullable String style; + final transient ForeignExe exe; // used for executing - final transient List args; + private transient @Nullable List args; - State(ClangFormatStep step, String exeAbsPath) { + State(ClangFormatStep step, ForeignExe pathToExe) { this.version = step.version; this.style = step.style; - args = new ArrayList<>(2); - args.add(exeAbsPath); - if (style != null) { - args.add("--style=" + style); - } + this.exe = Objects.requireNonNull(pathToExe); } String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { - String[] processArgs = args.toArray(new String[args.size() + 1]); - // add an argument to the end - processArgs[args.size()] = "--assume-filename=" + file.getName(); - return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8); + if (args == null) { + final List tmpArgs = new ArrayList<>(); + tmpArgs.add(exe.confirmVersionAndGetAbsolutePath()); + if (style != null) { + tmpArgs.add("--style=" + style); + } + args = tmpArgs; + } + final String[] processArgs = args.toArray(new String[args.size() + 1]); + processArgs[processArgs.length - 1] = "--assume-filename=" + file.getName(); + return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8); } FormatterFunc.Closeable toFunc() { diff --git a/lib/src/main/java/com/diffplug/spotless/python/BlackStep.java b/lib/src/main/java/com/diffplug/spotless/python/BlackStep.java index 6a03d0d808..9bce2241dd 100644 --- a/lib/src/main/java/com/diffplug/spotless/python/BlackStep.java +++ b/lib/src/main/java/com/diffplug/spotless/python/BlackStep.java @@ -18,8 +18,7 @@ import java.io.IOException; import java.io.Serializable; import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; +import java.util.Objects; import java.util.regex.Pattern; import javax.annotation.Nullable; @@ -62,12 +61,11 @@ public FormatterStep create() { private State createState() throws IOException, InterruptedException { String trackingIssue = "\n github issue to handle this better: https://github.com/diffplug/spotless/issues/674"; - String exeAbsPath = ForeignExe.nameAndVersion("black", version) + ForeignExe exeAbsPath = ForeignExe.nameAndVersion("black", version) .pathToExe(pathToExe) .versionRegex(Pattern.compile("(?:black, version|black,|version) (\\S*)")) .fixCantFind("Try running {@code pip install black=={version}}, or else tell Spotless where it is with {@code black().pathToExe('path/to/executable')}" + trackingIssue) - .fixWrongVersion("Try running {@code pip install --force-reinstall black=={version}}, or else specify {@code black('{versionFound}')} to Spotless" + trackingIssue) - .confirmVersionAndGetAbsolutePath(); + .fixWrongVersion("Try running {@code pip install --force-reinstall black=={version}}, or else specify {@code black('{versionFound}')} to Spotless" + trackingIssue); return new State(this, exeAbsPath); } @@ -76,15 +74,19 @@ 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; // used for executing - final transient List args; + private transient @Nullable String[] args; - State(BlackStep step, String exeAbsPath) { + State(BlackStep step, ForeignExe exeAbsPath) { this.version = step.version; - this.args = Arrays.asList(exeAbsPath, "-"); + this.exe = Objects.requireNonNull(exeAbsPath); } String format(ProcessRunner runner, String input) throws IOException, InterruptedException { + if (args == null) { + args = new String[]{exe.confirmVersionAndGetAbsolutePath(), "-"}; + } return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8); } diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 02d8da736d..43a1fb1d24 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -3,6 +3,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`). ## [Unreleased] +### Added +* Clang and Black no longer break the build when the binary is unavailable, if they will not be run during that build ([#1257](https://github.com/diffplug/spotless/pull/1257)). ## [6.8.0] - 2022-06-30 ### Added diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 2cc389b7d3..3499aeab36 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,6 +3,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +* Clang and Black no longer break the build when the binary is unavailable, if they will not be run during that build ([#1257](https://github.com/diffplug/spotless/pull/1257)). ## [2.23.0] - 2022-06-30 ### Added