changeset 29063:8ede973597fd

rebase: handle successor targets (issue5198) When a parent has a successor (indicated by revprecursor in state), we need to use it.
author timeless <timeless@mozdev.org>
date Mon, 11 Apr 2016 21:33:07 +0000
parents 906a1c8a75fd
children 207c0db08953
files hgext/rebase.py tests/test-rebase-obsolete.t
diffstat 2 files changed, 66 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/rebase.py	Wed May 04 06:44:44 2016 +0900
+++ b/hgext/rebase.py	Mon Apr 11 21:33:07 2016 +0000
@@ -390,7 +390,8 @@
                 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
                             _('changesets'), total)
                 p1, p2, base = defineparents(repo, rev, target, state,
-                                             targetancestors)
+                                             targetancestors,
+                                             obsoletenotrebased)
                 storestatus(repo, originalwd, target, state, collapsef, keepf,
                             keepbranchesf, external, activebookmark)
                 storecollapsemsg(repo, collapsemsg)
@@ -455,7 +456,8 @@
 
         if collapsef and not keepopen:
             p1, p2, _base = defineparents(repo, min(state), target,
-                                          state, targetancestors)
+                                          state, targetancestors,
+                                          obsoletenotrebased)
             editopt = opts.get('edit')
             editform = 'rebase.collapse'
             if collapsemsg:
@@ -744,10 +746,12 @@
                  'experimental.rebaseskipobsolete to False')
         raise error.Abort(msg, hint=hint)
 
-def defineparents(repo, rev, target, state, targetancestors):
+def defineparents(repo, rev, target, state, targetancestors,
+                  obsoletenotrebased):
     'Return the new parent relationship of the revision that will be rebased'
     parents = repo[rev].parents()
     p1 = p2 = nullrev
+    rp1 = None
 
     p1n = parents[0].rev()
     if p1n in targetancestors:
@@ -771,6 +775,8 @@
         if p2n in state:
             if p1 == target: # p1n in targetancestors or external
                 p1 = state[p2n]
+                if p1 == revprecursor:
+                    rp1 = obsoletenotrebased[p2n]
             elif state[p2n] in revskipped:
                 p2 = nearestrebased(repo, p2n, state)
                 if p2 is None:
@@ -784,7 +790,7 @@
                         'would have 3 parents') % rev)
             p2 = p2n
     repo.ui.debug(" future parents are %d and %d\n" %
-                            (repo[p1].rev(), repo[p2].rev()))
+                            (repo[rp1 or p1].rev(), repo[p2].rev()))
 
     if not any(p.rev() in state for p in parents):
         # Case (1) root changeset of a non-detaching rebase set.
@@ -828,6 +834,8 @@
         # make it feasible to consider different cases separately. In these
         # other cases we currently just leave it to the user to correctly
         # resolve an impossible merge using a wrong ancestor.
+        #
+        # xx, p1 could be -4, and both parents could probably be -4...
         for p in repo[rev].parents():
             if state.get(p.rev()) == p1:
                 base = p.rev()
@@ -838,7 +846,7 @@
             # Raise because this function is called wrong (see issue 4106)
             raise AssertionError('no base found to rebase on '
                                  '(defineparents called wrong)')
-    return p1, p2, base
+    return rp1 or p1, p2, base
 
 def isagitpatch(repo, patchname):
     'Return true if the given patch is in git format'
--- a/tests/test-rebase-obsolete.t	Wed May 04 06:44:44 2016 +0900
+++ b/tests/test-rebase-obsolete.t	Mon Apr 11 21:33:07 2016 +0000
@@ -863,3 +863,56 @@
   rebasing 20:b82fb57ea638 "willconflict second version"
   note: not rebasing 21:8b31da3c4919 "dummy change", already in destination as 19:601db7a18f51 "dummy change successor"
   rebasing 22:7bdc8a87673d "dummy change" (tip)
+  $ cd ..
+
+rebase source is obsoleted (issue5198)
+---------------------------------
+
+  $ hg clone base amended
+  updating to branch default
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd amended
+  $ hg up 9520eea781bc
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo 1 >> E
+  $ hg commit --amend -m "E'"
+  $ hg log -G
+  @  9:69abe8906104 E'
+  |
+  | o  7:02de42196ebe H
+  | |
+  | | o  6:eea13746799a G
+  | |/|
+  | o |  5:24b6387c8c8c F
+  |/ /
+  | x  4:9520eea781bc E
+  |/
+  | o  3:32af7686d403 D
+  | |
+  | o  2:5fddd98957c8 C
+  | |
+  | o  1:42ccdea3bb16 B
+  |/
+  o  0:cd010b8cd998 A
+  
+  $ hg rebase -d . -s 9520eea781bc
+  note: not rebasing 4:9520eea781bc "E", already in destination as 9:69abe8906104 "E'"
+  rebasing 6:eea13746799a "G"
+  $ hg log -G
+  o    10:17be06e82e95 G
+  |\
+  | @  9:69abe8906104 E'
+  | |
+  +---o  7:02de42196ebe H
+  | |
+  o |  5:24b6387c8c8c F
+  |/
+  | o  3:32af7686d403 D
+  | |
+  | o  2:5fddd98957c8 C
+  | |
+  | o  1:42ccdea3bb16 B
+  |/
+  o  0:cd010b8cd998 A
+  
+  $ cd ..