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

Speedup GIT_ATTRIBUTES #1838

Merged
merged 7 commits into from
Sep 28, 2023
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
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
the version accordingly. ([#1804](https://github.com/diffplug/spotless/issues/1804)).
* Support for `google-java-format`'s `skip-javadoc-formatting` option. ([#1793](https://github.com/diffplug/spotless/pull/1793))
* Support configuration of mirrors for P2 repositories in maven DSL ([#1697](https://github.com/diffplug/spotless/issues/1697)).
* New line endings mode `GIT_ATTRIBUTES_FAST_ALLSAME`. ([#1838](https://github.com/diffplug/spotless/pull/1838))
### Fixed
* Fix support for plugins when using Prettier version `3.0.0` and newer. ([#1802](https://github.com/diffplug/spotless/pull/1802))
* Fix configuration cache issue around `external process started '/usr/bin/git --version'`. ([#1806](https://github.com/diffplug/spotless/issues/1806))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,42 @@ public final class GitAttributesLineEndings {
// prevent direct instantiation
private GitAttributesLineEndings() {}

/**
* Creates a line-endings policy which matches {@link #create(File, Supplier)},
* which is much faster at the cost that every file under the policy
* is assumed to have the same line endings as the first file.
*/
public static LineEnding.Policy createFastAllSame(File projectDir, Supplier<Iterable<File>> toFormat) {
return new LazyAllTheSame(projectDir, toFormat);
}

static class LazyAllTheSame extends LazyForwardingEquality<String> implements LineEnding.Policy {
private static final long serialVersionUID = 727912266173243664L;
transient File projectDir;
transient Supplier<Iterable<File>> toFormat;

public LazyAllTheSame(File projectDir, Supplier<Iterable<File>> toFormat) {
this.projectDir = projectDir;
this.toFormat = toFormat;
}

@Override
protected String calculateState() throws Exception {
var files = toFormat.get().iterator();
if (files.hasNext()) {
Runtime runtime = new RuntimeInit(projectDir).atRuntime();
return runtime.getEndingFor(files.next());
} else {
return LineEnding.UNIX.str();
}
}

@Override
public String getEndingFor(File file) {
return state();
}
}

/**
* Creates a line-endings policy whose serialized state is relativized against projectDir,
* at the cost of eagerly evaluating the line-ending state of every target file when the
Expand Down
45 changes: 24 additions & 21 deletions lib/src/main/java/com/diffplug/spotless/LineEnding.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2022 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.
Expand All @@ -19,11 +19,8 @@
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Supplier;

import javax.annotation.Nullable;

/**
* Represents the line endings which should be written by the tool.
*/
Expand All @@ -37,6 +34,14 @@ public Policy createPolicy() {
return super.createPolicy();
}
},
/** Uses the same line endings as Git, and assumes that every single file being formatted will have the same line ending. */
GIT_ATTRIBUTES_FAST_ALLSAME {
/** .gitattributes is path-specific, so you must use {@link LineEnding#createPolicy(File, Supplier)}. */
@Override @Deprecated
public Policy createPolicy() {
return super.createPolicy();
}
},
/** {@code \n} on unix systems, {@code \r\n} on windows systems. */
PLATFORM_NATIVE,
/** {@code \r\n} */
Expand All @@ -51,33 +56,31 @@ public Policy createPolicy() {
public Policy createPolicy(File projectDir, Supplier<Iterable<File>> toFormat) {
Objects.requireNonNull(projectDir, "projectDir");
Objects.requireNonNull(toFormat, "toFormat");
if (this != GIT_ATTRIBUTES) {
return createPolicy();
String gitAttributesMethod;
if (this == GIT_ATTRIBUTES) {
gitAttributesMethod = "create";
} else if (this == GIT_ATTRIBUTES_FAST_ALLSAME) {
gitAttributesMethod = "createFastAllSame";
} else {
if (gitAttributesPolicyCreator == null) {
try {
Class<?> clazz = Class.forName("com.diffplug.spotless.extra.GitAttributesLineEndings");
Method method = clazz.getMethod("create", File.class, Supplier.class);
gitAttributesPolicyCreator = (proj, target) -> ThrowingEx.get(() -> (Policy) method.invoke(null, proj, target));
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
throw new IllegalStateException("LineEnding.GIT_ATTRIBUTES requires the spotless-lib-extra library, but it is not on the classpath", e);
}
}
// gitAttributesPolicyCreator will always be nonnull at this point
return gitAttributesPolicyCreator.apply(projectDir, toFormat);
return createPolicy();
}
try {
Class<?> clazz = Class.forName("com.diffplug.spotless.extra.GitAttributesLineEndings");
Method method = clazz.getMethod(gitAttributesMethod, File.class, Supplier.class);
return ThrowingEx.get(() -> (Policy) method.invoke(null, projectDir, toFormat));
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
throw new IllegalStateException("LineEnding.GIT_ATTRIBUTES requires the spotless-lib-extra library, but it is not on the classpath", e);
}
}

private static volatile @Nullable BiFunction<File, Supplier<Iterable<File>>, Policy> gitAttributesPolicyCreator;

// @formatter:off
/** Should use {@link #createPolicy(File, Supplier)} instead, but this will work iff its a path-independent LineEnding policy. */
public Policy createPolicy() {
switch (this) {
case PLATFORM_NATIVE: return _platformNativePolicy;
case WINDOWS: return WINDOWS_POLICY;
case UNIX: return UNIX_POLICY;
case MAC_CLASSIC: return MAC_CLASSIC_POLICY;
case MAC_CLASSIC: return MAC_CLASSIC_POLICY;
default: throw new UnsupportedOperationException(this + " is a path-specific line ending.");
}
}
Expand Down Expand Up @@ -121,7 +124,7 @@ public String str() {
case PLATFORM_NATIVE: return _platformNative;
case WINDOWS: return "\r\n";
case UNIX: return "\n";
case MAC_CLASSIC: return "\r";
case MAC_CLASSIC: return "\r";
default: throw new UnsupportedOperationException(this + " is a path-specific line ending.");
}
}
Expand Down
3 changes: 3 additions & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
* Fixed support for plugins when using Prettier version `3.0.0` and newer. ([#1802](https://github.com/diffplug/spotless/pull/1802))
### Changes
* Bump default `ktlint` version to latest `0.50.0` -> `1.0.0`. ([#1808](https://github.com/diffplug/spotless/pull/1808))
* **POSSIBLY BREAKING** the default line endings are now `GIT_ATTRIBUTES_FAST_ALLSAME` instead of `GIT_ATTRIBUTES`. ([#1838](https://github.com/diffplug/spotless/pull/1838))
* If all the files within a format have the same line endings, then there is no change in behavior.
* Fixes large performance regression. ([#1527](https://github.com/diffplug/spotless/issues/1527))

## [6.21.0] - 2023-08-29
### Added
Expand Down
4 changes: 2 additions & 2 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1425,12 +1425,12 @@ spotless {
encoding 'Cp1252' // except java, which will be Cp1252
```

Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `MAC_CLASSIC`, `PLATFORM_NATIVE`, and `GIT_ATTRIBUTES`. The default value is `GIT_ATTRIBUTES`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time.
Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `MAC_CLASSIC`, `PLATFORM_NATIVE`, `GIT_ATTRIBUTES`, and `GIT_ATTRIBUTES_FAST_ALLSAME`. The default value is `GIT_ATTRIBUTES_FAST_ALLSAME`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time. `FAST_ALLSAME` just means that Spotless can assume that every file being formatted has the same line endings ([more info](https://github.com/diffplug/spotless/pull/1838)).

You can easily set the line endings of different files using [a `.gitattributes` file](https://help.github.com/articles/dealing-with-line-endings/). Here's an example `.gitattributes` which sets all files to unix newlines: `* text eol=lf`.

<a name="custom"></a>
<a name="custom-rulwa"></a>
<a name="custom-steps"></a>

## Custom steps

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ RegisterDependenciesTask getRegisterDependenciesTask() {
}

/** Line endings (if any). */
LineEnding lineEndings = LineEnding.GIT_ATTRIBUTES;
LineEnding lineEndings = LineEnding.GIT_ATTRIBUTES_FAST_ALLSAME;

public LineEnding getLineEndings() {
return lineEndings;
Expand Down
3 changes: 3 additions & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
### Changes
* Bump default `flexmark` version to latest `0.64.0` -> `0.64.8`. ([#1801](https://github.com/diffplug/spotless/pull/1801))
* Bump default `ktlint` version to latest `0.50.0` -> `1.0.0`. ([#1808](https://github.com/diffplug/spotless/pull/1808))
* **POSSIBLY BREAKING** the default line endings are now `GIT_ATTRIBUTES_FAST_ALLSAME` instead of `GIT_ATTRIBUTES`. ([#1838](https://github.com/diffplug/spotless/pull/1838))
* If all the files within a format have the same line endings, then there is no change in behavior.
* Fixes large performance regression. ([#1527](https://github.com/diffplug/spotless/issues/1527))

## [2.39.0] - 2023-08-29
### 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 @@ -1586,7 +1586,7 @@ Spotless uses UTF-8 by default, but you can use [any encoding which Java support
</configuration>
```

Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `MAC_CLASSIC`, `PLATFORM_NATIVE`, and `GIT_ATTRIBUTES`. The default value is `GIT_ATTRIBUTES`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time.
Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `MAC_CLASSIC`, `PLATFORM_NATIVE`, `GIT_ATTRIBUTES`, and `GIT_ATTRIBUTES_FAST_ALLSAME`. The default value is `GIT_ATTRIBUTES_FAST_ALLSAME`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time. `FAST_ALLSAME` just means that Spotless can assume that every file being formatted has the same line endings ([more info](https://github.com/diffplug/spotless/pull/1838)).

You can easily set the line endings of different files using [a `.gitattributes` file](https://help.github.com/articles/dealing-with-line-endings/). Here's an example `.gitattributes` which sets all files to unix newlines: `* text eol=lf`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
public abstract class AbstractSpotlessMojo extends AbstractMojo {
private static final String DEFAULT_INDEX_FILE_NAME = "spotless-index";
private static final String DEFAULT_ENCODING = "UTF-8";
private static final String DEFAULT_LINE_ENDINGS = "GIT_ATTRIBUTES";
private static final String DEFAULT_LINE_ENDINGS = "GIT_ATTRIBUTES_FAST_ALLSAME";

/** Value to allow unsetting the ratchet inherited from parent pom configuration. */
static final String RATCHETFROM_NONE = "NONE";
Expand Down
Loading