diff --git a/hgext3rd/undo.py b/hgext3rd/undo.py --- a/hgext3rd/undo.py +++ b/hgext3rd/undo.py @@ -75,17 +75,19 @@ else: rootlog = False - result = orig(lui, repo, cmd, fullargs, *args) + try: + result = orig(lui, repo, cmd, fullargs, *args) + finally: + if repo is not None: + # mercurial is bad with caches + # eg update to hidden commit will leave false cache + repo.invalidatevolatilesets() - # mercurial is bad with caches - # eg update to hidden commit will leave false cache - if repo: - repo.invalidatevolatilesets() + # record changes to repo + if rootlog: + safelog(repo, command) + del os.environ['_undologactive'] - # record changes to repo - if rootlog: - safelog(repo, command) - del os.environ['_undologactive'] return result # Write: Log control @@ -173,11 +175,21 @@ newnodes.update({ 'date': _logdate(repo, tr), 'command': _logcommand(repo, tr, command), + 'unfinished': unfinished(repo), }) _logindex(repo, tr, newnodes) # changes have been recorded return True +def unfinished(repo, commit=False): + '''like cmdutil.checkunfinished without raising an Abort''' + for f, clearable, allowcommit, msg, hint in cmdutil.unfinishedstates: + if commit and allowcommit: + continue + if repo.vfs.exists(f): + return True + return False + # Write: Logs def writelog(repo, tr, name, revstring): @@ -372,6 +384,7 @@ content = rawcontent fm.startitem() fm.write('content', '%s', header + content) + fm.write('content', '%s', "unfinished:\t" + nodedict['unfinished']) fm.end() # Revset logic @@ -606,9 +619,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")) @@ -691,7 +708,10 @@ commandstr = _readnode(repo, 'command.i', nodedict['command']) commandlist = commandstr.split("\0") - if commandlist[0] == "undo": + if 'True' == nodedict['unfinished']: + # don't want to redo to an interupted state + reverseindex += 1 + elif commandlist[0] == "undo": undoopts = {} fancyopts.fancyopts(commandlist, cmdtable['undo'][1] + commands.globalopts, @@ -820,6 +840,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") @@ -862,6 +886,16 @@ 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) + if 'True' == indexdict['unfinished']: + reverseindex += sign + else: + done = True return reverseindex def _findnextdelta(repo, reverseindex, branch, direction): @@ -901,6 +935,9 @@ nodedict = _readindex(repo, incrementalindex) except IndexError: raise error.Abort(_("index out of bounds")) + # skip interupted commands + if 'True' == nodedict['unfinished']: + 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 @@ -66,6 +66,7 @@ command bae41a9d0ae9614fc3aa843a0f5cbdf47bc98c43 date * (glob) draftheads b80de5d138758541c5f05265ad144ab9fa86d1db + unfinished False workingparent fcb754f6a51eaf982f66d0637b39f3d2e6b520d5 (no-eol) $ touch a3 && hg add a3 $ hg commit --amend @@ -105,8 +106,7 @@ 0a3dd3e15e65b90836f492112d816f3ee073d897 REMOVED: - workingparent: - 0a3dd3e15e65b90836f492112d816f3ee073d897 + unfinished: False Test gap in data (extension dis and enabled) $ hg debugundohistory -l @@ -145,8 +145,7 @@ 1dafc0b436123cab96f82a8e9e8d1d42c0301aaa REMOVED: 0a3dd3e15e65b90836f492112d816f3ee073d897 - workingparent: - 1dafc0b436123cab96f82a8e9e8d1d42c0301aaa + unfinished: False Index out of bound error $ hg debugundohistory -n 50 @@ -169,8 +168,7 @@ aa430c8afedf9b2ec3f0655d39eef6b6b0a2ddb6 REMOVED: 1dafc0b436123cab96f82a8e9e8d1d42c0301aaa - workingparent: - aa430c8afedf9b2ec3f0655d39eef6b6b0a2ddb6 + unfinished: False Test 'olddraft([NUM])' revset $ hg log -G -r 'olddraft(0) - olddraft(1)' --hidden -T compact @@ -1087,3 +1085,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