]> source.dussan.org Git - jgit.git/commitdiff
Add config reader for user-defined difftools 81/137481/46
authorAndre Bossert <andre.bossert@siemens.com>
Sun, 19 Jan 2020 19:41:23 +0000 (20:41 +0100)
committerSimeon Andreev <simeon.danailov.andreev@gmail.com>
Wed, 8 Dec 2021 09:43:00 +0000 (10:43 +0100)
see: http://git-scm.com/docs/git-difftool

* add config reader for user-defined difftools
  * diff.tool
  * diff.guitool
  * difftool.prompt
  * difftool.trustExitCode
  * difftool.<tool>.path
  * difftool.<tool>.cmd
* add pre-defined difftools
* implemented "git difftool --tool-help" to verify config reader and
pre-defined difftools

Bug: 356832
Change-Id: Idde8fddbef61f3378ee565c6321570b3962d0e1d
Signed-off-by: Andre Bossert <andre.bossert@siemens.com>
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTool.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalDiffToolTest.java
org.eclipse.jgit/META-INF/MANIFEST.MF
org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/CommandLineDiffTool.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffToolConfig.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffTools.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/PreDefinedDiffTool.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/UserDefinedDiffTool.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java

index 3e0a4eaf20269ec03d97a99c443b350af58eb5f9..3d6e909adf8d35ea0b12bf563a661f46bf8ee2ab 100644 (file)
@@ -12,6 +12,7 @@ Import-Package: org.eclipse.jgit.api;version="[6.1.0,6.2.0)",
  org.eclipse.jgit.api.errors;version="[6.1.0,6.2.0)",
  org.eclipse.jgit.diff;version="[6.1.0,6.2.0)",
  org.eclipse.jgit.dircache;version="[6.1.0,6.2.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="6.1.0",
  org.eclipse.jgit.internal.storage.file;version="6.1.0",
  org.eclipse.jgit.junit;version="[6.1.0,6.2.0)",
  org.eclipse.jgit.lib;version="[6.1.0,6.2.0)",
index 2ce50c7827f133f8ee415f522ac41cca927f1495..e7bf48417d52afcc27d1c03190bbe781a1bf98e5 100644 (file)
@@ -12,10 +12,12 @@ package org.eclipse.jgit.pgm;
 import static org.junit.Assert.assertEquals;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.internal.diffmergetool.CommandLineDiffTool;
 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
 import org.eclipse.jgit.pgm.opt.CmdLineParser;
 import org.eclipse.jgit.pgm.opt.SubcommandHandler;
@@ -135,16 +137,24 @@ public class DiffToolTest extends CLIRepositoryTestCase {
 
        @Test
        public void testToolHelp() throws Exception {
-               String[] expectedOutput = {
-                               "git difftool --tool=<tool> may be set to one of the following:",
+               CommandLineDiffTool[] defaultTools = CommandLineDiffTool.values();
+               List<String> expectedOutput = new ArrayList<>();
+               expectedOutput.add("git difftool --tool=<tool> may be set to one of the following:");
+               for (CommandLineDiffTool defaultTool : defaultTools) {
+                       String toolName = defaultTool.name();
+                       expectedOutput.add(toolName);
+               }
+               String[] userDefinedToolsHelp = {
                                "user-defined:",
                                "The following tools are valid, but not currently available:",
                                "Some of the tools listed above only work in a windowed",
-                               "environment. If run in a terminal-only session, they will fail.", };
+                               "environment. If run in a terminal-only session, they will fail.",
+               };
+               expectedOutput.addAll(Arrays.asList(userDefinedToolsHelp));
 
                String option = "--tool-help";
                assertArrayOfLinesEquals("Incorrect output for option: " + option,
-                               expectedOutput, runAndCaptureUsingInitRaw("difftool", option));
+                               expectedOutput.toArray(new String[0]), runAndCaptureUsingInitRaw("difftool", option));
        }
 
        private RevCommit createUnstagedChanges() throws Exception {
index 9fc26c93564137d7851c6f7a6fdfcb010930cea5..d26842c641b25af0329e5b5aedad1d229e3a2e76 100644 (file)
@@ -199,20 +199,20 @@ class DiffTool extends TextBuiltin {
        }
 
        private void showToolHelp() throws IOException {
-               String availableToolNames = new String();
+               StringBuilder availableToolNames = new StringBuilder();
                for (String name : diffTools.getAvailableTools().keySet()) {
-                       availableToolNames += String.format("\t\t{0}\n", name); //$NON-NLS-1$
+                       availableToolNames.append(String.format("\t\t%s\n", name)); //$NON-NLS-1$
                }
-               String notAvailableToolNames = new String();
+               StringBuilder notAvailableToolNames = new StringBuilder();
                for (String name : diffTools.getNotAvailableTools().keySet()) {
-                       notAvailableToolNames += String.format("\t\t{0}\n", name); //$NON-NLS-1$
+                       notAvailableToolNames.append(String.format("\t\t%s\n", name)); //$NON-NLS-1$
                }
-               String userToolNames = new String();
+               StringBuilder userToolNames = new StringBuilder();
                Map<String, ExternalDiffTool> userTools = diffTools
                                .getUserDefinedTools();
                for (String name : userTools.keySet()) {
-                       availableToolNames += String.format("\t\t{0}.cmd {1}\n", //$NON-NLS-1$
-                                       name, userTools.get(name).getCommand());
+                       userToolNames.append(String.format("\t\t%s.cmd %s\n", //$NON-NLS-1$
+                                       name, userTools.get(name).getCommand()));
                }
                outw.println(MessageFormat.format(
                                CLIText.get().diffToolHelpSetToFollowing, availableToolNames,
index f07d9d1afca2fe103392243f13061708cd9b2e74..b141a86f76c75865c956580c1e76dfbaead5b365 100644 (file)
@@ -9,9 +9,18 @@
  */
 package org.eclipse.jgit.internal.diffmergetool;
 
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DIFFTOOL_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CMD;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_GUITOOL;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PATH;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PROMPT;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_TRUST_EXIT_CODE;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.jgit.lib.internal.BooleanTriState;
@@ -29,27 +38,64 @@ public class ExternalDiffToolTest extends ExternalToolTest {
                Set<String> actualToolNames = manager.getToolNames();
                Set<String> expectedToolNames = Collections.emptySet();
                assertEquals("Incorrect set of external diff tool names",
-                               expectedToolNames,
-                               actualToolNames);
+                               expectedToolNames, actualToolNames);
        }
 
        @Test
        public void testAllTools() {
                DiffTools manager = new DiffTools(db);
                Set<String> actualToolNames = manager.getAvailableTools().keySet();
-               Set<String> expectedToolNames = Collections.emptySet();
-               assertEquals("Incorrect set of available external diff tools",
-                               expectedToolNames,
+               Set<String> expectedToolNames = new LinkedHashSet<>();
+               CommandLineDiffTool[] defaultTools = CommandLineDiffTool.values();
+               for (CommandLineDiffTool defaultTool : defaultTools) {
+                       String toolName = defaultTool.name();
+                       expectedToolNames.add(toolName);
+               }
+               assertEquals("Incorrect set of external diff tools", expectedToolNames,
                                actualToolNames);
        }
 
+       @Test
+       public void testOverridePredefinedToolPath() {
+               String toolName = CommandLineDiffTool.guiffy.name();
+               String customToolPath = "/usr/bin/echo";
+
+               FileBasedConfig config = db.getConfig();
+               config.setString(CONFIG_DIFFTOOL_SECTION, toolName, CONFIG_KEY_CMD,
+                               "echo");
+               config.setString(CONFIG_DIFFTOOL_SECTION, toolName, CONFIG_KEY_PATH,
+                               customToolPath);
+
+               DiffTools manager = new DiffTools(db);
+               Map<String, ExternalDiffTool> tools = manager.getUserDefinedTools();
+               ExternalDiffTool diffTool = tools.get(toolName);
+               assertNotNull("Expected tool \"" + toolName + "\" to be user defined",
+                               diffTool);
+
+               String toolPath = diffTool.getPath();
+               assertEquals("Expected external diff tool to have an overriden path",
+                               customToolPath, toolPath);
+       }
+
        @Test
        public void testUserDefinedTools() {
+               FileBasedConfig config = db.getConfig();
+               String customToolname = "customTool";
+               config.setString(CONFIG_DIFFTOOL_SECTION, customToolname,
+                               CONFIG_KEY_CMD, "echo");
+               config.setString(CONFIG_DIFFTOOL_SECTION, customToolname,
+                               CONFIG_KEY_PATH, "/usr/bin/echo");
+               config.setString(CONFIG_DIFFTOOL_SECTION, customToolname,
+                               CONFIG_KEY_PROMPT, "--no-prompt");
+               config.setString(CONFIG_DIFFTOOL_SECTION, customToolname,
+                               CONFIG_KEY_GUITOOL, "--no-gui");
+               config.setString(CONFIG_DIFFTOOL_SECTION, customToolname,
+                               CONFIG_KEY_TRUST_EXIT_CODE, "--no-trust-exit-code");
                DiffTools manager = new DiffTools(db);
                Set<String> actualToolNames = manager.getUserDefinedTools().keySet();
-               Set<String> expectedToolNames = Collections.emptySet();
-               assertEquals("Incorrect set of user defined external diff tools",
-                               expectedToolNames,
+               Set<String> expectedToolNames = new LinkedHashSet<>();
+               expectedToolNames.add(customToolname);
+               assertEquals("Incorrect set of external diff tools", expectedToolNames,
                                actualToolNames);
        }
 
@@ -59,8 +105,7 @@ public class ExternalDiffToolTest extends ExternalToolTest {
                Set<String> actualToolNames = manager.getNotAvailableTools().keySet();
                Set<String> expectedToolNames = Collections.emptySet();
                assertEquals("Incorrect set of not available external diff tools",
-                               expectedToolNames,
-                               actualToolNames);
+                               expectedToolNames, actualToolNames);
        }
 
        @Test
@@ -80,8 +125,7 @@ public class ExternalDiffToolTest extends ExternalToolTest {
                int compareResult = manager.compare(newPath, oldPath, newId, oldId,
                                toolName, prompt, gui, trustExitCode);
                assertEquals("Incorrect compare result for external diff tool",
-                               expectedCompareResult,
-                               compareResult);
+                               expectedCompareResult, compareResult);
        }
 
        @Test
index 90e5ccba09c5c5571cd676bbf490ea1a15b31b23..91e905b2ff0e1a88d3dfdb46c46b9f909e776def 100644 (file)
@@ -72,6 +72,7 @@ Export-Package: org.eclipse.jgit.annotations;version="6.1.0",
    org.eclipse.jgit.http.test",
  org.eclipse.jgit.internal.diffmergetool;version="6.1.0";
   x-friends:="org.eclipse.jgit.test,
+   org.eclipse.jgit.pgm.test,
    org.eclipse.jgit.pgm",
  org.eclipse.jgit.internal.fsck;version="6.1.0";
   x-friends:="org.eclipse.jgit.test",
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/CommandLineDiffTool.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/CommandLineDiffTool.java
new file mode 100644 (file)
index 0000000..509515c
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2018-2021, Andre Bossert <andre.bossert@siemens.com>
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.diffmergetool;
+
+/**
+ * Pre-defined command line diff tools.
+ *
+ * Adds same diff tools as also pre-defined in C-Git
+ * <p>
+ * see "git-core\mergetools\"
+ * </p>
+ * <p>
+ * see links to command line parameter description for the tools
+ * </p>
+ *
+ * <pre>
+ * araxis
+ * bc
+ * bc3
+ * codecompare
+ * deltawalker
+ * diffmerge
+ * diffuse
+ * ecmerge
+ * emerge
+ * examdiff
+ * guiffy
+ * gvimdiff
+ * gvimdiff2
+ * gvimdiff3
+ * kdiff3
+ * kompare
+ * meld
+ * opendiff
+ * p4merge
+ * tkdiff
+ * vimdiff
+ * vimdiff2
+ * vimdiff3
+ * winmerge
+ * xxdiff
+ * </pre>
+ *
+ */
+@SuppressWarnings("nls")
+public enum CommandLineDiffTool {
+       /**
+        * See: <a href=
+        * "https://www.araxis.com/merge/documentation-windows/command-line.en">https://www.araxis.com/merge/documentation-windows/command-line.en</a>
+        */
+       araxis("compare", "-wait -2 \"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://www.scootersoftware.com/v4help/index.html?command_line_reference.html">https://www.scootersoftware.com/v4help/index.html?command_line_reference.html</a>
+        */
+       bc("bcomp", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://www.scootersoftware.com/v4help/index.html?command_line_reference.html">https://www.scootersoftware.com/v4help/index.html?command_line_reference.html</a>
+        */
+       bc3("bcompare", bc),
+       /**
+        * See: <a href=
+        * "https://www.devart.com/codecompare/docs/index.html?comparing_via_command_line.htm">https://www.devart.com/codecompare/docs/index.html?comparing_via_command_line.htm</a>
+        */
+       codecompare("CodeCompare", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://www.deltawalker.com/integrate/command-line">https://www.deltawalker.com/integrate/command-line</a>
+        */
+       deltawalker("DeltaWalker", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://sourcegear.com/diffmerge/webhelp/sec__clargs__diff.html">https://sourcegear.com/diffmerge/webhelp/sec__clargs__diff.html</a>
+        */
+       diffmerge("diffmerge", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://diffuse.sourceforge.net/manual.html#introduction-usage">http://diffuse.sourceforge.net/manual.html#introduction-usage</a>
+        */
+       diffuse("diffuse", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://www.elliecomputing.com/en/OnlineDoc/ecmerge_en/44205167.asp">http://www.elliecomputing.com/en/OnlineDoc/ecmerge_en/44205167.asp</a>
+        */
+       ecmerge("ecmerge", "--default --mode=diff2 \"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://www.gnu.org/software/emacs/manual/html_node/emacs/Overview-of-Emerge.html">https://www.gnu.org/software/emacs/manual/html_node/emacs/Overview-of-Emerge.html</a>
+        */
+       emerge("emacs", "-f emerge-files-command \"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://www.prestosoft.com/ps.asp?page=htmlhelp/edp/command_line_options">https://www.prestosoft.com/ps.asp?page=htmlhelp/edp/command_line_options</a>
+        */
+       examdiff("ExamDiff", "\"$LOCAL\" \"$REMOTE\" -nh"),
+       /**
+        * See: <a href=
+        * "https://www.guiffy.com/help/GuiffyHelp/GuiffyCmd.html">https://www.guiffy.com/help/GuiffyHelp/GuiffyCmd.html</a>
+        */
+       guiffy("guiffy", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
+        */
+       gvimdiff("gviewdiff", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
+        */
+       gvimdiff2(gvimdiff),
+       /**
+        * See: <a href=
+        * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
+        */
+       gvimdiff3(gvimdiff),
+       /**
+        * See: <a href=
+        * "http://kdiff3.sourceforge.net/doc/documentation.html">http://kdiff3.sourceforge.net/doc/documentation.html</a>
+        */
+       kdiff3("kdiff3",
+                       "--L1 \"$MERGED (A)\" --L2 \"$MERGED (B)\" \"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://docs.kde.org/trunk5/en/kdesdk/kompare/commandline-options.html">https://docs.kde.org/trunk5/en/kdesdk/kompare/commandline-options.html</a>
+        */
+       kompare("kompare", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "ttp://meldmerge.org/help/file-mode.html">http://meldmerge.org/help/file-mode.html</a>
+        */
+       meld("meld", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://www.manpagez.com/man/1/opendiff/">http://www.manpagez.com/man/1/opendiff/</a>
+        * <p>
+        * Hint: check the ' | cat' for the call
+        * </p>
+        */
+       opendiff("opendiff", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "https://www.perforce.com/manuals/v15.1/cmdref/p4_merge.html">https://www.perforce.com/manuals/v15.1/cmdref/p4_merge.html</a>
+        */
+       p4merge("p4merge", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://linux.math.tifr.res.in/manuals/man/tkdiff.html">http://linux.math.tifr.res.in/manuals/man/tkdiff.html</a>
+        */
+       tkdiff("tkdiff", "\"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
+        */
+       vimdiff("viewdiff", gvimdiff),
+       /**
+        * See: <a href=
+        * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
+        */
+       vimdiff2(vimdiff),
+       /**
+        * See: <a href=
+        * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
+        */
+       vimdiff3(vimdiff),
+       /**
+        * See: <a href=
+        * "http://manual.winmerge.org/Command_line.html">http://manual.winmerge.org/Command_line.html</a>
+        * <p>
+        * Hint: check how 'mergetool_find_win32_cmd "WinMergeU.exe" "WinMerge"'
+        * works
+        * </p>
+        */
+       winmerge("WinMergeU", "-u -e \"$LOCAL\" \"$REMOTE\""),
+       /**
+        * See: <a href=
+        * "http://furius.ca/xxdiff/doc/xxdiff-doc.html">http://furius.ca/xxdiff/doc/xxdiff-doc.html</a>
+        */
+       xxdiff("xxdiff",
+                       "-R 'Accel.Search: \"Ctrl+F\"' -R 'Accel.SearchForward: \"Ctrl+G\"' \"$LOCAL\" \"$REMOTE\"");
+
+       CommandLineDiffTool(String path, String parameters) {
+               this.path = path;
+               this.parameters = parameters;
+       }
+
+       CommandLineDiffTool(CommandLineDiffTool from) {
+               this(from.getPath(), from.getParameters());
+       }
+
+       CommandLineDiffTool(String path, CommandLineDiffTool from) {
+               this(path, from.getParameters());
+       }
+
+       private final String path;
+
+       private final String parameters;
+
+       /**
+        * @return path
+        */
+       public String getPath() {
+               return path;
+       }
+
+       /**
+        * @return parameters as one string
+        */
+       public String getParameters() {
+               return parameters;
+       }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffToolConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffToolConfig.java
new file mode 100644 (file)
index 0000000..551f634
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018-2021, Andre Bossert <andre.bossert@siemens.com>
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.diffmergetool;
+
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DIFFTOOL_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DIFF_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CMD;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_GUITOOL;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PATH;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PROMPT;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_TOOL;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_TRUST_EXIT_CODE;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.internal.BooleanTriState;
+
+/**
+ * Keeps track of difftool related configuration options.
+ */
+public class DiffToolConfig {
+
+       /** Key for {@link Config#get(SectionParser)}. */
+       public static final Config.SectionParser<DiffToolConfig> KEY = DiffToolConfig::new;
+
+       private final String toolName;
+
+       private final String guiToolName;
+
+       private final boolean prompt;
+
+       private final BooleanTriState trustExitCode;
+
+       private final Map<String, ExternalDiffTool> tools;
+
+       private DiffToolConfig(Config rc) {
+               toolName = rc.getString(CONFIG_DIFF_SECTION, null, CONFIG_KEY_TOOL);
+               guiToolName = rc.getString(CONFIG_DIFF_SECTION, null,
+                               CONFIG_KEY_GUITOOL);
+               prompt = rc.getBoolean(CONFIG_DIFFTOOL_SECTION, CONFIG_KEY_PROMPT,
+                               true);
+               String trustStr = rc.getString(CONFIG_DIFFTOOL_SECTION, null,
+                               CONFIG_KEY_TRUST_EXIT_CODE);
+               if (trustStr != null) {
+                       trustExitCode = Boolean.parseBoolean(trustStr)
+                                       ? BooleanTriState.TRUE
+                                       : BooleanTriState.FALSE;
+               } else {
+                       trustExitCode = BooleanTriState.UNSET;
+               }
+               tools = new HashMap<>();
+               Set<String> subsections = rc.getSubsections(CONFIG_DIFFTOOL_SECTION);
+               for (String name : subsections) {
+                       String cmd = rc.getString(CONFIG_DIFFTOOL_SECTION, name,
+                                       CONFIG_KEY_CMD);
+                       String path = rc.getString(CONFIG_DIFFTOOL_SECTION, name,
+                                       CONFIG_KEY_PATH);
+                       if ((cmd != null) || (path != null)) {
+                               tools.put(name, new UserDefinedDiffTool(name, path, cmd));
+                       }
+               }
+       }
+
+       /**
+        * @return the default diff tool name (diff.tool)
+        */
+       public String getDefaultToolName() {
+               return toolName;
+       }
+
+       /**
+        * @return the default GUI diff tool name (diff.guitool)
+        */
+       public String getDefaultGuiToolName() {
+               return guiToolName;
+       }
+
+       /**
+        * @return the diff tool "prompt" option (difftool.prompt)
+        */
+       public boolean isPrompt() {
+               return prompt;
+       }
+
+       /**
+        * @return the diff tool "trust exit code" option (difftool.trustExitCode)
+        */
+       public boolean isTrustExitCode() {
+               return trustExitCode == BooleanTriState.TRUE;
+       }
+
+       /**
+        * @return the tools map
+        */
+       public Map<String, ExternalDiffTool> getTools() {
+               return tools;
+       }
+
+       /**
+        * @return the tool names
+        */
+       public Set<String> getToolNames() {
+               return tools.keySet();
+       }
+}
index cb0640d2e860219ad4f80945b59324f0e32bafcf..39729a4eecaf08447b66bacfc0e9495f1b304ada 100644 (file)
@@ -23,6 +23,8 @@ import org.eclipse.jgit.lib.internal.BooleanTriState;
  */
 public class DiffTools {
 
+       private final DiffToolConfig config;
+
        private Map<String, ExternalDiffTool> predefinedTools;
 
        private Map<String, ExternalDiffTool> userDefinedTools;
@@ -31,9 +33,10 @@ public class DiffTools {
         * Creates the external diff-tools manager for given repository.
         *
         * @param repo
-        *            the repository database
+        *            the repository
         */
        public DiffTools(Repository repo) {
+               config = repo.getConfig().get(DiffToolConfig.KEY);
                setupPredefinedTools();
                setupUserDefinedTools();
        }
@@ -69,7 +72,7 @@ public class DiffTools {
         * @return the tool names
         */
        public Set<String> getToolNames() {
-               return Collections.emptySet();
+               return config.getToolNames();
        }
 
        /**
@@ -112,10 +115,29 @@ public class DiffTools {
 
        private void setupPredefinedTools() {
                predefinedTools = new TreeMap<>();
+               for (CommandLineDiffTool tool : CommandLineDiffTool.values()) {
+                       predefinedTools.put(tool.name(), new PreDefinedDiffTool(tool));
+               }
        }
 
        private void setupUserDefinedTools() {
                userDefinedTools = new TreeMap<>();
+               Map<String, ExternalDiffTool> userTools = config.getTools();
+               for (String name : userTools.keySet()) {
+                       ExternalDiffTool userTool = userTools.get(name);
+                       // if difftool.<name>.cmd is defined we have user defined tool
+                       if (userTool.getCommand() != null) {
+                               userDefinedTools.put(name, userTool);
+                       } else if (userTool.getPath() != null) {
+                               // if difftool.<name>.path is defined we just overload the path
+                               // of predefined tool
+                               PreDefinedDiffTool predefTool = (PreDefinedDiffTool) predefinedTools
+                                               .get(name);
+                               if (predefTool != null) {
+                                       predefTool.setPath(userTool.getPath());
+                               }
+                       }
+               }
        }
 
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/PreDefinedDiffTool.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/PreDefinedDiffTool.java
new file mode 100644 (file)
index 0000000..1c69fb4
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018-2021, Andre Bossert <andre.bossert@siemens.com>
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.diffmergetool;
+
+/**
+ * The pre-defined diff tool.
+ */
+public class PreDefinedDiffTool extends UserDefinedDiffTool {
+
+       /**
+        * Create a pre-defined diff tool
+        *
+        * @param name
+        *            the name
+        * @param path
+        *            the path
+        * @param parameters
+        *            the tool parameters as one string that is used together with
+        *            path as command
+        */
+       public PreDefinedDiffTool(String name, String path, String parameters) {
+               super(name, path, parameters);
+       }
+
+       /**
+        * Creates the pre-defined diff tool
+        *
+        * @param tool
+        *            the command line diff tool
+        *
+        */
+       public PreDefinedDiffTool(CommandLineDiffTool tool) {
+               this(tool.name(), tool.getPath(), tool.getParameters());
+       }
+
+       /**
+        * @param path
+        */
+       @Override
+       public void setPath(String path) {
+               // handling of spaces in path
+               if (path.contains(" ")) { //$NON-NLS-1$
+                       // add quotes before if needed
+                       if (!path.startsWith("\"")) { //$NON-NLS-1$
+                               path = "\"" + path; //$NON-NLS-1$
+                       }
+                       // add quotes after if needed
+                       if (!path.endsWith("\"")) { //$NON-NLS-1$
+                               path = path + "\""; //$NON-NLS-1$
+                       }
+               }
+               super.setPath(path);
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * @return the concatenated path and command of the pre-defined diff tool
+        */
+       @Override
+       public String getCommand() {
+               return getPath() + " " + super.getCommand(); //$NON-NLS-1$
+       }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/UserDefinedDiffTool.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/UserDefinedDiffTool.java
new file mode 100644 (file)
index 0000000..012296e
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2018-2021, Andre Bossert <andre.bossert@siemens.com>
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.diffmergetool;
+
+/**
+ * The user-defined diff tool.
+ */
+public class UserDefinedDiffTool implements ExternalDiffTool {
+
+       /**
+        * the diff tool name
+        */
+       private final String name;
+
+       /**
+        * the diff tool path
+        */
+       private String path;
+
+       /**
+        * the diff tool command
+        */
+       private final String cmd;
+
+       /**
+        * Creates the diff tool
+        *
+        * @param name
+        *            the name
+        * @param path
+        *            the path
+        * @param cmd
+        *            the command
+        */
+       public UserDefinedDiffTool(String name, String path, String cmd) {
+               this.name = name;
+               this.path = path;
+               this.cmd = cmd;
+       }
+
+       /**
+        * @return the diff tool name
+        */
+       @Override
+       public String getName() {
+               return name;
+       }
+
+       /**
+        * The path of the diff tool.
+        *
+        * <p>
+        * The path to a pre-defined external diff tool can be overridden by
+        * specifying {@code difftool.<tool>.path} in a configuration file.
+        * </p>
+        * <p>
+        * For a user defined diff tool (that does not override a pre-defined diff
+        * tool), the path is ignored when invoking the tool.
+        * </p>
+        *
+        * @return the diff tool path
+        *
+        * @see <a href=
+        *      "https://git-scm.com/docs/git-difftool">https://git-scm.com/docs/git-difftool</a>
+        */
+       @Override
+       public String getPath() {
+               return path;
+       }
+
+       /**
+        * The command of the diff tool.
+        *
+        * <p>
+        * A pre-defined external diff tool can be overridden using the tools name
+        * in a configuration file. The overwritten tool is then a user defined tool
+        * and the command of the diff tool is specified with
+        * {@code difftool.<tool>.cmd}. This command must work without prepending
+        * the value of {@link #getPath()} and can sometimes include tool
+        * parameters.
+        * </p>
+        *
+        * @return the diff tool command
+        *
+        * @see <a href=
+        *      "https://git-scm.com/docs/git-difftool">https://git-scm.com/docs/git-difftool</a>
+        */
+       @Override
+       public String getCommand() {
+               return cmd;
+       }
+
+       /**
+        * Overrides the path for the given tool. Equivalent to setting
+        * {@code difftool.<tool>.path}.
+        *
+        * @param path
+        *            the new diff tool path
+        *
+        * @see <a href=
+        *      "https://git-scm.com/docs/git-difftool">https://git-scm.com/docs/git-difftool</a>
+        */
+       public void setPath(String path) {
+               this.path = path;
+       }
+}
index 24eebc6a1988debaf9c056716dc200c353d612d0..4b21e4be4e9396f2a576ee4e6d1b689a6e0a8b2d 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
  * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
- * Copyright (C) 2012, 2020, Robin Rosenberg and others
+ * Copyright (C) 2012-2013, Robin Rosenberg
+ * Copyright (C) 2018-2021, Andre Bossert <andre.bossert@siemens.com> and others
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -29,6 +30,48 @@ public final class ConfigConstants {
        /** The "diff" section */
        public static final String CONFIG_DIFF_SECTION = "diff";
 
+       /**
+        * The "tool" key within "diff" section
+        *
+        * @since 6.1
+        */
+       public static final String CONFIG_KEY_TOOL = "tool";
+
+       /**
+        * The "guitool" key within "diff" section
+        *
+        * @since 6.1
+        */
+       public static final String CONFIG_KEY_GUITOOL = "guitool";
+
+       /**
+        * The "difftool" section
+        *
+        * @since 6.1
+        */
+       public static final String CONFIG_DIFFTOOL_SECTION = "difftool";
+
+       /**
+        * The "prompt" key within "difftool" section
+        *
+        * @since 6.1
+        */
+       public static final String CONFIG_KEY_PROMPT = "prompt";
+
+       /**
+        * The "trustExitCode" key within "difftool" section
+        *
+        * @since 6.1
+        */
+       public static final String CONFIG_KEY_TRUST_EXIT_CODE = "trustExitCode";
+
+       /**
+        * The "cmd" key within "difftool.*." section
+        *
+        * @since 6.1
+        */
+       public static final String CONFIG_KEY_CMD = "cmd";
+
        /** The "dfs" section */
        public static final String CONFIG_DFS_SECTION = "dfs";