Skip to content

Commit 9bc702f

Browse files
authored
fix(plugin-gradle): Try to locate the git system config without executing any processes (#2514)
2 parents 9cbdac8 + 2921626 commit 9bc702f

File tree

2 files changed

+83
-13
lines changed

2 files changed

+83
-13
lines changed

plugin-gradle/CHANGES.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
99
* Adds support for worktrees (fixes [#1765](https://github.com/diffplug/spotless/issues/1765))
1010
* Bump default `google-java-format` version to latest `1.24.0` -> `1.28.0`. ([#2345](https://github.com/diffplug/spotless/pull/2345))
1111
* Bump default `ktlint` version to latest `1.5.0` -> `1.7.1`. ([#2555](https://github.com/diffplug/spotless/pull/2555))
12+
### Fixed
13+
* Respect system gitconfig when performing git operations ([#2404](https://github.com/diffplug/spotless/issues/2404))
1214

1315
## [7.2.1] - 2025-07-21
1416
### Fixed
@@ -34,8 +36,6 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
3436
* Make sure npm-based formatters use the correct `node_modules` directory when running in parallel. ([#2542](https://github.com/diffplug/spotless/pull/2542))
3537
### Changed
3638
* Bump internal dependencies for npm-based formatters ([#2542](https://github.com/diffplug/spotless/pull/2542))
37-
38-
### Changed
3939
* scalafmt: enforce version consistency between the version configured in Spotless and the version declared in Scalafmt config file ([#2460](https://github.com/diffplug/spotless/issues/2460))
4040

4141
## [7.0.4] - 2025-05-27

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GitRatchetGradle.java

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 DiffPlug
2+
* Copyright 2020-2025 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.
@@ -16,10 +16,14 @@
1616
package com.diffplug.gradle.spotless;
1717

1818
import java.io.File;
19+
import java.io.IOException;
20+
import java.util.concurrent.atomic.AtomicReference;
1921

2022
import javax.annotation.Nullable;
2123

24+
import org.eclipse.jgit.errors.ConfigInvalidException;
2225
import org.eclipse.jgit.lib.Config;
26+
import org.eclipse.jgit.lib.StoredConfig;
2327
import org.eclipse.jgit.storage.file.FileBasedConfig;
2428
import org.eclipse.jgit.util.FS;
2529
import org.eclipse.jgit.util.SystemReader;
@@ -28,20 +32,86 @@
2832

2933
/** Gradle implementation of GitRatchet. */
3034
public class GitRatchetGradle extends GitRatchet<File> {
35+
private static final String[] GIT_EXEC_CANDIDATES = {"git", "git.exe", "git.cmd"};
36+
3137
static {
32-
preventJGitFromCallingExecutables();
38+
GitRatchetGradle.redirectJGitExecutions();
3339
}
3440

35-
static void preventJGitFromCallingExecutables() {
36-
SystemReader reader = SystemReader.getInstance();
37-
SystemReader.setInstance(new DelegatingSystemReader(reader) {
41+
static void redirectJGitExecutions() {
42+
SystemReader existing = SystemReader.getInstance();
43+
SystemReader.setInstance(new DelegatingSystemReader(existing) {
44+
private AtomicReference<FileBasedConfig> systemConfig = new AtomicReference<>();
45+
46+
@Override
47+
public StoredConfig getSystemConfig() throws ConfigInvalidException, IOException {
48+
FileBasedConfig c = systemConfig.get();
49+
if (c == null) {
50+
systemConfig.compareAndSet(null,
51+
this.openSystemConfig(this.getJGitConfig(), FS.DETECTED));
52+
c = systemConfig.get();
53+
}
54+
updateAll(c);
55+
return c;
56+
}
57+
58+
// lifted from SystemReader since it's private
59+
private void updateAll(Config config) throws ConfigInvalidException, IOException {
60+
if (config == null) {
61+
return;
62+
}
63+
64+
updateAll(config.getBaseConfig());
65+
if (config instanceof FileBasedConfig) {
66+
FileBasedConfig cfg = (FileBasedConfig) config;
67+
if (cfg.isOutdated()) {
68+
cfg.load();
69+
}
70+
}
71+
}
72+
3873
@Override
39-
public String getenv(String variable) {
40-
if ("PATH".equals(variable)) {
41-
return "";
42-
} else {
43-
return super.getenv(variable);
74+
public FileBasedConfig openSystemConfig(final Config parent, final FS fs) {
75+
// cgit logic: https://git.kernel.org/pub/scm/git/git.git/tree/config.c#n1973 - in git_system_config()
76+
// They check the GIT_CONFIG_SYSTEM env var first, then follow up with logic based on compile-time parameters
77+
// We can't replicate this exactly so we'll do the closest approximation that Gradle will allow.
78+
final String systemPath = this.getenv("GIT_CONFIG_SYSTEM");
79+
if (systemPath != null) {
80+
fs.setGitSystemConfig(new File(systemPath).getAbsoluteFile());
81+
return super.openSystemConfig(parent, fs);
82+
}
83+
84+
// match FS.searchPath
85+
File gitExec = null;
86+
final String path = this.getenv("PATH");
87+
if (path != null) {
88+
outer: for (final String p : path.split(File.pathSeparator)) {
89+
for (final String name : GIT_EXEC_CANDIDATES) {
90+
final File candidate = new File(p, name);
91+
if (candidate.isFile() && candidate.canExecute()) {
92+
gitExec = candidate.getAbsoluteFile();
93+
break outer;
94+
}
95+
}
96+
}
97+
}
98+
99+
// Guess at common locations
100+
if (gitExec != null) {
101+
// If git exec is at <prefix>/bin/git, this returns <prefix>
102+
File prefix = gitExec.getParentFile().getParentFile();
103+
104+
// Then we try to resolve a config
105+
final File systemConfig = new File(prefix, "etc/gitconfig");
106+
if (systemConfig.exists()) {
107+
fs.setGitSystemConfig(systemConfig);
108+
return super.openSystemConfig(parent, fs);
109+
}
44110
}
111+
112+
// Fallback to the non-prefixed path (this is not the logic that cgit uses, but oh well)
113+
fs.setGitSystemConfig(new File("/etc/gitconfig"));
114+
return super.openSystemConfig(parent, fs);
45115
}
46116
});
47117
}
@@ -70,7 +140,7 @@ public String getHostname() {
70140

71141
@Override
72142
public String getenv(String variable) {
73-
return reader.getProperty(variable);
143+
return reader.getenv(variable);
74144
}
75145

76146
@Override

0 commit comments

Comments
 (0)