diff --git a/hgext3rd/undo.py b/hgext3rd/undo.py --- a/hgext3rd/undo.py +++ b/hgext3rd/undo.py @@ -75,7 +75,13 @@ else: rootlog = False - result = orig(lui, repo, cmd, fullargs, *args) + unfinished = False + try: + result = orig(lui, repo, cmd, fullargs, *args) + except error.InterventionRequired as inst: + # handle commands that pause: eg histedit with merge conflict + unfinished = True + command = command + ['\0'] # mercurial is bad with caches # eg update to hidden commit will leave false cache @@ -86,6 +92,9 @@ if rootlog: safelog(repo, command) del os.environ['_undologactive'] + + if unfinished: + raise error.InterventionRequired(inst) return result # Write: Log control @@ -589,9 +598,13 @@ if branch and reverseindex != 1 and reverseindex != -1: raise error.Abort(_("--branch with --index not supported")) if relativeundo: - reverseindex = _computerelative(repo, reverseindex, - absolute = not relativeundo, - branch = branch) + try: + reverseindex = _computerelative(repo, reverseindex, + absolute = not relativeundo, + branch = branch) + except IndexError: + raise error.Abort(_("index out of bounds")) + if branch and preview: raise error.Abort(_("--branch with --preview not supported")) @@ -674,7 +687,10 @@ commandstr = _readnode(repo, 'command.i', nodedict['command']) commandlist = commandstr.split("\0") - if commandlist[0] == "undo": + if "" in commandlist: + # don't want to redo to an interupted state + reverseindex += 1 + elif commandlist[0] == "undo": undoopts = {} # remove both cases of "undo": it appears as an element of fullargs # and as the cmd. See runcommand wrapper @@ -807,6 +823,10 @@ # redonode storage # allows for branch undos using # findnextdelta logic + if reverseindex != 0: + sign = reverseindex / abs(reverseindex) + else: + sign = None if not absolute: try: # attempt to get relative shift nodebranch = repo.vfs.read("undolog/redonode").split("\0") @@ -849,6 +869,17 @@ shiftedindex = _findnextdelta(repo, shiftedindex, branch, direction=sign) reverseindex = shiftedindex + # skip interupted commands + if sign: + done = False + rlog = _getrevlog(repo, 'index.i') + while not done: + indexdict = _readindex(repo, reverseindex, rlog) + commandstr = _readnode(repo, "command.i", indexdict["command"]) + if commandstr and "\0" == commandstr[-1]: + reverseindex += sign + else: + done = True return reverseindex def _findnextdelta(repo, reverseindex, branch, direction): @@ -888,6 +919,10 @@ nodedict = _readindex(repo, incrementalindex) except IndexError: raise error.Abort(_("index out of bounds")) + # skip interupted commands + commandstr = _readnode(repo, "command.i", nodedict["command"]) + if commandstr and "\0" == commandstr[-1]: + break # check wkp, commits, bookmarks workingcopyparent = _readnode(repo, "workingparent.i", nodedict["workingparent"]) diff --git a/tests/test-undo.t b/tests/test-undo.t --- a/tests/test-undo.t +++ b/tests/test-undo.t @@ -1087,3 +1087,165 @@ o 23 a0b72b3048d6 1970-01-01 00:00 +0000 test | prev1 ~ + +Interupted commands +Commands like hg rebase, unshelve and histedit may interupt in order for the +user to solve merge conflicts etc. Since for example hg rebase --abort may +permanently delete a commit, we do not want to undo to this state. + $ touch afile + $ echo "afile" > afile + $ hg add afile && hg ci -m afile + $ hg up 0963b9e31e70 + 3 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ touch afile + $ echo "bfile" > afile + $ hg add afile && hg ci -m bfile + $ hg log -G -T compact -l6 + @ 31[tip]:29 00617a57f780 1970-01-01 00:00 +0000 test + | bfile + | + | o 30:24 28dfc398cab7 1970-01-01 00:00 +0000 test + | | afile + | | + o | 29 0963b9e31e70 1970-01-01 00:00 +0000 test + | | c3 + | | + o | 28 4e0ac6fa4ca0 1970-01-01 00:00 +0000 test + | | c2 + | | + o | 27:-1 c54b1b73bb58 1970-01-01 00:00 +0000 test + / c1 + | + o 24:-1 90af9088326b 1970-01-01 00:00 +0000 test + b1 + + $ cat >> $HGRCPATH < [extensions] + > rebase = + > EOF + $ hg rebase -r 00617 -d 28dfc + rebasing 31:00617a57f780 "bfile" (tip) + merging afile + warning: conflicts while merging afile! (edit, then use 'hg resolve --mark') + unresolved conflicts (see hg resolve, then hg rebase --continue) + [1] + $ hg log -G -T compact -l6 + @ 31[tip]:29 00617a57f780 1970-01-01 00:00 +0000 test + | bfile + | + | @ 30:24 28dfc398cab7 1970-01-01 00:00 +0000 test + | | afile + | | + o | 29 0963b9e31e70 1970-01-01 00:00 +0000 test + | | c3 + | | + o | 28 4e0ac6fa4ca0 1970-01-01 00:00 +0000 test + | | c2 + | | + o | 27:-1 c54b1b73bb58 1970-01-01 00:00 +0000 test + / c1 + | + o 24:-1 90af9088326b 1970-01-01 00:00 +0000 test + b1 + + $ hg resolve -m afile + (no more unresolved files) + continue: hg rebase --continue + $ hg rebase --continue + rebasing 31:00617a57f780 "bfile" (tip) + $ hg log -G -T compact -l6 + @ 32[tip]:30 e642892c5cb0 1970-01-01 00:00 +0000 test + | bfile + | + o 30:24 28dfc398cab7 1970-01-01 00:00 +0000 test + | afile + | + | o 29 0963b9e31e70 1970-01-01 00:00 +0000 test + | | c3 + | | + | o 28 4e0ac6fa4ca0 1970-01-01 00:00 +0000 test + | | c2 + | | + | o 27:-1 c54b1b73bb58 1970-01-01 00:00 +0000 test + | c1 + | + o 24:-1 90af9088326b 1970-01-01 00:00 +0000 test + b1 + + $ hg undo + 4 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg log -G -T compact -l6 + @ 31[tip]:29 00617a57f780 1970-01-01 00:00 +0000 test + | bfile + | + | o 30:24 28dfc398cab7 1970-01-01 00:00 +0000 test + | | afile + | | + o | 29 0963b9e31e70 1970-01-01 00:00 +0000 test + | | c3 + | | + o | 28 4e0ac6fa4ca0 1970-01-01 00:00 +0000 test + | | c2 + | | + o | 27:-1 c54b1b73bb58 1970-01-01 00:00 +0000 test + / c1 + | + o 24:-1 90af9088326b 1970-01-01 00:00 +0000 test + b1 + + $ hg redo + 2 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ hg log -G -T compact -l6 + @ 32[tip]:30 e642892c5cb0 1970-01-01 00:00 +0000 test + | bfile + | + o 30:24 28dfc398cab7 1970-01-01 00:00 +0000 test + | afile + | + | o 29 0963b9e31e70 1970-01-01 00:00 +0000 test + | | c3 + | | + | o 28 4e0ac6fa4ca0 1970-01-01 00:00 +0000 test + | | c2 + | | + | o 27:-1 c54b1b73bb58 1970-01-01 00:00 +0000 test + | c1 + | + o 24:-1 90af9088326b 1970-01-01 00:00 +0000 test + b1 + + $ hg undo + 4 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg rebase -r 00617 -d 28dfc + rebasing 31:00617a57f780 "bfile" (tip) + merging afile + warning: conflicts while merging afile! (edit, then use 'hg resolve --mark') + unresolved conflicts (see hg resolve, then hg rebase --continue) + [1] + $ hg rebase --abort + rebase aborted + $ hg undo + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg log -G -T compact -l6 + @ 31[tip]:29 00617a57f780 1970-01-01 00:00 +0000 test + | bfile + | + | o 30:24 28dfc398cab7 1970-01-01 00:00 +0000 test + | | afile + | | + o | 29 0963b9e31e70 1970-01-01 00:00 +0000 test + | | c3 + | | + o | 28 4e0ac6fa4ca0 1970-01-01 00:00 +0000 test + | | c2 + | | + o | 27:-1 c54b1b73bb58 1970-01-01 00:00 +0000 test + / c1 + | + o 24:-1 90af9088326b 1970-01-01 00:00 +0000 test + b1 + + $ cat >> $HGRCPATH < [extensions] + > rebase =! + > EOF