# HG changeset patch # User Laurent Charignon # Date 1426548839 25200 # Node ID 521fe8287dd54bd9f1a6ea6f3cbec53c22931d2e # Parent 8d9e9063b0409ab387ac63832772007ab5fa61ad revert: add flag to make revert interactive diff -r 8d9e9063b040 -r 521fe8287dd5 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Mon Mar 16 15:37:00 2015 -0700 +++ b/mercurial/cmdutil.py Mon Mar 16 16:33:59 2015 -0700 @@ -3018,8 +3018,8 @@ if not opts.get('dry_run'): needdata = ('revert', 'add', 'undelete') _revertprefetch(repo, ctx, *[actions[name][0] for name in needdata]) - - _performrevert(repo, parents, ctx, actions) + interactive = opts.get('interactive', False) + _performrevert(repo, parents, ctx, actions, interactive) # get the list of subrepos that must be reverted subrepomatch = scmutil.match(ctx, pats, opts) @@ -3036,7 +3036,7 @@ """Let extension changing the storage layer prefetch content""" pass -def _performrevert(repo, parents, ctx, actions): +def _performrevert(repo, parents, ctx, actions, interactive=False): """function that actually perform all the actions computed for revert This is an independent function to let extension to plug in and react to @@ -3070,10 +3070,40 @@ normal = repo.dirstate.normallookup else: normal = repo.dirstate.normal - for f in actions['revert'][0]: - checkout(f) - if normal: - normal(f) + + if interactive: + # Prompt the user for changes to revert + torevert = [repo.wjoin(f) for f in actions['revert'][0]] + m = scmutil.match(ctx, torevert, {}) + diff = patch.diff(repo, None, ctx.node(), m) + originalchunks = patch.parsepatch(diff) + try: + chunks = recordfilter(repo.ui, originalchunks) + except patch.PatchError, err: + raise util.Abort(_('error parsing patch: %s') % err) + + # Apply changes + fp = cStringIO.StringIO() + for c in chunks: + c.write(fp) + dopatch = fp.tell() + fp.seek(0) + if dopatch: + try: + patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None) + except patch.PatchError, err: + raise util.Abort(str(err)) + del fp + + for f in actions['revert'][0]: + if normal: + normal(f) + + else: + for f in actions['revert'][0]: + checkout(f) + if normal: + normal(f) for f in actions['add'][0]: checkout(f) diff -r 8d9e9063b040 -r 521fe8287dd5 mercurial/commands.py --- a/mercurial/commands.py Mon Mar 16 15:37:00 2015 -0700 +++ b/mercurial/commands.py Mon Mar 16 16:33:59 2015 -0700 @@ -5375,6 +5375,7 @@ ('d', 'date', '', _('tipmost revision matching date'), _('DATE')), ('r', 'rev', '', _('revert to the specified revision'), _('REV')), ('C', 'no-backup', None, _('do not save backup copies of files')), + ('i', 'interactive', None, _('interactively select the changes')), ] + walkopts + dryrunopts, _('[OPTION]... [-r REV] [NAME]...')) def revert(ui, repo, *pats, **opts): diff -r 8d9e9063b040 -r 521fe8287dd5 tests/test-completion.t --- a/tests/test-completion.t Mon Mar 16 15:37:00 2015 -0700 +++ b/tests/test-completion.t Mon Mar 16 16:33:59 2015 -0700 @@ -279,7 +279,7 @@ recover: rename: after, force, include, exclude, dry-run resolve: all, list, mark, unmark, no-status, tool, include, exclude, template - revert: all, date, rev, no-backup, include, exclude, dry-run + revert: all, date, rev, no-backup, interactive, include, exclude, dry-run rollback: dry-run, force root: tag: force, local, rev, remove, edit, message, date, user diff -r 8d9e9063b040 -r 521fe8287dd5 tests/test-revert-interactive.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-revert-interactive.t Mon Mar 16 16:33:59 2015 -0700 @@ -0,0 +1,203 @@ +Revert interactive tests +1 add and commit file f +2 add commit file folder1/g +3 add and commit file folder2/h +4 add and commit file folder1/i +5 commit change to file f +6 commit changes to files folder1/g folder2/h +7 commit changes to files folder1/g folder2/h +8 revert interactive to commit id 2 (line 3 above), check that folder1/i is removed and +9 make workdir match 7 +10 run the same test than 8 from within folder1 and check same expectations + + $ cat <> $HGRCPATH + > [ui] + > interactive = true + > [extensions] + > record = + > EOF + + + $ mkdir -p a/{folder1,folder2} + $ cd a + $ hg init + $ seq 1 5 > f ; hg add f ; hg commit -m "adding f" + $ seq 1 5 > folder1/g ; hg add folder1/g ; hg commit -m "adding folder1/g" + $ seq 1 5 > folder2/h ; hg add folder2/h ; hg commit -m "adding folder2/h" + $ seq 1 5 > folder1/i ; hg add folder1/i ; hg commit -m "adding folder1/i" + $ echo "a" > f ; seq 1 5 >> f ; echo "b" >> f ; hg commit -m "modifying f" + $ echo "c" > folder1/g ; seq 1 5 >> folder1/g ; echo "d" >> folder1/g ; hg commit -m "modifying folder1/g" + $ echo "e" > folder2/h ; seq 1 5 >> folder2/h ; echo "f" >> folder2/h ; hg commit -m "modifying folder2/h" + $ hg tip + changeset: 6:59dd6e4ab63a + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: modifying folder2/h + + $ hg revert -i -r 2 --all -- << EOF + > y + > y + > y + > y + > y + > n + > n + > EOF + reverting f + reverting folder1/g (glob) + removing folder1/i (glob) + reverting folder2/h (glob) + diff -r 89ac3d72e4a4 f + 2 hunks, 2 lines changed + examine changes to 'f'? [Ynesfdaq?] y + + @@ -1,6 +1,5 @@ + -a + 1 + 2 + 3 + 4 + 5 + record change 1/6 to 'f'? [Ynesfdaq?] y + + @@ -2,6 +1,5 @@ + 1 + 2 + 3 + 4 + 5 + -b + record change 2/6 to 'f'? [Ynesfdaq?] y + + diff -r 89ac3d72e4a4 folder1/g + 2 hunks, 2 lines changed + examine changes to 'folder1/g'? [Ynesfdaq?] y + + @@ -1,6 +1,5 @@ + -c + 1 + 2 + 3 + 4 + 5 + record change 3/6 to 'folder1/g'? [Ynesfdaq?] y + + @@ -2,6 +1,5 @@ + 1 + 2 + 3 + 4 + 5 + -d + record change 4/6 to 'folder1/g'? [Ynesfdaq?] n + + diff -r 89ac3d72e4a4 folder2/h + 2 hunks, 2 lines changed + examine changes to 'folder2/h'? [Ynesfdaq?] n + + $ cat f + 1 + 2 + 3 + 4 + 5 + $ cat folder1/g + 1 + 2 + 3 + 4 + 5 + d + $ cat folder2/h + e + 1 + 2 + 3 + 4 + 5 + f + $ hg update -C 6 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg revert -i -r 2 --all -- << EOF + > y + > y + > y + > y + > y + > n + > n + > EOF + reverting f + reverting folder1/g (glob) + removing folder1/i (glob) + reverting folder2/h (glob) + diff -r 89ac3d72e4a4 f + 2 hunks, 2 lines changed + examine changes to 'f'? [Ynesfdaq?] y + + @@ -1,6 +1,5 @@ + -a + 1 + 2 + 3 + 4 + 5 + record change 1/6 to 'f'? [Ynesfdaq?] y + + @@ -2,6 +1,5 @@ + 1 + 2 + 3 + 4 + 5 + -b + record change 2/6 to 'f'? [Ynesfdaq?] y + + diff -r 89ac3d72e4a4 folder1/g + 2 hunks, 2 lines changed + examine changes to 'folder1/g'? [Ynesfdaq?] y + + @@ -1,6 +1,5 @@ + -c + 1 + 2 + 3 + 4 + 5 + record change 3/6 to 'folder1/g'? [Ynesfdaq?] y + + @@ -2,6 +1,5 @@ + 1 + 2 + 3 + 4 + 5 + -d + record change 4/6 to 'folder1/g'? [Ynesfdaq?] n + + diff -r 89ac3d72e4a4 folder2/h + 2 hunks, 2 lines changed + examine changes to 'folder2/h'? [Ynesfdaq?] n + + $ cat f + 1 + 2 + 3 + 4 + 5 + $ cat folder1/g + 1 + 2 + 3 + 4 + 5 + d + $ cat folder2/h + e + 1 + 2 + 3 + 4 + 5 + f