[PATCH 2 of 2] rebase: collapse revisions between -s and -b if -s is used

Stefano Tortarolo stefano.tortarolo at gmail.com
Sun Mar 29 15:28:14 CDT 2009


# HG changeset patch
# User Stefano Tortarolo <stefano.tortarolo at gmail.com>
# Date 1238341252 -7200
# Node ID ddeee9ddf6ad1d5c5c4e03e6d1237d779a7d335c
# Parent  1b0dfe2121f22ca65e78541a0132f00940a9401c
rebase: collapse revisions between -s and -b if -s is used

Running rebase --upto x -s y collapses the revisions between
y and its base. The revisions between y and x will be rebased
as usual.
Note that it doesn't collapse the commit messages.

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -49,6 +49,7 @@
     """
     originalwd = target = None
     external = nullrev
+    collapseupto = nullrev
     state = skipped = {}
 
     lock = wlock = None
@@ -82,8 +83,8 @@
                 raise error.ParseError('rebase',
                     _('abort and continue do not allow specifying revisions'))
 
-            (originalwd, target, state, collapsef, keepf, keepbranchesf,
-                                            external) = restorestatus(repo)
+            (originalwd, target, state, collapsef, collapseupto, keepf,
+                                keepbranchesf, external) = restorestatus(repo)
             if abortf:
                 abort(repo, originalwd, target, state)
                 return
@@ -92,6 +93,7 @@
                 keepf = True
                 if srcf and not basef:
                     ui.warn(_('warning: assuming base instead of source\n'))
+                    collapseupto = repo[srcf].rev()
                     basef = srcf
                     srcf = None
             if srcf and basef:
@@ -112,18 +114,26 @@
             def extrafn(ctx, extra):
                 extra['branch'] = ctx.branch()
 
+        # Collapse revisions between min(state) and collapseupto
+        if collapseupto != nullrev and min(state) != collapseupto:
+            repo.ui.status(_('collapsing up to %d\n') % collapseupto)
+            collapsef = True
+
         # Rebase
         targetancestors = list(repo.changelog.ancestors(target))
         targetancestors.append(target)
 
         for rev in util.sort(state):
             if state[rev] == -1:
-                storestatus(repo, originalwd, target, state, collapsef, keepf,
-                                                    keepbranchesf, external)
+                if collapseupto and rev == collapseupto:
+                    collapsef = False
+                storestatus(repo, originalwd, target, state, collapsef,
+                                collapseupto, keepf, keepbranchesf, external)
                 rebasenode(repo, rev, target, state, skipped, targetancestors,
                                                        collapsef, extrafn)
         ui.note(_('rebase merging completed\n'))
 
+        # Note that this is true only if --collapse is used, not with --upto
         if collapsef:
             p1, p2 = defineparents(repo, min(state), target,
                                                         state, targetancestors)
@@ -285,14 +295,15 @@
                             git=opts.get('git', False),rev=[str(state[rev])])
         repo.mq.save_dirty()
 
-def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
-                                                                external):
+def storestatus(repo, originalwd, target, state, collapse, collapseupto, keep,
+                                keepbranches, external):
     'Store the current status to allow recovery'
     f = repo.opener("rebasestate", "w")
     f.write(repo[originalwd].hex() + '\n')
     f.write(repo[target].hex() + '\n')
     f.write(repo[external].hex() + '\n')
     f.write('%d\n' % int(collapse))
+    f.write(repo[collapseupto].hex() + '\n')
     f.write('%d\n' % int(keep))
     f.write('%d\n' % int(keepbranches))
     for d, v in state.iteritems():
@@ -325,14 +336,17 @@
             elif i == 3:
                 collapse = bool(int(l))
             elif i == 4:
+                collapseupto = repo[l].rev()
+            elif i == 5:
                 keep = bool(int(l))
-            elif i == 5:
+            elif i == 6:
                 keepbranches = bool(int(l))
             else:
                 oldrev, newrev = l.split(':')
                 state[repo[oldrev].rev()] = repo[newrev].rev()
         repo.ui.debug(_('rebase status resumed\n'))
-        return originalwd, target, state, collapse, keep, keepbranches, external
+        return (originalwd, target, state, collapse, collapseupto,
+                                keep, keepbranches, external)
     except IOError, err:
         if err.errno != errno.ENOENT:
             raise
diff --git a/tests/test-rebase-check-restore b/tests/test-rebase-check-restore
--- a/tests/test-rebase-check-restore
+++ b/tests/test-rebase-check-restore
@@ -79,5 +79,23 @@
 hg resolve -m A
 hg rebase --continue 2>&1 | sed 's/\(saving bundle to \).*/\1/'
 hg glog  --template '{rev}:{desc}:{branches}\n'
+echo "Expected A B E" 
+hg manifest
+
+echo
+echo "% - Cherrypick E onto C - collapsing and conflict"
+createrepo > /dev/null 2>&1
+hg glog  --template '{rev}:{desc}:{branches}\n'
+hg rebase --upto 4 -s 4 -d 2 2>&1 | sed 's/\(saving bundle to \).*/\1/'
+
+echo
+echo "% - Solve the conflict and go on - must stop at E"
+echo 'conflict solved' > A
+rm A.orig
+hg resolve -m A
+hg rebase --continue 2>&1 | sed 's/\(saving bundle to \).*/\1/'
+hg glog  --template '{rev}:{desc}:{branches}\n'
+echo "Expected A B E" 
+hg manifest
 
 exit 0
diff --git a/tests/test-rebase-check-restore.out b/tests/test-rebase-check-restore.out
--- a/tests/test-rebase-check-restore.out
+++ b/tests/test-rebase-check-restore.out
@@ -123,3 +123,53 @@
 |/
 o  0:A:
 
+Expected A B E
+A
+B
+E
+
+% - Cherrypick E onto C - collapsing and conflict
+@  6:G:notdefault
+|
+| o  5:F:
+| |
+| o  4:E:
+| |
+| o  3:D:
+|/
+| o  2:C:
+| |
+| o  1:B:
+|/
+o  0:A:
+
+warning: assuming base instead of source
+collapsing up to 4
+merging A
+warning: conflicts during merge.
+merging A failed!
+abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
+
+% - Solve the conflict and go on - must stop at E
+collapsing up to 4
+rebase completed
+@  7:E:
+|
+| o  6:G:notdefault
+| |
+| | o  5:F:
+| | |
+| | o  4:E:
+| | |
+| | o  3:D:
+| |/
+o |  2:C:
+| |
+o |  1:B:
+|/
+o  0:A:
+
+Expected A B E
+A
+B
+E
diff --git a/tests/test-rebase-cherrypicking b/tests/test-rebase-cherrypicking
--- a/tests/test-rebase-cherrypicking
+++ b/tests/test-rebase-cherrypicking
@@ -42,7 +42,7 @@
 
 echo
 echo '% Cherry picking D, E onto C'
-echo '% (using --source, converted to --base)'
+echo '% (using --source, converted to --base, no collapsing)'
 createrepo > /dev/null 2>&1
 hg glog  --template '{rev}: {desc}\n'
 hg rebase --upto 4 -s 3 -d 2 2>&1 | sed 's/\(saving bundle to \).*/\1/'
@@ -52,6 +52,7 @@
 
 echo
 echo '% Cherry picking F onto C'
+echo '% (using --source, converted to --base, collapsing)'
 createrepo > /dev/null 2>&1
 hg glog  --template '{rev}: {desc}\n'
 hg rebase --upto 5 -s 5 -d 2 2>&1 | sed 's/\(saving bundle to \).*/\1/'
@@ -59,4 +60,14 @@
 echo "Expected A, B, C, D, E, F"
 hg manifest
 
+echo
+echo '% Cherry picking base F onto C'
+echo '% (using --base, no collapsing)'
+createrepo > /dev/null 2>&1
+hg glog  --template '{rev}: {desc}\n'
+hg rebase --upto 5 -b 5 -d 2 2>&1 | sed 's/\(saving bundle to \).*/\1/'
+hg glog  --template '{rev}: {desc}\n'
+echo "Expected A, B, C, D, E, F"
+hg manifest
+
 exit 0
diff --git a/tests/test-rebase-cherrypicking.out b/tests/test-rebase-cherrypicking.out
--- a/tests/test-rebase-cherrypicking.out
+++ b/tests/test-rebase-cherrypicking.out
@@ -37,7 +37,7 @@
 D
 
 % Cherry picking D, E onto C
-% (using --source, converted to --base)
+% (using --source, converted to --base, no collapsing)
 @  6: G
 |
 o  5: F
@@ -80,6 +80,7 @@
 E
 
 % Cherry picking F onto C
+% (using --source, converted to --base, collapsing)
 @  6: G
 |
 o  5: F
@@ -95,6 +96,48 @@
 o  0: A
 
 warning: assuming base instead of source
+collapsing up to 5
+rebase completed
+@  7: F
+|
+| o  6: G
+| |
+| o  5: F
+| |
+| o  4: E
+| |
+| o  3: D
+| |
+o |  2: C
+| |
+o |  1: B
+|/
+o  0: A
+
+Expected A, B, C, D, E, F
+A
+B
+C
+D
+E
+F
+
+% Cherry picking base F onto C
+% (using --base, no collapsing)
+@  6: G
+|
+o  5: F
+|
+o  4: E
+|
+o  3: D
+|
+| o  2: C
+| |
+| o  1: B
+|/
+o  0: A
+
 rebase completed
 @  9: F
 |


More information about the Mercurial-devel mailing list