summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalDiffToolTest.java130
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalMergeToolTest.java62
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffTools.java70
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/ExternalToolUtils.java65
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/MergeTools.java54
8 files changed, 382 insertions, 12 deletions
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java
index ce4c004c09..2b50d45253 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java
@@ -79,7 +79,7 @@ public class DiffToolTest extends ToolTestCase {
+ errorReturnCode);
}
- @Test
+ @Test(expected = Die.class)
public void testEmptyToolName() throws Exception {
String emptyToolName = "";
@@ -95,6 +95,7 @@ public class DiffToolTest extends ToolTestCase {
String[] expectedErrorOutput = { araxisErrorLine, araxisErrorLine, };
runAndCaptureUsingInitRaw(Arrays.asList(expectedErrorOutput), DIFF_TOOL,
"--no-prompt");
+ fail("Expected exception to be thrown due to external tool exiting with an error");
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalDiffToolTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalDiffToolTest.java
index 222608e314..f69a1794ef 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalDiffToolTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalDiffToolTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
@@ -34,6 +35,8 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.internal.BooleanTriState;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS.ExecutionResult;
@@ -127,13 +130,20 @@ public class ExternalDiffToolTest extends ExternalToolTestCase {
@Test
public void testUserDefinedToolWithCancelledPrompt() throws Exception {
+ String command = getEchoCommand();
+
+ FileBasedConfig config = db.getConfig();
+ String customToolName = "customTool";
+ config.setString(CONFIG_DIFFTOOL_SECTION, customToolName,
+ CONFIG_KEY_CMD, command);
+
DiffTools manager = new DiffTools(db);
PromptHandler promptHandler = PromptHandler.cancelPrompt();
MissingToolHandler noToolHandler = new MissingToolHandler();
Optional<ExecutionResult> result = manager.compare(local, remote,
- Optional.empty(), BooleanTriState.TRUE, false,
+ Optional.of(customToolName), BooleanTriState.TRUE, false,
BooleanTriState.TRUE, promptHandler, noToolHandler);
assertFalse("Expected no result if user cancels the operation",
result.isPresent());
@@ -245,8 +255,9 @@ public class ExternalDiffToolTest extends ExternalToolTestCase {
gui = true;
String defaultGuiToolName = manager.getDefaultToolName(gui);
- assertNull("Expected default difftool to not be set",
- defaultGuiToolName);
+ assertEquals(
+ "Expected default gui difftool to be the default tool if no gui tool is set",
+ toolName, defaultGuiToolName);
config.setString(CONFIG_DIFF_SECTION, subsection, CONFIG_KEY_GUITOOL,
guiToolName);
@@ -296,6 +307,119 @@ public class ExternalDiffToolTest extends ExternalToolTestCase {
fail("Expected exception to be thrown due to not defined external diff tool");
}
+ @Test
+ public void testDefaultToolExecutionWithPrompt() throws Exception {
+ FileBasedConfig config = db.getConfig();
+ // the default diff tool is configured without a subsection
+ String subsection = null;
+ config.setString("diff", subsection, "tool", "customTool");
+
+ String command = getEchoCommand();
+
+ config.setString("difftool", "customTool", "cmd", command);
+
+ DiffTools manager = new DiffTools(db);
+
+ PromptHandler promptHandler = PromptHandler.acceptPrompt();
+ MissingToolHandler noToolHandler = new MissingToolHandler();
+
+ manager.compare(local, remote, Optional.empty(), BooleanTriState.TRUE,
+ false, BooleanTriState.TRUE, promptHandler, noToolHandler);
+
+ assertEchoCommandHasCorrectOutput();
+ }
+
+ @Test
+ public void testNoDefaultToolName() {
+ DiffTools manager = new DiffTools(db);
+ boolean gui = false;
+ String defaultToolName = manager.getDefaultToolName(gui);
+ assertNull("Expected no default tool when none is configured",
+ defaultToolName);
+
+ gui = true;
+ defaultToolName = manager.getDefaultToolName(gui);
+ assertNull("Expected no default tool when none is configured",
+ defaultToolName);
+ }
+
+ @Test
+ public void testExternalToolInGitAttributes() throws Exception {
+ String content = "attributes:\n*.txt difftool=customTool";
+ File gitattributes = writeTrashFile(".gitattributes", content);
+ gitattributes.deleteOnExit();
+ try (TestRepository<Repository> testRepository = new TestRepository<>(
+ db)) {
+ FileBasedConfig config = db.getConfig();
+ config.setString("difftool", "customTool", "cmd", "echo");
+ testRepository.git().add().addFilepattern(localFile.getName())
+ .call();
+
+ testRepository.git().add().addFilepattern(".gitattributes").call();
+
+ testRepository.branch("master").commit().message("first commit")
+ .create();
+
+ DiffTools manager = new DiffTools(db);
+ Optional<String> tool = manager
+ .getExternalToolFromAttributes(localFile.getName());
+ assertTrue("Failed to find user defined tool", tool.isPresent());
+ assertEquals("Failed to find user defined tool", "customTool",
+ tool.get());
+ } finally {
+ Files.delete(gitattributes.toPath());
+ }
+ }
+
+ @Test
+ public void testNotExternalToolInGitAttributes() throws Exception {
+ String content = "";
+ File gitattributes = writeTrashFile(".gitattributes", content);
+ gitattributes.deleteOnExit();
+ try (TestRepository<Repository> testRepository = new TestRepository<>(
+ db)) {
+ FileBasedConfig config = db.getConfig();
+ config.setString("difftool", "customTool", "cmd", "echo");
+ testRepository.git().add().addFilepattern(localFile.getName())
+ .call();
+
+ testRepository.git().add().addFilepattern(".gitattributes").call();
+
+ testRepository.branch("master").commit().message("first commit")
+ .create();
+
+ DiffTools manager = new DiffTools(db);
+ Optional<String> tool = manager
+ .getExternalToolFromAttributes(localFile.getName());
+ assertFalse(
+ "Expected no external tool if no default tool is specified in .gitattributes",
+ tool.isPresent());
+ } finally {
+ Files.delete(gitattributes.toPath());
+ }
+ }
+
+ @Test(expected = ToolException.class)
+ public void testNullTool() throws Exception {
+ DiffTools manager = new DiffTools(db);
+
+ boolean trustExitCode = true;
+ ExternalDiffTool tool = null;
+ manager.compare(local, remote, tool, trustExitCode);
+ }
+
+ @Test(expected = ToolException.class)
+ public void testNullToolWithPrompt() throws Exception {
+ DiffTools manager = new DiffTools(db);
+
+ PromptHandler promptHandler = PromptHandler.cancelPrompt();
+ MissingToolHandler noToolHandler = new MissingToolHandler();
+
+ Optional<String> tool = null;
+ manager.compare(local, remote, tool, BooleanTriState.TRUE, false,
+ BooleanTriState.TRUE, promptHandler, noToolHandler);
+ }
+
private Optional<ExecutionResult> invokeCompare(String toolName)
throws ToolException {
DiffTools manager = new DiffTools(db);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalMergeToolTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalMergeToolTest.java
index 130b42a92a..94b67b374b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalMergeToolTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/diffmergetool/ExternalMergeToolTest.java
@@ -329,6 +329,68 @@ public class ExternalMergeToolTest extends ExternalToolTestCase {
fail("Expected exception to be thrown due to not defined external merge tool");
}
+ @Test
+ public void testDefaultToolExecutionWithPrompt() throws Exception {
+ FileBasedConfig config = db.getConfig();
+ // the default diff tool is configured without a subsection
+ String subsection = null;
+ config.setString("merge", subsection, "tool", "customTool");
+
+ String command = getEchoCommand();
+
+ config.setString("mergetool", "customTool", "cmd", command);
+
+ MergeTools manager = new MergeTools(db);
+
+ PromptHandler promptHandler = PromptHandler.acceptPrompt();
+ MissingToolHandler noToolHandler = new MissingToolHandler();
+
+ manager.merge(local, remote, merged, base, null, Optional.empty(),
+ BooleanTriState.TRUE, false, promptHandler, noToolHandler);
+
+ assertEchoCommandHasCorrectOutput();
+ }
+
+ @Test
+ public void testNoDefaultToolName() {
+ MergeTools manager = new MergeTools(db);
+ boolean gui = false;
+ String defaultToolName = manager.getDefaultToolName(gui);
+ assertNull("Expected no default tool when none is configured",
+ defaultToolName);
+
+ gui = true;
+ defaultToolName = manager.getDefaultToolName(gui);
+ assertNull("Expected no default tool when none is configured",
+ defaultToolName);
+ }
+
+ @Test(expected = ToolException.class)
+ public void testNullTool() throws Exception {
+ MergeTools manager = new MergeTools(db);
+
+ PromptHandler promptHandler = null;
+ MissingToolHandler noToolHandler = null;
+
+ Optional<String> tool = null;
+
+ manager.merge(local, remote, merged, base, null, tool,
+ BooleanTriState.TRUE, false, promptHandler, noToolHandler);
+ }
+
+ @Test(expected = ToolException.class)
+ public void testNullToolWithPrompt() throws Exception {
+ MergeTools manager = new MergeTools(db);
+
+ PromptHandler promptHandler = PromptHandler.cancelPrompt();
+ MissingToolHandler noToolHandler = new MissingToolHandler();
+
+ Optional<String> tool = null;
+
+ manager.merge(local, remote, merged, base, null, tool,
+ BooleanTriState.TRUE, false, promptHandler, noToolHandler);
+ }
+
private Optional<ExecutionResult> invokeMerge(String toolName)
throws ToolException {
BooleanTriState prompt = BooleanTriState.UNSET;
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 9f264fca34..f0bb6c6c99 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -237,6 +237,9 @@ deleteTagUnexpectedResult=Delete tag returned unexpected result {0}
deletingNotSupported=Deleting {0} not supported.
destinationIsNotAWildcard=Destination is not a wildcard.
detachedHeadDetected=HEAD is detached
+diffToolNotGivenError=No diff tool provided and no defaults configured.
+diffToolNotSpecifiedInGitAttributesError=Diff tool specified in git attributes cannot be found.
+diffToolNullError=Parameter for diff tool cannot be null.
dirCacheDoesNotHaveABackingFile=DirCache does not have a backing file
dirCacheFileIsNotLocked=DirCache {0} not locked
dirCacheIsNotLocked=DirCache is not locked
@@ -457,6 +460,8 @@ mergeStrategyDoesNotSupportHeads=merge strategy {0} does not support {1} heads t
mergeUsingStrategyResultedInDescription=Merge of revisions {0} with base {1} using strategy {2} resulted in: {3}. {4}
mergeRecursiveConflictsWhenMergingCommonAncestors=Multiple common ancestors were found and merging them resulted in a conflict: {0}, {1}
mergeRecursiveTooManyMergeBasesFor = "More than {0} merge bases for:\n a {1}\n b {2} found:\n count {3}"
+mergeToolNotGivenError=No merge tool provided and no defaults configured.
+mergeToolNullError=Parameter for merge tool cannot be null.
messageAndTaggerNotAllowedInUnannotatedTags = Unannotated tags cannot have a message or tagger
minutesAgo={0} minutes ago
mismatchOffset=mismatch offset for object {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index b81e605c13..17e359de49 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -265,6 +265,9 @@ public class JGitText extends TranslationBundle {
/***/ public String deletingNotSupported;
/***/ public String destinationIsNotAWildcard;
/***/ public String detachedHeadDetected;
+ /***/ public String diffToolNotGivenError;
+ /***/ public String diffToolNotSpecifiedInGitAttributesError;
+ /***/ public String diffToolNullError;
/***/ public String dirCacheDoesNotHaveABackingFile;
/***/ public String dirCacheFileIsNotLocked;
/***/ public String dirCacheIsNotLocked;
@@ -485,6 +488,8 @@ public class JGitText extends TranslationBundle {
/***/ public String mergeUsingStrategyResultedInDescription;
/***/ public String mergeRecursiveConflictsWhenMergingCommonAncestors;
/***/ public String mergeRecursiveTooManyMergeBasesFor;
+ /***/ public String mergeToolNotGivenError;
+ /***/ public String mergeToolNullError;
/***/ public String messageAndTaggerNotAllowedInUnannotatedTags;
/***/ public String minutesAgo;
/***/ public String mismatchOffset;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffTools.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffTools.java
index 5fe263a4ef..7cedd82995 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffTools.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/DiffTools.java
@@ -13,18 +13,22 @@ package org.eclipse.jgit.internal.diffmergetool;
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.internal.BooleanTriState;
+import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.ExecutionResult;
+import org.eclipse.jgit.util.StringUtils;
/**
* Manages diff tools.
@@ -39,6 +43,8 @@ public class DiffTools {
private final DiffToolConfig config;
+ private final Repository repo;
+
private final Map<String, ExternalDiffTool> predefinedTools;
private final Map<String, ExternalDiffTool> userDefinedTools;
@@ -64,6 +70,7 @@ public class DiffTools {
}
private DiffTools(Repository repo, StoredConfig config) {
+ this.repo = repo;
this.config = config.get(DiffToolConfig.KEY);
this.gitDir = repo == null ? null : repo.getDirectory();
this.fs = repo == null ? FS.DETECTED : repo.getFS();
@@ -108,15 +115,18 @@ public class DiffTools {
String toolNameToUse;
+ if (toolName == null) {
+ throw new ToolException(JGitText.get().diffToolNullError);
+ }
+
if (toolName.isPresent()) {
toolNameToUse = toolName.get();
} else {
toolNameToUse = getDefaultToolName(gui);
+ }
- if (toolNameToUse == null || toolNameToUse.isEmpty()) {
- noToolHandler.inform(new ArrayList<>(predefinedTools.keySet()));
- toolNameToUse = getFirstAvailableTool();
- }
+ if (StringUtils.isEmptyOrNull(toolNameToUse)) {
+ throw new ToolException(JGitText.get().diffToolNotGivenError);
}
boolean doPrompt;
@@ -167,6 +177,10 @@ public class DiffTools {
FileElement remoteFile, ExternalDiffTool tool,
boolean trustExitCode) throws ToolException {
try {
+ if (tool == null) {
+ throw new ToolException(JGitText
+ .get().diffToolNotSpecifiedInGitAttributesError);
+ }
// prepare the command (replace the file paths)
String command = ExternalToolUtils.prepareCommand(tool.getCommand(),
localFile, remoteFile, null, null);
@@ -218,6 +232,42 @@ public class DiffTools {
}
/**
+ * Provides {@link Optional} with the name of an external diff tool if
+ * specified in git configuration for a path.
+ *
+ * The formed git configuration results from global rules as well as merged
+ * rules from info and worktree attributes.
+ *
+ * Triggers {@link TreeWalk} until specified path found in the tree.
+ *
+ * @param path
+ * path to the node in repository to parse git attributes for
+ * @return name of the difftool if set
+ * @throws ToolException
+ */
+ public Optional<String> getExternalToolFromAttributes(final String path)
+ throws ToolException {
+ return ExternalToolUtils.getExternalToolFromAttributes(repo, path,
+ ExternalToolUtils.KEY_DIFF_TOOL);
+ }
+
+ /**
+ * Checks the availability of the predefined tools in the system.
+ *
+ * @return set of predefined available tools
+ */
+ public Set<String> getPredefinedAvailableTools() {
+ Map<String, ExternalDiffTool> defTools = getPredefinedTools(true);
+ Set<String> availableTools = new LinkedHashSet<>();
+ for (Entry<String, ExternalDiffTool> elem : defTools.entrySet()) {
+ if (elem.getValue().isAvailable()) {
+ availableTools.add(elem.getKey());
+ }
+ }
+ return availableTools;
+ }
+
+ /**
* Get user defined tools map.
*
* @return the user defined tools
@@ -272,8 +322,14 @@ public class DiffTools {
* @return the default tool name
*/
public String getDefaultToolName(boolean gui) {
- return gui ? config.getDefaultGuiToolName()
- : config.getDefaultToolName();
+ String guiToolName;
+ if (gui) {
+ guiToolName = config.getDefaultGuiToolName();
+ if (guiToolName != null) {
+ return guiToolName;
+ }
+ }
+ return config.getDefaultToolName();
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/ExternalToolUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/ExternalToolUtils.java
index 9a69681133..b2dd846d70 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/ExternalToolUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/ExternalToolUtils.java
@@ -14,9 +14,17 @@ import java.io.File;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import org.eclipse.jgit.attributes.Attributes;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.filter.NotIgnoredFilter;
import org.eclipse.jgit.util.FS;
/**
@@ -25,6 +33,16 @@ import org.eclipse.jgit.util.FS;
public class ExternalToolUtils {
/**
+ * Key for merge tool git configuration section
+ */
+ public static final String KEY_MERGE_TOOL = "mergetool"; //$NON-NLS-1$
+
+ /**
+ * Key for diff tool git configuration section
+ */
+ public static final String KEY_DIFF_TOOL = "difftool"; //$NON-NLS-1$
+
+ /**
* Prepare command for execution.
*
* @param command
@@ -174,4 +192,51 @@ public class ExternalToolUtils {
return names;
}
+ /**
+ * Provides {@link Optional} with the name of an external tool if specified
+ * in git configuration for a path.
+ *
+ * The formed git configuration results from global rules as well as merged
+ * rules from info and worktree attributes.
+ *
+ * Triggers {@link TreeWalk} until specified path found in the tree.
+ *
+ * @param repository
+ * target repository to traverse into
+ * @param path
+ * path to the node in repository to parse git attributes for
+ * @param toolKey
+ * config key name for the tool
+ * @return attribute value for the given tool key if set
+ * @throws ToolException
+ */
+ public static Optional<String> getExternalToolFromAttributes(
+ final Repository repository, final String path,
+ final String toolKey) throws ToolException {
+ try {
+ WorkingTreeIterator treeIterator = new FileTreeIterator(repository);
+ try (TreeWalk walk = new TreeWalk(repository)) {
+ walk.addTree(treeIterator);
+ walk.setFilter(new NotIgnoredFilter(0));
+ while (walk.next()) {
+ String treePath = walk.getPathString();
+ if (treePath.equals(path)) {
+ Attributes attrs = walk.getAttributes();
+ if (attrs.containsKey(toolKey)) {
+ return Optional.of(attrs.getValue(toolKey));
+ }
+ }
+ if (walk.isSubtree()) {
+ walk.enterSubtree();
+ }
+ }
+ // no external tool specified
+ return Optional.empty();
+ }
+
+ } catch (RevisionSyntaxException | IOException e) {
+ throw new ToolException(e);
+ }
+ }
+
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/MergeTools.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/MergeTools.java
index d2055272e0..b903201264 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/MergeTools.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/diffmergetool/MergeTools.java
@@ -18,16 +18,21 @@ import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.diffmergetool.FileElement.Type;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.internal.BooleanTriState;
+import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.FS.ExecutionResult;
/**
@@ -43,6 +48,8 @@ public class MergeTools {
private final MergeToolConfig config;
+ private final Repository repo;
+
private final Map<String, ExternalMergeTool> predefinedTools;
private final Map<String, ExternalMergeTool> userDefinedTools;
@@ -68,6 +75,7 @@ public class MergeTools {
}
private MergeTools(Repository repo, StoredConfig config) {
+ this.repo = repo;
this.config = config.get(MergeToolConfig.KEY);
this.gitDir = repo == null ? null : repo.getDirectory();
this.fs = repo == null ? FS.DETECTED : repo.getFS();
@@ -116,17 +124,25 @@ public class MergeTools {
String toolNameToUse;
+ if (toolName == null) {
+ throw new ToolException(JGitText.get().diffToolNullError);
+ }
+
if (toolName.isPresent()) {
toolNameToUse = toolName.get();
} else {
toolNameToUse = getDefaultToolName(gui);
- if (toolNameToUse == null || toolNameToUse.isEmpty()) {
+ if (StringUtils.isEmptyOrNull(toolNameToUse)) {
noToolHandler.inform(new ArrayList<>(predefinedTools.keySet()));
toolNameToUse = getFirstAvailableTool();
}
}
+ if (StringUtils.isEmptyOrNull(toolNameToUse)) {
+ throw new ToolException(JGitText.get().diffToolNotGivenError);
+ }
+
boolean doPrompt;
if (prompt != BooleanTriState.UNSET) {
doPrompt = prompt == BooleanTriState.TRUE;
@@ -277,6 +293,42 @@ public class MergeTools {
}
/**
+ * Provides {@link Optional} with the name of an external merge tool if
+ * specified in git configuration for a path.
+ *
+ * The formed git configuration results from global rules as well as merged
+ * rules from info and worktree attributes.
+ *
+ * Triggers {@link TreeWalk} until specified path found in the tree.
+ *
+ * @param path
+ * path to the node in repository to parse git attributes for
+ * @return name of the difftool if set
+ * @throws ToolException
+ */
+ public Optional<String> getExternalToolFromAttributes(final String path)
+ throws ToolException {
+ return ExternalToolUtils.getExternalToolFromAttributes(repo, path,
+ ExternalToolUtils.KEY_MERGE_TOOL);
+ }
+
+ /**
+ * Checks the availability of the predefined tools in the system.
+ *
+ * @return set of predefined available tools
+ */
+ public Set<String> getPredefinedAvailableTools() {
+ Map<String, ExternalMergeTool> defTools = getPredefinedTools(true);
+ Set<String> availableTools = new LinkedHashSet<>();
+ for (Entry<String, ExternalMergeTool> elem : defTools.entrySet()) {
+ if (elem.getValue().isAvailable()) {
+ availableTools.add(elem.getKey());
+ }
+ }
+ return availableTools;
+ }
+
+ /**
* @return the user defined tools
*/
public Map<String, ExternalMergeTool> getUserDefinedTools() {