Merge branch 'stable-5.11' into stable-5.12

* stable-5.11:
  Better git system config finding

Change-Id: I47946b91658cb2e38709179b7a8513b1211431e4
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
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 0946f64..586ce7d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -60,6 +60,8 @@
 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;
@@ -95,6 +97,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;
 
 	/**
@@ -1515,26 +1520,76 @@ protected File discoverGitSystemConfig() {
 			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);
+	}
 
-		return 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;
+	}
+
+	private long makeVersion(int major, int minor, int patch) {
+		return ((major * 10_000L) + minor) * 10_000L + patch;
 	}
 
 	/**