diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java index c03ced563..245219d88 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java @@ -232,6 +232,71 @@ public void testPullEmptyRepository() throws Exception { Git.wrap(empty).pull().call(); } + @Test + public void testPullMergeProgrammaticConfiguration() throws Exception { + // create another commit on another branch in source + source.checkout().setCreateBranch(true).setName("other").call(); + sourceFile = new File(db.getWorkTree(), "file2.txt"); + writeToFile(sourceFile, "content"); + source.add().addFilepattern("file2.txt").call(); + RevCommit sourceCommit = source.commit() + .setMessage("source commit on branch other").call(); + + File targetFile2 = new File(dbTarget.getWorkTree(), "OtherFile.txt"); + writeToFile(targetFile2, "Unconflicting change"); + target.add().addFilepattern("OtherFile.txt").call(); + RevCommit targetCommit = target.commit() + .setMessage("Unconflicting change in local").call(); + + PullResult res = target.pull().setRemote("origin") + .setRemoteBranchName("other") + .setRebase(false).call(); + + MergeResult mergeResult = res.getMergeResult(); + ObjectId[] mergedCommits = mergeResult.getMergedCommits(); + assertEquals(targetCommit.getId(), mergedCommits[0]); + assertEquals(sourceCommit.getId(), mergedCommits[1]); + RevCommit mergeCommit = new RevWalk(dbTarget).parseCommit(mergeResult + .getNewHead()); + String message = "Merge branch 'other' of " + + db.getWorkTree().getAbsolutePath(); + assertEquals(message, mergeCommit.getShortMessage()); + } + + @Test + public void testPullMergeProgrammaticConfigurationImpliedTargetBranch() + throws Exception { + // create another commit on another branch in source + source.checkout().setCreateBranch(true).setName("other").call(); + sourceFile = new File(db.getWorkTree(), "file2.txt"); + writeToFile(sourceFile, "content"); + source.add().addFilepattern("file2.txt").call(); + RevCommit sourceCommit = source.commit() + .setMessage("source commit on branch other").call(); + + target.checkout().setCreateBranch(true).setName("other").call(); + File targetFile2 = new File(dbTarget.getWorkTree(), "OtherFile.txt"); + writeToFile(targetFile2, "Unconflicting change"); + target.add().addFilepattern("OtherFile.txt").call(); + RevCommit targetCommit = target.commit() + .setMessage("Unconflicting change in local").call(); + + // the source branch "other" matching the target branch should be + // implied + PullResult res = target.pull().setRemote("origin").setRebase(false) + .call(); + + MergeResult mergeResult = res.getMergeResult(); + ObjectId[] mergedCommits = mergeResult.getMergedCommits(); + assertEquals(targetCommit.getId(), mergedCommits[0]); + assertEquals(sourceCommit.getId(), mergedCommits[1]); + RevCommit mergeCommit = new RevWalk(dbTarget).parseCommit(mergeResult + .getNewHead()); + String message = "Merge branch 'other' of " + + db.getWorkTree().getAbsolutePath() + " into other"; + assertEquals(message, mergeCommit.getShortMessage()); + } + @Override @Before public void setUp() throws Exception { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java index 4c935095c..c157f14fc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java @@ -82,6 +82,10 @@ public class PullCommand extends TransportCommand { private PullRebaseMode pullRebaseMode = PullRebaseMode.USE_CONFIG; + private String remote; + + private String remoteBranchName; + private enum PullRebaseMode { USE_CONFIG, REBASE, @@ -177,21 +181,24 @@ public PullResult call() throws GitAPIException, JGitText.get().cannotPullOnARepoWithState, repo .getRepositoryState().name())); - // get the configured remote for the currently checked out branch - // stored in configuration key branch..remote Config repoConfig = repo.getConfig(); - String remote = repoConfig.getString( - ConfigConstants.CONFIG_BRANCH_SECTION, branchName, - ConfigConstants.CONFIG_KEY_REMOTE); + if (remote == null) { + // get the configured remote for the currently checked out branch + // stored in configuration key branch..remote + remote = repoConfig.getString( + ConfigConstants.CONFIG_BRANCH_SECTION, branchName, + ConfigConstants.CONFIG_KEY_REMOTE); + } if (remote == null) // fall back to default remote remote = Constants.DEFAULT_REMOTE_NAME; - // get the name of the branch in the remote repository - // stored in configuration key branch..merge - String remoteBranchName = repoConfig.getString( - ConfigConstants.CONFIG_BRANCH_SECTION, branchName, - ConfigConstants.CONFIG_KEY_MERGE); + if (remoteBranchName == null) + // get the name of the branch in the remote repository + // stored in configuration key branch..merge + remoteBranchName = repoConfig.getString( + ConfigConstants.CONFIG_BRANCH_SECTION, branchName, + ConfigConstants.CONFIG_KEY_MERGE); // determines whether rebase should be used after fetching boolean doRebase = false; @@ -211,12 +218,8 @@ public PullResult call() throws GitAPIException, break; } - if (remoteBranchName == null) { - String missingKey = ConfigConstants.CONFIG_BRANCH_SECTION + DOT - + branchName + DOT + ConfigConstants.CONFIG_KEY_MERGE; - throw new InvalidConfigurationException(MessageFormat.format( - JGitText.get().missingConfigurationForKey, missingKey)); - } + if (remoteBranchName == null) + remoteBranchName = branchName; final boolean isRemote = !remote.equals("."); //$NON-NLS-1$ String remoteUri; @@ -309,4 +312,53 @@ public PullResult call() throws GitAPIException, return result; } + /** + * The remote (uri or name) to be used for the pull operation. If no remote + * is set, the branch's configuration will be used. If the branch + * configuration is missing the default value of + * Constants.DEFAULT_REMOTE_NAME will be used. + * + * @see Constants#DEFAULT_REMOTE_NAME + * @param remote + * @return {@code this} + * @since 3.3 + */ + public PullCommand setRemote(String remote) { + checkCallable(); + this.remote = remote; + return this; + } + + /** + * The remote branch name to be used for the pull operation. If no + * remoteBranchName is set, the branch's configuration will be used. If the + * branch configuration is missing the remote branch with the same name as + * the current branch is used. + * + * @param remoteBranchName + * @return {@code this} + * @since 3.3 + */ + public PullCommand setRemoteBranchName(String remoteBranchName) { + checkCallable(); + this.remoteBranchName = remoteBranchName; + return this; + } + + /** + * @return the remote used for the pull operation if it was set explicitly + * @since 3.3 + */ + public String getRemote() { + return remote; + } + + /** + * @return the remote branch name used for the pull operation if it was set + * explicitly + * @since 3.3 + */ + public String getRemoteBranchName() { + return remoteBranchName; + } }