Skip to content

Commit

Permalink
Enable up-to-date checking in Maven plugin by default (#1621)
Browse files Browse the repository at this point in the history
  • Loading branch information
nedtwigg authored Mar 13, 2023
2 parents 7477651 + 24abb54 commit 18de088
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 64 deletions.
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");
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

0 comments on commit 18de088

Please sign in to comment.