From 778c5c0306353e62ce00a7b67d4112c0e1e04fb7 Mon Sep 17 00:00:00 2001 From: Shitikanth Kashyap Date: Fri, 9 Jan 2026 17:31:55 +0530 Subject: [PATCH 1/5] Cache git dirty files --- .../spotless/maven/AbstractSpotlessMojo.java | 8 +-- .../spotless/maven/DirtyFilesCache.java | 61 +++++++++++++++++++ .../spotless/maven/GitRatchetMaven.java | 4 +- 3 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 3952a8de70..01b80198eb 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -335,13 +335,7 @@ private List collectFilesFromGit(FormatterFactory formatterFactory, String MatchPatterns excludePatterns = MatchPatterns.from( withNormalizedFileSeparators(getExcludes(formatterFactory))); - Iterable dirtyFiles; - try { - dirtyFiles = GitRatchetMaven - .instance().getDirtyFiles(baseDir, ratchetFrom); - } catch (IOException e) { - throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); - } + Iterable dirtyFiles = DirtyFilesCache.instance().getDirtyFiles(baseDir, ratchetFrom); List result = new ArrayList<>(); for (String file : withNormalizedFileSeparators(dirtyFiles)) { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java new file mode 100644 index 0000000000..8aa4db7d2a --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java @@ -0,0 +1,61 @@ +package com.diffplug.spotless.maven; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +class DirtyFilesCache { + private final Map> cache = new ConcurrentHashMap<>(); + private static volatile DirtyFilesCache instance = new DirtyFilesCache(); + + static DirtyFilesCache instance() { + if (instance == null) { + synchronized (DirtyFilesCache.class) { + if (instance == null) { + instance = new DirtyFilesCache(); + } + } + } + return instance; + } + + + Iterable getDirtyFiles(File baseDir, String ratchetFrom) { + Key key = new Key(baseDir, ratchetFrom); + return cache.computeIfAbsent( + key, + k -> { + try { + return GitRatchetMaven.instance().getDirtyFiles(baseDir, ratchetFrom); + } catch (IOException e) { + throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); + } + } + ); + } + + private static final class Key { + private final File baseDir; + private final String ratchetFrom; + + private Key(File baseDir, String ratchetFrom) { + this.baseDir = baseDir; + this.ratchetFrom = ratchetFrom; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Key key = (Key) o; + return Objects.equals(baseDir, key.baseDir) && Objects.equals(ratchetFrom, key.ratchetFrom); + } + + @Override + public int hashCode() { + return Objects.hash(baseDir, ratchetFrom); + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java index ab3ec8b958..3383611902 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -30,6 +31,7 @@ import com.diffplug.spotless.extra.GitRatchet; final class GitRatchetMaven extends GitRatchet { + private GitRatchetMaven() {} @Override @@ -55,7 +57,7 @@ static GitRatchetMaven instance() { return instance; } - Iterable getDirtyFiles(File baseDir, String ratchetFrom) throws IOException { + List getDirtyFiles(File baseDir, String ratchetFrom) throws IOException { Repository repository = repositoryFor(baseDir); ObjectId sha = rootTreeShaOf(baseDir, ratchetFrom); From c886b7419be4b1ede70eb5b3ec599c5f4b831557 Mon Sep 17 00:00:00 2001 From: Shitikanth Kashyap Date: Mon, 12 Jan 2026 14:15:40 +0530 Subject: [PATCH 2/5] Add caching logic to GitRatchetMaven --- plugin-maven/build | 1 + .../spotless/maven/AbstractSpotlessMojo.java | 8 ++- .../spotless/maven/DirtyFilesCache.java | 61 ------------------- .../spotless/maven/GitRatchetMaven.java | 55 ++++++++++++++--- 4 files changed, 56 insertions(+), 69 deletions(-) create mode 120000 plugin-maven/build delete mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java diff --git a/plugin-maven/build b/plugin-maven/build new file mode 120000 index 0000000000..52a3ef3686 --- /dev/null +++ b/plugin-maven/build @@ -0,0 +1 @@ +/Users/shitikanth/build/spotless/plugin-maven/build \ No newline at end of file diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 01b80198eb..6f35007b70 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -335,7 +335,13 @@ private List collectFilesFromGit(FormatterFactory formatterFactory, String MatchPatterns excludePatterns = MatchPatterns.from( withNormalizedFileSeparators(getExcludes(formatterFactory))); - Iterable dirtyFiles = DirtyFilesCache.instance().getDirtyFiles(baseDir, ratchetFrom); + Iterable dirtyFiles; + try { + dirtyFiles = GitRatchetMaven + .instance().getDirtyFiles(baseDir, ratchetFrom); + } catch (IOException e) { + throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); + } List result = new ArrayList<>(); for (String file : withNormalizedFileSeparators(dirtyFiles)) { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java deleted file mode 100644 index 8aa4db7d2a..0000000000 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/DirtyFilesCache.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.diffplug.spotless.maven; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -class DirtyFilesCache { - private final Map> cache = new ConcurrentHashMap<>(); - private static volatile DirtyFilesCache instance = new DirtyFilesCache(); - - static DirtyFilesCache instance() { - if (instance == null) { - synchronized (DirtyFilesCache.class) { - if (instance == null) { - instance = new DirtyFilesCache(); - } - } - } - return instance; - } - - - Iterable getDirtyFiles(File baseDir, String ratchetFrom) { - Key key = new Key(baseDir, ratchetFrom); - return cache.computeIfAbsent( - key, - k -> { - try { - return GitRatchetMaven.instance().getDirtyFiles(baseDir, ratchetFrom); - } catch (IOException e) { - throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); - } - } - ); - } - - private static final class Key { - private final File baseDir; - private final String ratchetFrom; - - private Key(File baseDir, String ratchetFrom) { - this.baseDir = baseDir; - this.ratchetFrom = ratchetFrom; - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - Key key = (Key) o; - return Objects.equals(baseDir, key.baseDir) && Objects.equals(ratchetFrom, key.ratchetFrom); - } - - @Override - public int hashCode() { - return Objects.hash(baseDir, ratchetFrom); - } - } -} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java index 3383611902..34cd643c30 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java @@ -18,8 +18,11 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -32,6 +35,8 @@ final class GitRatchetMaven extends GitRatchet { + Map> cache = new HashMap<>(); + private GitRatchetMaven() {} @Override @@ -59,14 +64,30 @@ static GitRatchetMaven instance() { List getDirtyFiles(File baseDir, String ratchetFrom) throws IOException { Repository repository = repositoryFor(baseDir); - ObjectId sha = rootTreeShaOf(baseDir, ratchetFrom); + Set dirtyPaths = null; + Key key = new Key(repository.getIdentifier(), ratchetFrom); + synchronized (this) { + if (cache.containsKey(key)) { + dirtyPaths = cache.get(key); + } else { + dirtyPaths = getDirtyFilesInternal(repository, baseDir, ratchetFrom); + cache.put(key, dirtyPaths); + } + } + + Path baseDirPath = Path.of(baseDir.getPath()); + String workTreePath = repository.getWorkTree().getPath(); + return dirtyPaths.stream() + .map(path -> baseDirPath.relativize(Path.of(workTreePath, path)).toString()) + .collect(Collectors.toList()); + } + + Set getDirtyFilesInternal(Repository repository, File baseDir, String ratchetFrom) throws IOException { + ObjectId sha = rootTreeShaOf(baseDir, ratchetFrom); IndexDiff indexDiff = new IndexDiff(repository, sha, new FileTreeIterator(repository)); indexDiff.diff(); - String workTreePath = repository.getWorkTree().getPath(); - Path baseDirPath = Path.of(baseDir.getPath()); - Set dirtyPaths = new HashSet<>(indexDiff.getChanged()); dirtyPaths.addAll(indexDiff.getAdded()); dirtyPaths.addAll(indexDiff.getConflicting()); @@ -93,8 +114,28 @@ List getDirtyFiles(File baseDir, String ratchetFrom) throws IOException // A file can be modified in the index but removed in the tree dirtyPaths.removeAll(indexDiff.getMissing()); - return dirtyPaths.stream() - .map(path -> baseDirPath.relativize(Path.of(workTreePath, path)).toString()) - .collect(Collectors.toList()); + return dirtyPaths; + } + + private static final class Key { + private final String identifier; + private final String ratchetFrom; + + private Key(String identifier, String ratchetFrom) { + this.identifier = identifier; + this.ratchetFrom = ratchetFrom; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Key key = (Key) o; + return Objects.equals(identifier, key.identifier) && Objects.equals(ratchetFrom, key.ratchetFrom); + } + + @Override + public int hashCode() { + return Objects.hash(identifier, ratchetFrom); + } } } From f5a8ae18cc0bcc9920953650ed221b57126f8353 Mon Sep 17 00:00:00 2001 From: Shitikanth Kashyap Date: Mon, 12 Jan 2026 14:17:26 +0530 Subject: [PATCH 3/5] Remove build symlink --- plugin-maven/build | 1 - 1 file changed, 1 deletion(-) delete mode 120000 plugin-maven/build diff --git a/plugin-maven/build b/plugin-maven/build deleted file mode 120000 index 52a3ef3686..0000000000 --- a/plugin-maven/build +++ /dev/null @@ -1 +0,0 @@ -/Users/shitikanth/build/spotless/plugin-maven/build \ No newline at end of file From 1954a9a9c578cc2b01c0bcdc9f8fcfc03a9a77fb Mon Sep 17 00:00:00 2001 From: Shitikanth Kashyap Date: Mon, 12 Jan 2026 14:47:05 +0530 Subject: [PATCH 4/5] Remove unnecessary change in AbstractSpotlessMojo --- .../java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 6f35007b70..3952a8de70 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -338,7 +338,7 @@ private List collectFilesFromGit(FormatterFactory formatterFactory, String Iterable dirtyFiles; try { dirtyFiles = GitRatchetMaven - .instance().getDirtyFiles(baseDir, ratchetFrom); + .instance().getDirtyFiles(baseDir, ratchetFrom); } catch (IOException e) { throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); } From 10aa32df1f915599755044b8b578ee8848031a21 Mon Sep 17 00:00:00 2001 From: Shitikanth Kashyap Date: Mon, 12 Jan 2026 09:26:30 +0000 Subject: [PATCH 5/5] Fix formatting --- .../java/com/diffplug/spotless/maven/GitRatchetMaven.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java index 34cd643c30..ec11860c01 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/GitRatchetMaven.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2025 DiffPlug + * Copyright 2020-2026 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,7 +128,8 @@ private Key(String identifier, String ratchetFrom) { @Override public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; + if (o == null || getClass() != o.getClass()) + return false; Key key = (Key) o; return Objects.equals(identifier, key.identifier) && Objects.equals(ratchetFrom, key.ratchetFrom); }