Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable up-to-date checking in Maven plugin by default #1621

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
* You can now put the filename into a license header template with `$FILE`. ([#1605](https://github.com/diffplug/spotless/pull/1605) fixes [#1147](https://github.com/diffplug/spotless/issues/1147))
### Fixed
* `licenseHeader` default pattern for Java files is updated to `(package|import|public|class|module) `. ([#1614](https://github.com/diffplug/spotless/pull/1614))
### Changes
* Enable incremental up-to-date checking by default. ([#1621](https://github.com/diffplug/spotless/pull/1621))

## [2.34.0] - 2023-02-27
### Added
Expand Down
2 changes: 1 addition & 1 deletion plugin-maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1262,7 +1262,7 @@ To define what lines to skip at the beginning of such files, fill the `skipLines

## Incremental up-to-date checking and formatting

**This feature is turned off by default.**
**This feature is enabled by default starting from version 2.35.0.**

Execution of `spotless:check` and `spotless:apply` for large projects can take time.
By default, Spotless Maven plugin needs to read and format each source file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo {
private String setLicenseHeaderYearsFromGitHistory;

@Parameter
private UpToDateChecking upToDateChecking;
private UpToDateChecking upToDateChecking = UpToDateChecking.enabled();

protected abstract void process(Iterable<File> files, Formatter formatter, UpToDateChecker upToDateChecker) throws MojoExecutionException;

Expand Down Expand Up @@ -373,9 +373,9 @@ private UpToDateChecker createUpToDateChecker(Iterable<Formatter> formatters) {
}
final UpToDateChecker checker;
if (upToDateChecking != null && upToDateChecking.isEnabled()) {
getLog().info("Up-to-date checking enabled");
checker = UpToDateChecker.forProject(project, indexFile, formatters, getLog());
} else {
getLog().info("Up-to-date checking disabled");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed logging slightly because disabled up-to-date checking will be an uncommon path that requires explicit configuration. Thus, the plugin should log something on such an uncommon path

checker = UpToDateChecker.noop(project, indexFile, getLog());
}
return UpToDateChecker.wrapWithBuildContext(checker, buildContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Objects;

import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.project.MavenProject;

import com.diffplug.spotless.Formatter;
Expand All @@ -43,10 +44,7 @@ private PluginFingerprint(String value) {
}

static PluginFingerprint from(MavenProject project, Iterable<Formatter> formatters) {
Plugin spotlessPlugin = project.getPlugin(SPOTLESS_PLUGIN_KEY);
if (spotlessPlugin == null) {
throw new IllegalArgumentException("Spotless plugin absent from the project: " + project);
}
Plugin spotlessPlugin = findSpotlessPlugin(project);
byte[] digest = digest(spotlessPlugin, formatters);
String value = Base64.getEncoder().encodeToString(digest);
return new PluginFingerprint(value);
Expand Down Expand Up @@ -86,6 +84,24 @@ public String toString() {
return "PluginFingerprint[" + value + "]";
}

private static Plugin findSpotlessPlugin(MavenProject project) {
// Try to find the plugin instance from <build><plugins><plugin> XML element
Plugin plugin = project.getPlugin(SPOTLESS_PLUGIN_KEY);
if (plugin == null) {
// Try to find the plugin instance from <build><pluginManagement><plugins><plugin> XML element. Useful when
// the current module is a parent of a multimodule project
PluginManagement pluginManagement = project.getPluginManagement();
if (pluginManagement != null) {
plugin = pluginManagement.getPluginsAsMap().get(SPOTLESS_PLUGIN_KEY);
}
}

if (plugin == null) {
throw new IllegalArgumentException("Spotless plugin absent from the project: " + project);
}
return plugin;
}

private static byte[] digest(Plugin plugin, Iterable<Formatter> formatters) {
try (ObjectDigestOutputStream out = ObjectDigestOutputStream.create()) {
out.writeObject(plugin.getVersion());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2022 DiffPlug
* Copyright 2021-2023 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,4 +38,10 @@ public boolean isEnabled() {
public Path getIndexFile() {
return indexFile == null ? null : new File(indexFile).toPath();
}

public static UpToDateChecking enabled() {
UpToDateChecking upToDateChecking = new UpToDateChecking();
upToDateChecking.enabled = true;
return upToDateChecking;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,31 @@ class MultiModuleProjectTest extends MavenIntegrationHarness {
@Test
void testConfigurationDependency() throws Exception {
/*
create a multi-module project with the following stucture:
create a multi-module project with the following structure:

/junit-tmp-dir
├── config
   ├── pom.xml
   └── src/main/resources/configs
   ├── eclipse-formatter.xml
   └── scalafmt.conf
├── pom.xml
└── src/main/resources/configs
├── eclipse-formatter.xml
└── scalafmt.conf
├── mvnw
├── mvnw.cmd
├── one
   ├── pom.xml
   └── src
   ├── main/java/test1.java
   └── test/java/test2.java
├── pom.xml
└── src
├── main/java/test1.java
└── test/java/test2.java
├── two
   ├── pom.xml
   └── src
   ├── main/java/test1.java
   └── test/java/test2.java
├── pom.xml
└── src
├── main/java/test1.java
└── test/java/test2.java
├── three
   ├── pom.xml
   └── src
   ├── main/scala/test1.scala
   └── test/scala/test2.scala
├── pom.xml
└── src
├── main/scala/test1.scala
└── test/scala/test2.scala
├── pom.xml
├── .mvn
├── mvnw
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
import java.io.ByteArrayInputStream;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.ReaderFactory;
Expand Down Expand Up @@ -106,14 +109,45 @@ void emptyFingerprint() {
}

@Test
void failsWhenProjectDoesNotContainSpotlessPlugin() {
void failsForProjectWithoutSpotlessPlugin() {
MavenProject projectWithoutSpotless = new MavenProject();

assertThatThrownBy(() -> PluginFingerprint.from(projectWithoutSpotless, FORMATTERS))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Spotless plugin absent from the project");
}

@Test
void buildsFingerprintForProjectWithSpotlessPluginInBuildPlugins() {
MavenProject project = new MavenProject();
Plugin spotlessPlugin = new Plugin();
spotlessPlugin.setGroupId("com.diffplug.spotless");
spotlessPlugin.setArtifactId("spotless-maven-plugin");
spotlessPlugin.setVersion("1.2.3");
project.getBuild().addPlugin(spotlessPlugin);

PluginFingerprint fingerprint = PluginFingerprint.from(project, Collections.emptyList());

assertThat(fingerprint).isNotNull();
}

@Test
void buildsFingerprintForProjectWithSpotlessPluginInPluginManagement() {
MavenProject project = new MavenProject();
Plugin spotlessPlugin = new Plugin();
spotlessPlugin.setGroupId("com.diffplug.spotless");
spotlessPlugin.setArtifactId("spotless-maven-plugin");
spotlessPlugin.setVersion("1.2.3");
project.getBuild().addPlugin(spotlessPlugin);
PluginManagement pluginManagement = new PluginManagement();
pluginManagement.addPlugin(spotlessPlugin);
project.getBuild().setPluginManagement(pluginManagement);

PluginFingerprint fingerprint = PluginFingerprint.from(project, Collections.emptyList());

assertThat(fingerprint).isNotNull();
}

private MavenProject mavenProject(String spotlessVersion) throws Exception {
String xml = createPomXmlContent(spotlessVersion, new String[0], new String[0]);
return new MavenProject(readPom(xml));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@

class UpToDateCheckingTest extends MavenIntegrationHarness {

private static final String DISABLED_MESSAGE = "Up-to-date checking disabled";

@Test
void upToDateCheckingDisabledByDefault() throws Exception {
void upToDateCheckingEnabledByDefault() throws Exception {
writePom(
"<java>",
" <googleJavaFormat/>",
Expand All @@ -41,75 +43,53 @@ void upToDateCheckingDisabledByDefault() throws Exception {
List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).doesNotContain("Up-to-date checking enabled");
assertThat(output).doesNotContain(DISABLED_MESSAGE);
assertFormatted(files);
}

@Test
void enableUpToDateChecking() throws Exception {
void explicitlyEnableUpToDateChecking() throws Exception {
writePomWithUpToDateCheckingEnabled(true);

List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).contains("Up-to-date checking enabled");
assertThat(output).doesNotContain(DISABLED_MESSAGE);
assertFormatted(files);
}

@Test
void enableUpToDateCheckingWithPluginDependencies() throws Exception {
writePomWithPluginManagementAndDependency();
void explicitlyDisableUpToDateChecking() throws Exception {
writePomWithUpToDateCheckingEnabled(false);

List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).contains("Up-to-date checking enabled");
assertThat(output).contains(DISABLED_MESSAGE);
assertFormatted(files);
}

@Test
void enableUpToDateCheckingWithPluginDependenciesMaven3_6_3() throws Exception {
void enableUpToDateCheckingWithPluginDependencies() throws Exception {
writePomWithPluginManagementAndDependency();

setFile(".mvn/wrapper/maven-wrapper.properties").toContent("distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip\n");

List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).contains("Up-to-date checking enabled");
assertThat(output).doesNotContain(DISABLED_MESSAGE);
assertFormatted(files);
}

private void writePomWithPluginManagementAndDependency() throws IOException {
setFile("pom.xml").toContent(createPomXmlContent("/pom-test-management.xml.mustache",
null,
null,
new String[]{
"<java>",
" <googleJavaFormat/>",
"</java>",
"<upToDateChecking>",
" <enabled>true</enabled>",
"</upToDateChecking>"},
new String[]{
"<dependencies>",
" <dependency>",
" <groupId>javax.inject</groupId>",
" <artifactId>javax.inject</artifactId>",
" <version>1</version>",
" </dependency>",
"</dependencies>"},
null));
}

@Test
void disableUpToDateChecking() throws Exception {
writePomWithUpToDateCheckingEnabled(false);
void enableUpToDateCheckingWithPluginDependenciesMaven3_6_3() throws Exception {
writePomWithPluginManagementAndDependency();

setFile(".mvn/wrapper/maven-wrapper.properties").toContent("distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip\n");

List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).doesNotContain("Up-to-date checking enabled");
assertThat(output).doesNotContain(DISABLED_MESSAGE);
assertFormatted(files);
}

Expand All @@ -124,7 +104,7 @@ void enableUpToDateCheckingCustomIndexFile() throws Exception {
List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).contains("Up-to-date checking enabled");
assertThat(output).doesNotContain(DISABLED_MESSAGE);
assertFormatted(files);
assertThat(indexFile.getParent()).exists();
assertThat(indexFile).exists();
Expand All @@ -143,7 +123,7 @@ void disableUpToDateCheckingCustomIndexFile() throws Exception {
List<File> files = writeUnformattedFiles(1);
String output = runSpotlessApply();

assertThat(output).doesNotContain("Up-to-date checking enabled");
assertThat(output).contains(DISABLED_MESSAGE);
assertFormatted(files);
assertThat(indexFile.getParent()).exists();
assertThat(indexFile).doesNotExist();
Expand Down Expand Up @@ -215,6 +195,25 @@ void spotlessCheckRecordsUnformattedFiles() throws Exception {
assertSpotlessCheckSkipped(files, checkOutput3);
}

private void writePomWithPluginManagementAndDependency() throws IOException {
setFile("pom.xml").toContent(createPomXmlContent("/pom-test-management.xml.mustache",
null,
null,
new String[]{
"<java>",
" <googleJavaFormat/>",
"</java>"},
new String[]{
"<dependencies>",
" <dependency>",
" <groupId>javax.inject</groupId>",
" <artifactId>javax.inject</artifactId>",
" <version>1</version>",
" </dependency>",
"</dependencies>"},
null));
}

private void writePomWithUpToDateCheckingEnabled(boolean enabled) throws IOException {
writePom(
"<java>",
Expand Down