summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.pgm.test/tst/org/eclipse
diff options
context:
space:
mode:
authorAndre Bossert <andre.bossert@siemens.com>2020-01-19 20:52:56 +0100
committerAndrey Loskutov <loskutov@gmx.de>2022-05-25 13:52:04 +0200
commit85734356351ec2df4067b2472a37f6d9bcbb7350 (patch)
tree0596c7e5a59bfdbe37f1fb5456c755ec9a823580 /org.eclipse.jgit.pgm.test/tst/org/eclipse
parent24171b05f0db8487d0a1dc40072cc313bb6e2087 (diff)
downloadjgit-85734356351ec2df4067b2472a37f6d9bcbb7350.tar.gz
jgit-85734356351ec2df4067b2472a37f6d9bcbb7350.zip
Add command line support for "git mergetool"
see: https://git-scm.com/docs/git-mergetool see: https://git-scm.com/docs/git-config * add command line support for "git mergetool" * add option handling for "--tool-help", "--tool=<mytool>", "--[no-]prompt", "--[no-]gui" * handle prompt * add MergeTools * add pre-defined mergetools * print merge actions --> no execute, will be done later Bug: 356832 Change-Id: I6e505ffc3d03f75ecf4bba452a25d25dfcf5793f Signed-off-by: Andre Bossert <andre.bossert@siemens.com>
Diffstat (limited to 'org.eclipse.jgit.pgm.test/tst/org/eclipse')
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DiffToolTest.java106
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ExternalToolTestCase.java136
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeToolTest.java136
3 files changed, 287 insertions, 91 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 e2ff189276..017a5d994f 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
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021, Simeon Andreev <simeon.danailov.andreev@gmail.com> and others.
+ * Copyright (C) 2021-2022, Simeon Andreev <simeon.danailov.andreev@gmail.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
@@ -14,68 +14,30 @@ 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_PROMPT;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_TOOL;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
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.lib.StoredConfig;
-import org.eclipse.jgit.pgm.opt.CmdLineParser;
-import org.eclipse.jgit.pgm.opt.SubcommandHandler;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.treewalk.FileTreeIterator;
-import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.Before;
import org.junit.Test;
-import org.kohsuke.args4j.Argument;
/**
* Testing the {@code difftool} command.
*/
-public class DiffToolTest extends CLIRepositoryTestCase {
- public static class GitCliJGitWrapperParser {
- @Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
- TextBuiltin subcommand;
+public class DiffToolTest extends ExternalToolTestCase {
- @Argument(index = 1, metaVar = "metaVar_arg")
- List<String> arguments = new ArrayList<>();
- }
-
- private String[] runAndCaptureUsingInitRaw(String... args)
- throws Exception {
- CLIGitCommand.Result result = new CLIGitCommand.Result();
-
- GitCliJGitWrapperParser bean = new GitCliJGitWrapperParser();
- CmdLineParser clp = new CmdLineParser(bean);
- clp.parseArgument(args);
-
- TextBuiltin cmd = bean.subcommand;
- cmd.initRaw(db, null, null, result.out, result.err);
- cmd.execute(bean.arguments.toArray(new String[bean.arguments.size()]));
- if (cmd.getOutputWriter() != null) {
- cmd.getOutputWriter().flush();
- }
- if (cmd.getErrorWriter() != null) {
- cmd.getErrorWriter().flush();
- }
- return result.outLines().toArray(new String[0]);
- }
-
- private static final String TOOL_NAME = "some_tool";
- private Git git;
+ private static final String DIFF_TOOL = CONFIG_DIFFTOOL_SECTION;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
- git = new Git(db);
- git.commit().setMessage("initial commit").call();
configureEchoTool(TOOL_NAME);
}
@@ -83,7 +45,7 @@ public class DiffToolTest extends CLIRepositoryTestCase {
public void testNotDefinedTool() throws Exception {
createUnstagedChanges();
- runAndCaptureUsingInitRaw("difftool", "--tool", "undefined");
+ runAndCaptureUsingInitRaw(DIFF_TOOL, "--tool", "undefined");
fail("Expected exception when trying to run undefined tool");
}
@@ -91,7 +53,7 @@ public class DiffToolTest extends CLIRepositoryTestCase {
public void testTool() throws Exception {
RevCommit commit = createUnstagedChanges();
List<DiffEntry> changes = getRepositoryChanges(commit);
- String[] expectedOutput = getExpectedDiffToolOutput(changes);
+ String[] expectedOutput = getExpectedToolOutput(changes);
String[] options = {
"--tool",
@@ -101,7 +63,7 @@ public class DiffToolTest extends CLIRepositoryTestCase {
for (String option : options) {
assertArrayOfLinesEquals("Incorrect output for option: " + option,
expectedOutput,
- runAndCaptureUsingInitRaw("difftool", option,
+ runAndCaptureUsingInitRaw(DIFF_TOOL, option,
TOOL_NAME));
}
}
@@ -110,13 +72,13 @@ public class DiffToolTest extends CLIRepositoryTestCase {
public void testToolTrustExitCode() throws Exception {
RevCommit commit = createUnstagedChanges();
List<DiffEntry> changes = getRepositoryChanges(commit);
- String[] expectedOutput = getExpectedDiffToolOutput(changes);
+ String[] expectedOutput = getExpectedToolOutput(changes);
String[] options = { "--tool", "-t", };
for (String option : options) {
assertArrayOfLinesEquals("Incorrect output for option: " + option,
- expectedOutput, runAndCaptureUsingInitRaw("difftool",
+ expectedOutput, runAndCaptureUsingInitRaw(DIFF_TOOL,
"--trust-exit-code", option, TOOL_NAME));
}
}
@@ -125,13 +87,13 @@ public class DiffToolTest extends CLIRepositoryTestCase {
public void testToolNoGuiNoPromptNoTrustExitcode() throws Exception {
RevCommit commit = createUnstagedChanges();
List<DiffEntry> changes = getRepositoryChanges(commit);
- String[] expectedOutput = getExpectedDiffToolOutput(changes);
+ String[] expectedOutput = getExpectedToolOutput(changes);
String[] options = { "--tool", "-t", };
for (String option : options) {
assertArrayOfLinesEquals("Incorrect output for option: " + option,
- expectedOutput, runAndCaptureUsingInitRaw("difftool",
+ expectedOutput, runAndCaptureUsingInitRaw(DIFF_TOOL,
"--no-gui", "--no-prompt", "--no-trust-exit-code",
option, TOOL_NAME));
}
@@ -141,13 +103,13 @@ public class DiffToolTest extends CLIRepositoryTestCase {
public void testToolCached() throws Exception {
RevCommit commit = createStagedChanges();
List<DiffEntry> changes = getRepositoryChanges(commit);
- String[] expectedOutput = getExpectedDiffToolOutput(changes);
+ String[] expectedOutput = getExpectedToolOutput(changes);
String[] options = { "--cached", "--staged", };
for (String option : options) {
assertArrayOfLinesEquals("Incorrect output for option: " + option,
- expectedOutput, runAndCaptureUsingInitRaw("difftool",
+ expectedOutput, runAndCaptureUsingInitRaw(DIFF_TOOL,
option, "--tool", TOOL_NAME));
}
}
@@ -174,7 +136,8 @@ public class DiffToolTest extends CLIRepositoryTestCase {
String option = "--tool-help";
assertArrayOfLinesEquals("Incorrect output for option: " + option,
- expectedOutput.toArray(new String[0]), runAndCaptureUsingInitRaw("difftool", option));
+ expectedOutput.toArray(new String[0]),
+ runAndCaptureUsingInitRaw(DIFF_TOOL, option));
}
private void configureEchoTool(String toolName) {
@@ -196,33 +159,7 @@ public class DiffToolTest extends CLIRepositoryTestCase {
String.valueOf(false));
}
- private RevCommit createUnstagedChanges() throws Exception {
- writeTrashFile("a", "Hello world a");
- writeTrashFile("b", "Hello world b");
- git.add().addFilepattern(".").call();
- RevCommit commit = git.commit().setMessage("files a & b").call();
- writeTrashFile("a", "New Hello world a");
- writeTrashFile("b", "New Hello world b");
- return commit;
- }
-
- private RevCommit createStagedChanges() throws Exception {
- RevCommit commit = createUnstagedChanges();
- git.add().addFilepattern(".").call();
- return commit;
- }
-
- private List<DiffEntry> getRepositoryChanges(RevCommit commit)
- throws Exception {
- TreeWalk tw = new TreeWalk(db);
- tw.addTree(commit.getTree());
- FileTreeIterator modifiedTree = new FileTreeIterator(db);
- tw.addTree(modifiedTree);
- List<DiffEntry> changes = DiffEntry.scan(tw);
- return changes;
- }
-
- private String[] getExpectedDiffToolOutput(List<DiffEntry> changes) {
+ private String[] getExpectedToolOutput(List<DiffEntry> changes) {
String[] expectedToolOutput = new String[changes.size()];
for (int i = 0; i < changes.size(); ++i) {
DiffEntry change = changes.get(i);
@@ -232,17 +169,4 @@ public class DiffToolTest extends CLIRepositoryTestCase {
}
return expectedToolOutput;
}
-
- private static void assertArrayOfLinesEquals(String failMessage,
- String[] expected, String[] actual) {
- assertEquals(failMessage, toString(expected), toString(actual));
- }
-
- private static String getEchoCommand() {
- /*
- * use 'MERGED' placeholder, as both 'LOCAL' and 'REMOTE' will be
- * replaced with full paths to a temporary file during some of the tests
- */
- return "(echo \"$MERGED\")";
- }
}
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ExternalToolTestCase.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ExternalToolTestCase.java
new file mode 100644
index 0000000000..e10b13efb1
--- /dev/null
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ExternalToolTestCase.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2022, Simeon Andreev <simeon.danailov.andreev@gmail.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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.pgm;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jgit.api.CherryPickResult;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.lib.CLIRepositoryTestCase;
+import org.eclipse.jgit.pgm.opt.CmdLineParser;
+import org.eclipse.jgit.pgm.opt.SubcommandHandler;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.junit.Before;
+import org.kohsuke.args4j.Argument;
+
+/**
+ * Base test case for the {@code difftool} and {@code mergetool} commands.
+ */
+public abstract class ExternalToolTestCase extends CLIRepositoryTestCase {
+
+ public static class GitCliJGitWrapperParser {
+ @Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
+ TextBuiltin subcommand;
+
+ @Argument(index = 1, metaVar = "metaVar_arg")
+ List<String> arguments = new ArrayList<>();
+ }
+
+ protected static final String TOOL_NAME = "some_tool";
+
+ private static final String TEST_BRANCH_NAME = "test_branch";
+
+ private Git git;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ git = new Git(db);
+ git.commit().setMessage("initial commit").call();
+ git.branchCreate().setName(TEST_BRANCH_NAME).call();
+ }
+
+ protected String[] runAndCaptureUsingInitRaw(String... args)
+ throws Exception {
+ CLIGitCommand.Result result = new CLIGitCommand.Result();
+
+ GitCliJGitWrapperParser bean = new GitCliJGitWrapperParser();
+ CmdLineParser clp = new CmdLineParser(bean);
+ clp.parseArgument(args);
+
+ TextBuiltin cmd = bean.subcommand;
+ cmd.initRaw(db, null, null, result.out, result.err);
+ cmd.execute(bean.arguments.toArray(new String[bean.arguments.size()]));
+ if (cmd.getOutputWriter() != null) {
+ cmd.getOutputWriter().flush();
+ }
+ if (cmd.getErrorWriter() != null) {
+ cmd.getErrorWriter().flush();
+ }
+ return result.outLines().toArray(new String[0]);
+ }
+
+ protected CherryPickResult createMergeConflict() throws Exception {
+ writeTrashFile("a", "Hello world a");
+ writeTrashFile("b", "Hello world b");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("files a & b added").call();
+ writeTrashFile("a", "Hello world a 1");
+ writeTrashFile("b", "Hello world b 1");
+ git.add().addFilepattern(".").call();
+ RevCommit commit1 = git.commit().setMessage("files a & b commit 1")
+ .call();
+ git.branchCreate().setName("branch_1").call();
+ git.checkout().setName(TEST_BRANCH_NAME).call();
+ writeTrashFile("a", "Hello world a 2");
+ writeTrashFile("b", "Hello world b 2");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("files a & b commit 2").call();
+ git.branchCreate().setName("branch_2").call();
+ CherryPickResult result = git.cherryPick().include(commit1).call();
+ return result;
+ }
+
+ protected RevCommit createUnstagedChanges() throws Exception {
+ writeTrashFile("a", "Hello world a");
+ writeTrashFile("b", "Hello world b");
+ git.add().addFilepattern(".").call();
+ RevCommit commit = git.commit().setMessage("files a & b").call();
+ writeTrashFile("a", "New Hello world a");
+ writeTrashFile("b", "New Hello world b");
+ return commit;
+ }
+
+ protected RevCommit createStagedChanges() throws Exception {
+ RevCommit commit = createUnstagedChanges();
+ git.add().addFilepattern(".").call();
+ return commit;
+ }
+
+ protected List<DiffEntry> getRepositoryChanges(RevCommit commit)
+ throws Exception {
+ TreeWalk tw = new TreeWalk(db);
+ tw.addTree(commit.getTree());
+ FileTreeIterator modifiedTree = new FileTreeIterator(db);
+ tw.addTree(modifiedTree);
+ List<DiffEntry> changes = DiffEntry.scan(tw);
+ return changes;
+ }
+
+ protected static void assertArrayOfLinesEquals(String failMessage,
+ String[] expected, String[] actual) {
+ assertEquals(failMessage, toString(expected), toString(actual));
+ }
+
+ protected static String getEchoCommand() {
+ /*
+ * use 'MERGED' placeholder, as both 'LOCAL' and 'REMOTE' will be
+ * replaced with full paths to a temporary file during some of the tests
+ */
+ return "(echo \"$MERGED\")";
+ }
+}
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeToolTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeToolTest.java
new file mode 100644
index 0000000000..32cd60415e
--- /dev/null
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeToolTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2022, Simeon Andreev <simeon.danailov.andreev@gmail.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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.pgm;
+
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CMD;
+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_MERGETOOL_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_MERGE_SECTION;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jgit.internal.diffmergetool.CommandLineMergeTool;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Testing the {@code mergetool} command.
+ */
+public class MergeToolTest extends ExternalToolTestCase {
+
+ private static final String MERGE_TOOL = CONFIG_MERGETOOL_SECTION;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ configureEchoTool(TOOL_NAME);
+ }
+
+ @Test
+ public void testTool() throws Exception {
+ createMergeConflict();
+ String[] expectedOutput = getExpectedToolOutput();
+
+ String[] options = {
+ "--tool",
+ "-t",
+ };
+
+ for (String option : options) {
+ assertArrayOfLinesEquals("Incorrect output for option: " + option,
+ expectedOutput,
+ runAndCaptureUsingInitRaw(MERGE_TOOL, option,
+ TOOL_NAME));
+ }
+ }
+
+ @Test
+ public void testToolNoGuiNoPrompt() throws Exception {
+ createMergeConflict();
+ String[] expectedOutput = getExpectedToolOutput();
+
+ String[] options = { "--tool", "-t", };
+
+ for (String option : options) {
+ assertArrayOfLinesEquals("Incorrect output for option: " + option,
+ expectedOutput, runAndCaptureUsingInitRaw(MERGE_TOOL,
+ "--no-gui", "--no-prompt", option, TOOL_NAME));
+ }
+ }
+
+ @Test
+ public void testToolHelp() throws Exception {
+ CommandLineMergeTool[] defaultTools = CommandLineMergeTool.values();
+ List<String> expectedOutput = new ArrayList<>();
+ expectedOutput.add(
+ "'git mergetool --tool=<tool>' may be set to one of the following:");
+ for (CommandLineMergeTool defaultTool : defaultTools) {
+ String toolName = defaultTool.name();
+ expectedOutput.add(toolName);
+ }
+ String customToolHelpLine = TOOL_NAME + "." + CONFIG_KEY_CMD + " "
+ + getEchoCommand();
+ expectedOutput.add("user-defined:");
+ expectedOutput.add(customToolHelpLine);
+ String[] userDefinedToolsHelp = {
+ "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.",
+ };
+ expectedOutput.addAll(Arrays.asList(userDefinedToolsHelp));
+
+ String option = "--tool-help";
+ assertArrayOfLinesEquals("Incorrect output for option: " + option,
+ expectedOutput.toArray(new String[0]),
+ runAndCaptureUsingInitRaw(MERGE_TOOL, option));
+ }
+
+ private void configureEchoTool(String toolName) {
+ StoredConfig config = db.getConfig();
+ // the default merge tool is configured without a subsection
+ String subsection = null;
+ config.setString(CONFIG_MERGE_SECTION, subsection, CONFIG_KEY_TOOL,
+ toolName);
+
+ String command = getEchoCommand();
+
+ config.setString(CONFIG_MERGETOOL_SECTION, toolName, CONFIG_KEY_CMD,
+ command);
+ /*
+ * prevent prompts as we are running in tests and there is no user to
+ * interact with on the command line
+ */
+ config.setString(CONFIG_MERGETOOL_SECTION, toolName, CONFIG_KEY_PROMPT,
+ String.valueOf(false));
+ }
+
+ private String[] getExpectedToolOutput() {
+ String[] mergeConflictFilenames = { "a", "b", };
+ List<String> expectedOutput = new ArrayList<>();
+ expectedOutput.add("Merging:");
+ for (String mergeConflictFilename : mergeConflictFilenames) {
+ expectedOutput.add(mergeConflictFilename);
+ }
+ for (String mergeConflictFilename : mergeConflictFilenames) {
+ expectedOutput.add("Normal merge conflict for '"
+ + mergeConflictFilename + "':");
+ expectedOutput.add("{local}: modified file");
+ expectedOutput.add("{remote}: modified file");
+ expectedOutput.add("TODO: Launch mergetool '" + TOOL_NAME
+ + "' for path '" + mergeConflictFilename + "'...");
+ }
+ return expectedOutput.toArray(new String[0]);
+ }
+}