]> source.dussan.org Git - jgit.git/commitdiff
Add support for pull with --rebase and --no-rebase 03/6003/4
authorMikael Karlsson <mmmicke@gmail.com>
Wed, 16 May 2012 16:34:38 +0000 (18:34 +0200)
committerChris Aniszczyk <zx@twitter.com>
Fri, 16 Nov 2012 20:51:35 +0000 (12:51 -0800)
Bug: 394501
Change-Id: I697e2fc82a46c03762111eb1de93e673a2643b4f
Signed-off-by: Chris Aniszczyk <zx@twitter.com>
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandWithRebaseTest.java
org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java

index 2c1eb768bd7d326e80b91efe1cb9494ed39b86d9..2f2faf8228f99d0dd2ce31d7a098ea5c9ab76107 100644 (file)
@@ -44,6 +44,7 @@ package org.eclipse.jgit.api;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -58,11 +59,14 @@ import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.RebaseResult.Status;
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryState;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.merge.MergeStrategy;
 import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.storage.file.FileRepository;
 import org.eclipse.jgit.transport.RefSpec;
 import org.eclipse.jgit.transport.RemoteConfig;
@@ -226,6 +230,72 @@ public class PullCommandWithRebaseTest extends RepositoryTestCase {
                                .getRepository().getRepositoryState());
        }
 
+    @Test
+       public void testPullFastForwardWithLocalCommitAndRebaseFlagSet() throws Exception {
+               final String SOURCE_COMMIT_MESSAGE = "Source commit message for rebase flag test";
+               final String TARGET_COMMIT_MESSAGE = "Target commit message for rebase flag test";
+
+               assertFalse(SOURCE_COMMIT_MESSAGE.equals(TARGET_COMMIT_MESSAGE));
+
+               final String SOURCE_FILE_CONTENTS = "Source change";
+               final String NEW_FILE_CONTENTS = "New file from target";
+
+               // make sure the config for target says we should pull with merge
+               // we will override this later with the setRebase method
+               StoredConfig targetConfig = dbTarget.getConfig();
+               targetConfig.setBoolean("branch", "master", "rebase", false);
+               targetConfig.save();
+
+               // create commit in source
+               writeToFile(sourceFile, SOURCE_FILE_CONTENTS);
+               source.add().addFilepattern(sourceFile.getName()).call();
+               source.commit().setMessage(SOURCE_COMMIT_MESSAGE).call();
+
+               // create commit in target, not conflicting with the new commit in source
+               File newFile = new File(dbTarget.getWorkTree().getPath() + "/newFile.txt");
+               writeToFile(newFile, NEW_FILE_CONTENTS);
+               target.add().addFilepattern(newFile.getName()).call();
+               target.commit().setMessage(TARGET_COMMIT_MESSAGE).call();
+
+               // verify that rebase is set to false in the config
+               assertFalse(targetConfig.getBoolean("branch", "master", "rebase", true));
+
+               // pull with rebase - local commit in target should be on top
+               PullResult pullResult = target.pull().setRebase(true).call();
+
+               // make sure pull is considered successful
+               assertTrue(pullResult.isSuccessful());
+
+               // verify rebase result is ok
+               RebaseResult rebaseResult = pullResult.getRebaseResult();
+               assertNotNull(rebaseResult);
+               assertNull(rebaseResult.getFailingPaths());
+               assertEquals(Status.OK, rebaseResult.getStatus());
+
+               // Get the HEAD and HEAD~1 commits
+               Repository targetRepo = target.getRepository();
+               RevWalk revWalk = new RevWalk(targetRepo);
+               ObjectId headId = targetRepo.resolve(Constants.HEAD);
+               RevCommit root = revWalk.parseCommit(headId);
+               revWalk.markStart(root);
+               // HEAD
+               RevCommit head = revWalk.next();
+               // HEAD~1
+               RevCommit beforeHead = revWalk.next();
+
+               // verify the commit message on the HEAD commit
+               assertEquals(TARGET_COMMIT_MESSAGE, head.getFullMessage());
+               // verify the commit just before HEAD
+               assertEquals(SOURCE_COMMIT_MESSAGE, beforeHead.getFullMessage());
+
+               // verify file states
+               assertFileContentsEqual(sourceFile, SOURCE_FILE_CONTENTS);
+               assertFileContentsEqual(newFile, NEW_FILE_CONTENTS);
+               // verify repository state
+               assertEquals(RepositoryState.SAFE, target
+                       .getRepository().getRepositoryState());
+       }
+
        @Override
        @Before
        public void setUp() throws Exception {
index 5b8c776fd7dd860655e659b0f2eddc9da7991077..81790988851ae31d6bc5a6a447b0cbdff135b92e 100644 (file)
@@ -80,6 +80,14 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
 
        private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
 
+       private PullRebaseMode pullRebaseMode = PullRebaseMode.USE_CONFIG;
+
+       private enum PullRebaseMode {
+               USE_CONFIG,
+               REBASE,
+               NO_REBASE
+       }
+
        /**
         * @param repo
         */
@@ -97,6 +105,28 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
                return this;
        }
 
+       /**
+        * Set if rebase should be used after fetching. If set to true, rebase is
+        * used instead of merge. This is equivalent to --rebase on the command line.
+        * <p/>
+        * If set to false, merge is used after fetching, overriding the configuration
+        * file. This is equivalent to --no-rebase on the command line.
+        * <p/>
+        * This setting overrides the settings in the configuration file.
+        * By default, the setting in the repository configuration file is used.
+        * <p/>
+        * A branch can be configured to use rebase by default.
+        * See branch.[name].rebase and branch.autosetuprebase.
+        *
+        * @param useRebase
+        * @return {@code this}
+        */
+       public PullCommand setRebase(boolean useRebase) {
+               checkCallable();
+               pullRebaseMode = useRebase ? PullRebaseMode.REBASE : PullRebaseMode.NO_REBASE;
+               return this;
+       }
+
        /**
         * Executes the {@code Pull} command with all the options and parameters
         * collected by the setter methods (e.g.
@@ -162,10 +192,24 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
                String remoteBranchName = repoConfig.getString(
                                ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
                                ConfigConstants.CONFIG_KEY_MERGE);
-               // check if the branch is configured for pull-rebase
-               boolean doRebase = repoConfig.getBoolean(
-                               ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
-                               ConfigConstants.CONFIG_KEY_REBASE, false);
+
+        // determines whether rebase should be used after fetching
+        boolean doRebase = false;
+        switch (pullRebaseMode) {
+            case REBASE:
+                doRebase = true;
+                break;
+            case NO_REBASE:
+                doRebase = false;
+                break;
+            case USE_CONFIG:
+            default:
+                // check if the branch is configured for pull-rebase
+                doRebase = repoConfig.getBoolean(
+                        ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
+                        ConfigConstants.CONFIG_KEY_REBASE, false);
+                break;
+        }
 
                if (remoteBranchName == null) {
                        String missingKey = ConfigConstants.CONFIG_BRANCH_SECTION + DOT