Teach JGit to handle external diff/merge tools defined in .gitattributes
Adds API that allows UI to find (and handle) diff/merge tools, specific for the given path. The assumption is that user can specify file type specific diff/merge tools via gitattributes. Bug: 552840 Change-Id: I1daa091e9afa542a9ebb5417853dff0452ed52dd Signed-off-by: Mykola Zakharchuk <zakharchuk.vn@gmail.com> Signed-off-by: Andrey Loskutov <loskutov@gmx.de> Signed-off-by: Andre Bossert <andre.bossert@siemens.com>
This commit is contained in:
parent
ff77d412a9
commit
c32694e5ae
|
@ -79,7 +79,7 @@ public void testUserToolWithCommandNotFoundError() throws Exception {
|
|||
+ errorReturnCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = Die.class)
|
||||
public void testEmptyToolName() throws Exception {
|
||||
String emptyToolName = "";
|
||||
|
||||
|
@ -95,6 +95,7 @@ public void testEmptyToolName() throws Exception {
|
|||
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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
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.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 void testUserDefinedToolWithPrompt() throws Exception {
|
|||
|
||||
@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 void testDefaultTool() throws Exception {
|
|||
|
||||
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 void testUndefinedTool() throws Exception {
|
|||
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);
|
||||
|
|
|
@ -329,6 +329,68 @@ public void testUndefinedTool() throws Exception {
|
|||
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;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -265,6 +265,9 @@ public static JGitText get() {
|
|||
/***/ 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 static JGitText get() {
|
|||
/***/ public String mergeUsingStrategyResultedInDescription;
|
||||
/***/ public String mergeRecursiveConflictsWhenMergingCommonAncestors;
|
||||
/***/ public String mergeRecursiveTooManyMergeBasesFor;
|
||||
/***/ public String mergeToolNotGivenError;
|
||||
/***/ public String mergeToolNullError;
|
||||
/***/ public String messageAndTaggerNotAllowedInUnannotatedTags;
|
||||
/***/ public String minutesAgo;
|
||||
/***/ public String mismatchOffset;
|
||||
|
|
|
@ -13,18 +13,22 @@
|
|||
|
||||
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 DiffTools(StoredConfig config) {
|
|||
}
|
||||
|
||||
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 Optional<ExecutionResult> compare(FileElement localFile,
|
|||
|
||||
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 ExecutionResult compare(FileElement localFile,
|
|||
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);
|
||||
|
@ -217,6 +231,42 @@ public Set<String> getAllToolNames() {
|
|||
getUserDefinedToolNames(), getPredefinedToolNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
@ -272,8 +322,14 @@ public String getFirstAvailableTool() {
|
|||
* @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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,9 +14,17 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
|
@ -24,6 +32,16 @@
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -174,4 +192,51 @@ public static Set<String> createSortedToolSet(String defaultName,
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,16 +18,21 @@
|
|||
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 MergeTools(StoredConfig config) {
|
|||
}
|
||||
|
||||
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 Optional<ExecutionResult> merge(FileElement localFile,
|
|||
|
||||
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;
|
||||
|
@ -276,6 +292,42 @@ public Set<String> getAllToolNames() {
|
|||
getUserDefinedToolNames(), getPredefinedToolNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue