summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf <thomas.wolf@paranor.ch>2021-11-19 19:15:46 +0100
committerThomas Wolf <thomas.wolf@paranor.ch>2021-11-23 19:42:34 +0100
commit6aa29d1166137372ae0948d180a9f88e9edd4b94 (patch)
tree982d092e1764e957d38caff9d3dbef4e4fec3962
parent4f8d4346234ce28d592ae92bbfc02d4d203454b1 (diff)
downloadjgit-6aa29d1166137372ae0948d180a9f88e9edd4b94.tar.gz
jgit-6aa29d1166137372ae0948d180a9f88e9edd4b94.zip
Better git system config finding
We've used "GIT_EDITOR=edit git config --system --edit" to determine the location of the git system config for a long time. But git 2.34.0 always expects this command to have a tty, but there isn't one when called from Java. If there isn't one, the Java process may get a SIGTTOU from the child process and hangs. Arguably it's a bug in C git 2.34.0 to unconditionally assume there was a tty. But JGit needs a fix *now*, otherwise any application using JGit will lock up if git 2.34.0 is installed on the machine. Therefore, use a different approach if the C git found is 2.8.0 or newer: parse the output of git config --system --show-origin --list -z "--show-origin" exists since git 2.8.0; it prefixes the values with the file name of the config file they come from, which is the system config file for this command. (This works even if the first item in the system config is an include.) Bug: 577358 Change-Id: I3ef170ed3f488f63c3501468303119319b03575d Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch> (cherry picked from commit 9446e62733da5005be1d5182f0dce759a3052d4a)
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java71
1 files changed, 63 insertions, 8 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index bf7b753693..507bd2bc92 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -61,6 +61,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
@@ -96,6 +98,9 @@ public abstract class FS {
*/
protected static final Entry[] NO_ENTRIES = {};
+ private static final Pattern VERSION = Pattern
+ .compile("\\s(\\d+)\\.(\\d+)\\.(\\d+)"); //$NON-NLS-1$
+
private volatile Boolean supportSymlinks;
/**
@@ -1508,26 +1513,76 @@ public abstract class FS {
return null;
}
- // Trick Git into printing the path to the config file by using "echo"
- // as the editor.
- Map<String, String> env = new HashMap<>();
- env.put("GIT_EDITOR", "echo"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (parseVersion(v) < makeVersion(2, 8, 0)) {
+ // --show-origin was introduced in git 2.8.0. For older git: trick
+ // it into printing the path to the config file by using "echo" as
+ // the editor.
+ Map<String, String> env = new HashMap<>();
+ env.put("GIT_EDITOR", "echo"); //$NON-NLS-1$ //$NON-NLS-2$
+ String w;
+ try {
+ w = readPipe(gitExe.getParentFile(),
+ new String[] { gitExe.getPath(), "config", "--system", //$NON-NLS-1$ //$NON-NLS-2$
+ "--edit" }, //$NON-NLS-1$
+ Charset.defaultCharset().name(),
+ env);
+ } catch (CommandFailedException e) {
+ LOG.warn(e.getMessage());
+ return null;
+ }
+ if (StringUtils.isEmptyOrNull(w)) {
+ return null;
+ }
+
+ return new File(w);
+ }
String w;
try {
w = readPipe(gitExe.getParentFile(),
new String[] { gitExe.getPath(), "config", "--system", //$NON-NLS-1$ //$NON-NLS-2$
- "--edit" }, //$NON-NLS-1$
- Charset.defaultCharset().name(), env);
+ "--show-origin", "--list", "-z" }, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Charset.defaultCharset().name());
} catch (CommandFailedException e) {
LOG.warn(e.getMessage());
return null;
}
- if (StringUtils.isEmptyOrNull(w)) {
+ if (w == null) {
+ return null;
+ }
+ // We get NUL-terminated items; the first one will be a file name,
+ // prefixed by "file:". (Using -z is crucial, otherwise git quotes file
+ // names with special characters.)
+ int nul = w.indexOf(0);
+ if (nul <= 0) {
+ return null;
+ }
+ w = w.substring(0, nul);
+ int colon = w.indexOf(':');
+ if (colon < 0) {
return null;
}
+ w = w.substring(colon + 1);
+ return w.isEmpty() ? null : new File(w);
+ }
+
+ private long parseVersion(String version) {
+ Matcher m = VERSION.matcher(version);
+ if (m.find()) {
+ try {
+ return makeVersion(
+ Integer.parseInt(m.group(1)),
+ Integer.parseInt(m.group(2)),
+ Integer.parseInt(m.group(3)));
+ } catch (NumberFormatException e) {
+ // Ignore
+ }
+ }
+ return -1;
+ }
- return new File(w);
+ private long makeVersion(int major, int minor, int patch) {
+ return ((major * 10_000L) + minor) * 10_000L + patch;
}
/**