Skip to content

Commit 17609c7

Browse files
authored
Cache git dirty files in maven plugin (#2805 closes #2816)
2 parents acda497 + 76b19c1 commit 17609c7

2 files changed

Lines changed: 56 additions & 9 deletions

File tree

plugin-maven/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
55
## [Unreleased]
66
### Added
77
- Add the ability to specify a wildcard version (`*`) for external formatter executables. ([#2757](https://github.com/diffplug/spotless/issues/2757))
8+
### Changes
9+
- Dramatic (~100x) performance improvement when using git `ratchetFrom`. ([#2805](https://github.com/diffplug/spotless/pull/2805))
810
### Fixed
911
- [fix] `NPE` due to workingTreeIterator being null for git ignored files. #911 ([#2771](https://github.com/diffplug/spotless/issues/2771))
1012
- Prevent race conditions when multiple npm-based formatters launch the server process simultaneously while sharing the same `node_modules` directory. ([#2786](https://github.com/diffplug/spotless/pull/2786))

plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2025 DiffPlug
2+
* Copyright 2020-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,11 @@
1818
import java.io.File;
1919
import java.io.IOException;
2020
import java.nio.file.Path;
21+
import java.util.HashMap;
2122
import java.util.HashSet;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Objects;
2226
import java.util.Set;
2327
import java.util.stream.Collectors;
2428

@@ -30,6 +34,9 @@
3034
import com.diffplug.spotless.extra.GitRatchet;
3135

3236
final class GitRatchetMaven extends GitRatchet<File> {
37+
38+
Map<Key, Set<String>> cache = new HashMap<>();
39+
3340
private GitRatchetMaven() {}
3441

3542
@Override
@@ -55,16 +62,32 @@ static GitRatchetMaven instance() {
5562
return instance;
5663
}
5764

58-
Iterable<String> getDirtyFiles(File baseDir, String ratchetFrom) throws IOException {
65+
List<String> getDirtyFiles(File baseDir, String ratchetFrom) throws IOException {
5966
Repository repository = repositoryFor(baseDir);
60-
ObjectId sha = rootTreeShaOf(baseDir, ratchetFrom);
67+
Set<String> dirtyPaths = null;
68+
Key key = new Key(repository.getIdentifier(), ratchetFrom);
69+
synchronized (this) {
70+
if (cache.containsKey(key)) {
71+
dirtyPaths = cache.get(key);
72+
} else {
73+
dirtyPaths = getDirtyFilesInternal(repository, baseDir, ratchetFrom);
74+
cache.put(key, dirtyPaths);
75+
}
76+
}
77+
78+
Path baseDirPath = Path.of(baseDir.getPath());
79+
String workTreePath = repository.getWorkTree().getPath();
6180

81+
return dirtyPaths.stream()
82+
.map(path -> baseDirPath.relativize(Path.of(workTreePath, path)).toString())
83+
.collect(Collectors.toList());
84+
}
85+
86+
Set<String> getDirtyFilesInternal(Repository repository, File baseDir, String ratchetFrom) throws IOException {
87+
ObjectId sha = rootTreeShaOf(baseDir, ratchetFrom);
6288
IndexDiff indexDiff = new IndexDiff(repository, sha, new FileTreeIterator(repository));
6389
indexDiff.diff();
6490

65-
String workTreePath = repository.getWorkTree().getPath();
66-
Path baseDirPath = Path.of(baseDir.getPath());
67-
6891
Set<String> dirtyPaths = new HashSet<>(indexDiff.getChanged());
6992
dirtyPaths.addAll(indexDiff.getAdded());
7093
dirtyPaths.addAll(indexDiff.getConflicting());
@@ -91,8 +114,30 @@ Iterable<String> getDirtyFiles(File baseDir, String ratchetFrom) throws IOExcept
91114
// A file can be modified in the index but removed in the tree
92115
dirtyPaths.removeAll(indexDiff.getMissing());
93116

94-
return dirtyPaths.stream()
95-
.map(path -> baseDirPath.relativize(Path.of(workTreePath, path)).toString())
96-
.collect(Collectors.toList());
117+
return dirtyPaths;
118+
}
119+
120+
private static final class Key {
121+
private final String identifier;
122+
private final String ratchetFrom;
123+
124+
private Key(String identifier, String ratchetFrom) {
125+
this.identifier = identifier;
126+
this.ratchetFrom = ratchetFrom;
127+
}
128+
129+
@Override
130+
public boolean equals(Object o) {
131+
if (o == null || getClass() != o.getClass()) {
132+
return false;
133+
}
134+
Key key = (Key) o;
135+
return Objects.equals(identifier, key.identifier) && Objects.equals(ratchetFrom, key.ratchetFrom);
136+
}
137+
138+
@Override
139+
public int hashCode() {
140+
return Objects.hash(identifier, ratchetFrom);
141+
}
97142
}
98143
}

0 commit comments

Comments
 (0)