Mercurial > hg
comparison hgext/rebase.py @ 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 | 261c25372959 |
children | e521cb13d354 |
comparison
equal
deleted
inserted
replaced
29062:906a1c8a75fd | 29063:8ede973597fd |
---|---|
388 if state[rev] == revtodo: | 388 if state[rev] == revtodo: |
389 ui.status(_('rebasing %s\n') % desc) | 389 ui.status(_('rebasing %s\n') % desc) |
390 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)), | 390 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)), |
391 _('changesets'), total) | 391 _('changesets'), total) |
392 p1, p2, base = defineparents(repo, rev, target, state, | 392 p1, p2, base = defineparents(repo, rev, target, state, |
393 targetancestors) | 393 targetancestors, |
394 obsoletenotrebased) | |
394 storestatus(repo, originalwd, target, state, collapsef, keepf, | 395 storestatus(repo, originalwd, target, state, collapsef, keepf, |
395 keepbranchesf, external, activebookmark) | 396 keepbranchesf, external, activebookmark) |
396 storecollapsemsg(repo, collapsemsg) | 397 storecollapsemsg(repo, collapsemsg) |
397 if len(repo[None].parents()) == 2: | 398 if len(repo[None].parents()) == 2: |
398 repo.ui.debug('resuming interrupted rebase\n') | 399 repo.ui.debug('resuming interrupted rebase\n') |
453 ui.progress(_('rebasing'), None) | 454 ui.progress(_('rebasing'), None) |
454 ui.note(_('rebase merging completed\n')) | 455 ui.note(_('rebase merging completed\n')) |
455 | 456 |
456 if collapsef and not keepopen: | 457 if collapsef and not keepopen: |
457 p1, p2, _base = defineparents(repo, min(state), target, | 458 p1, p2, _base = defineparents(repo, min(state), target, |
458 state, targetancestors) | 459 state, targetancestors, |
460 obsoletenotrebased) | |
459 editopt = opts.get('edit') | 461 editopt = opts.get('edit') |
460 editform = 'rebase.collapse' | 462 editform = 'rebase.collapse' |
461 if collapsemsg: | 463 if collapsemsg: |
462 commitmsg = collapsemsg | 464 commitmsg = collapsemsg |
463 else: | 465 else: |
742 'or were marked as obsolete') | 744 'or were marked as obsolete') |
743 hint = _('to force the rebase, set the config ' | 745 hint = _('to force the rebase, set the config ' |
744 'experimental.rebaseskipobsolete to False') | 746 'experimental.rebaseskipobsolete to False') |
745 raise error.Abort(msg, hint=hint) | 747 raise error.Abort(msg, hint=hint) |
746 | 748 |
747 def defineparents(repo, rev, target, state, targetancestors): | 749 def defineparents(repo, rev, target, state, targetancestors, |
750 obsoletenotrebased): | |
748 'Return the new parent relationship of the revision that will be rebased' | 751 'Return the new parent relationship of the revision that will be rebased' |
749 parents = repo[rev].parents() | 752 parents = repo[rev].parents() |
750 p1 = p2 = nullrev | 753 p1 = p2 = nullrev |
754 rp1 = None | |
751 | 755 |
752 p1n = parents[0].rev() | 756 p1n = parents[0].rev() |
753 if p1n in targetancestors: | 757 if p1n in targetancestors: |
754 p1 = target | 758 p1 = target |
755 elif p1n in state: | 759 elif p1n in state: |
769 p2n = parents[1].rev() | 773 p2n = parents[1].rev() |
770 # interesting second parent | 774 # interesting second parent |
771 if p2n in state: | 775 if p2n in state: |
772 if p1 == target: # p1n in targetancestors or external | 776 if p1 == target: # p1n in targetancestors or external |
773 p1 = state[p2n] | 777 p1 = state[p2n] |
778 if p1 == revprecursor: | |
779 rp1 = obsoletenotrebased[p2n] | |
774 elif state[p2n] in revskipped: | 780 elif state[p2n] in revskipped: |
775 p2 = nearestrebased(repo, p2n, state) | 781 p2 = nearestrebased(repo, p2n, state) |
776 if p2 is None: | 782 if p2 is None: |
777 # no ancestors rebased yet, detach | 783 # no ancestors rebased yet, detach |
778 p2 = target | 784 p2 = target |
782 if p2 != nullrev: # p1n external too => rev is a merged revision | 788 if p2 != nullrev: # p1n external too => rev is a merged revision |
783 raise error.Abort(_('cannot use revision %d as base, result ' | 789 raise error.Abort(_('cannot use revision %d as base, result ' |
784 'would have 3 parents') % rev) | 790 'would have 3 parents') % rev) |
785 p2 = p2n | 791 p2 = p2n |
786 repo.ui.debug(" future parents are %d and %d\n" % | 792 repo.ui.debug(" future parents are %d and %d\n" % |
787 (repo[p1].rev(), repo[p2].rev())) | 793 (repo[rp1 or p1].rev(), repo[p2].rev())) |
788 | 794 |
789 if not any(p.rev() in state for p in parents): | 795 if not any(p.rev() in state for p in parents): |
790 # Case (1) root changeset of a non-detaching rebase set. | 796 # Case (1) root changeset of a non-detaching rebase set. |
791 # Let the merge mechanism find the base itself. | 797 # Let the merge mechanism find the base itself. |
792 base = None | 798 base = None |
826 # or if the other is not parent 'outside' (especially not if the other | 832 # or if the other is not parent 'outside' (especially not if the other |
827 # parent has been rebased). The current implementation does not | 833 # parent has been rebased). The current implementation does not |
828 # make it feasible to consider different cases separately. In these | 834 # make it feasible to consider different cases separately. In these |
829 # other cases we currently just leave it to the user to correctly | 835 # other cases we currently just leave it to the user to correctly |
830 # resolve an impossible merge using a wrong ancestor. | 836 # resolve an impossible merge using a wrong ancestor. |
837 # | |
838 # xx, p1 could be -4, and both parents could probably be -4... | |
831 for p in repo[rev].parents(): | 839 for p in repo[rev].parents(): |
832 if state.get(p.rev()) == p1: | 840 if state.get(p.rev()) == p1: |
833 base = p.rev() | 841 base = p.rev() |
834 break | 842 break |
835 else: # fallback when base not found | 843 else: # fallback when base not found |
836 base = None | 844 base = None |
837 | 845 |
838 # Raise because this function is called wrong (see issue 4106) | 846 # Raise because this function is called wrong (see issue 4106) |
839 raise AssertionError('no base found to rebase on ' | 847 raise AssertionError('no base found to rebase on ' |
840 '(defineparents called wrong)') | 848 '(defineparents called wrong)') |
841 return p1, p2, base | 849 return rp1 or p1, p2, base |
842 | 850 |
843 def isagitpatch(repo, patchname): | 851 def isagitpatch(repo, patchname): |
844 'Return true if the given patch is in git format' | 852 'Return true if the given patch is in git format' |
845 mqpatch = os.path.join(repo.mq.path, patchname) | 853 mqpatch = os.path.join(repo.mq.path, patchname) |
846 for line in patch.linereader(file(mqpatch, 'rb')): | 854 for line in patch.linereader(file(mqpatch, 'rb')): |