# HG changeset patch # User Matt Mackall # Date 2015-05-14 21:28:28 # Node ID d1bd0fd07ee6adf4ab3be2b0a0a7c0df54d55abf # Parent 0021ad4c2309e1451f327ec544c525cb1e419584 # Parent bd98d073a34fcf9651a77a9265878db1f7c88044 merge with stable diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -839,16 +839,21 @@ def restorestatus(repo): raise raise util.Abort(_('no rebase in progress')) -def inrebase(repo, originalwd, state): - '''check whether the working dir is in an interrupted rebase''' +def needupdate(repo, state): + '''check whether we should `update --clean` away from a merge, or if + somehow the working dir got forcibly updated, e.g. by older hg''' parents = [p.rev() for p in repo.parents()] - if originalwd in parents: + + # Are we in a merge state at all? + if len(parents) < 2: + return False + + # We should be standing on the first as-of-yet unrebased commit. + firstunrebased = min([old for old, new in state.iteritems() + if new == nullrev]) + if firstunrebased in parents: return True - for newrev in state.itervalues(): - if newrev in parents: - return True - return False def abort(repo, originalwd, target, state, activebookmark=None): @@ -875,7 +880,7 @@ def abort(repo, originalwd, target, stat if cleanup: # Update away from the rebase if necessary - if inrebase(repo, originalwd, state): + if needupdate(repo, state): merge.update(repo, originalwd, False, True, False) # Strip from the first rebased revision diff --git a/tests/test-rebase-abort.t b/tests/test-rebase-abort.t --- a/tests/test-rebase-abort.t +++ b/tests/test-rebase-abort.t @@ -241,3 +241,83 @@ rebase abort should not leave working co o 0 a $ cd .. + +Make sure we don't clobber changes in the working directory when the +user has somehow managed to update to a different revision (issue4009) + + $ hg init noupdate + $ cd noupdate + $ hg book @ + $ echo original > a + $ hg add a + $ hg commit -m a + $ echo x > b + $ hg add b + $ hg commit -m b1 + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark @) + $ hg book foo + $ echo y > b + $ hg add b + $ hg commit -m b2 + created new head + + $ hg rebase -d @ -b foo --tool=internal:fail + rebasing 2:070cf4580bb5 "b2" (tip foo) + unresolved conflicts (see hg resolve, then hg rebase --continue) + [1] + + $ mv .hg/rebasestate ./ # so we're allowed to hg up like in mercurial <2.6.3 + $ hg up -C 0 # user does other stuff in the repo + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ mv rebasestate .hg/ # user upgrades to 2.7 + + $ echo new > a + $ hg up 1 # user gets an error saying to run hg rebase --abort + abort: rebase in progress + (use 'hg rebase --continue' or 'hg rebase --abort') + [255] + + $ cat a + new + $ hg rebase --abort + rebase aborted + $ cat a + new + + $ cd .. + +On the other hand, make sure we *do* clobber changes whenever we +haven't somehow managed to update the repo to a different revision +during a rebase (issue4661) + + $ hg ini yesupdate + $ cd yesupdate + $ echo "initial data" > foo.txt + $ hg add + adding foo.txt + $ hg ci -m "initial checkin" + $ echo "change 1" > foo.txt + $ hg ci -m "change 1" + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo "conflicting change 1" > foo.txt + $ hg ci -m "conflicting 1" + created new head + $ echo "conflicting change 2" > foo.txt + $ hg ci -m "conflicting 2" + + $ hg rebase -d 1 --tool 'internal:fail' + rebasing 2:e4ea5cdc9789 "conflicting 1" + unresolved conflicts (see hg resolve, then hg rebase --continue) + [1] + $ hg rebase --abort + rebase aborted + $ hg summary + parent: 3:b16646383533 tip + conflicting 2 + branch: default + commit: (clean) + update: 1 new changesets, 2 branch heads (merge)