# HG changeset patch # User Denis Laxalde # Date 2018-02-14 13:12:05 # Node ID 39b3aab6231e8fa070eadd8e165b9960f8c46076 # Parent a228b2f55ad650eccf888df75517b72301a8ea27 revert: use an exact matcher in interactive diff selection (issue5789) When going through _performrevert() in the interactive case, we build a matcher with files to revert and pass it patch.diff() for later selection of diff hunks to revert. The files set used to build the matcher comes from dirstate and accounts for patterns explicitly passed to revert ('hg revert -i ') and, in case of nonexistent pattern, this set is empty (which is expected). Unfortunately, the matcher built from scmutil.match(ctx, []) is wrong as it leads patch.diff() to rebuild a 'changes' tuple with dirstate information, ignoring user-specified pattern. This leads to the situation described in issue5789, where one gets prompted about reverting files unrelated to specified patterns because they made a typo or so. We fix this by building an exact matcher with the correct set of file paths (built earlier). Thanks to Yuya Nishihara for suggesting the correct fix. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2903,7 +2903,6 @@ def _performrevert(repo, parents, ctx, a parent, p2 = parents node = ctx.node() excluded_files = [] - matcher_opts = {"exclude": excluded_files} def checkout(f): fc = ctx[f] @@ -2924,7 +2923,7 @@ def _performrevert(repo, parents, ctx, a if choice == 0: repo.dirstate.drop(f) else: - excluded_files.append(repo.wjoin(f)) + excluded_files.append(f) else: repo.dirstate.drop(f) for f in actions['remove'][0]: @@ -2935,7 +2934,7 @@ def _performrevert(repo, parents, ctx, a if choice == 0: doremove(f) else: - excluded_files.append(repo.wjoin(f)) + excluded_files.append(f) else: doremove(f) for f in actions['drop'][0]: @@ -2955,8 +2954,8 @@ def _performrevert(repo, parents, ctx, a newlyaddedandmodifiedfiles = set() if interactive: # Prompt the user for changes to revert - torevert = [repo.wjoin(f) for f in actions['revert'][0]] - m = scmutil.match(ctx, torevert, matcher_opts) + torevert = [f for f in actions['revert'][0] if f not in excluded_files] + m = scmutil.matchfiles(repo, torevert) diffopts = patch.difffeatureopts(repo.ui, whitespace=True) diffopts.nodates = True diffopts.git = True diff --git a/tests/test-revert-interactive.t b/tests/test-revert-interactive.t --- a/tests/test-revert-interactive.t +++ b/tests/test-revert-interactive.t @@ -428,9 +428,5 @@ When specified pattern does not exist, w b: no such file in rev b40d1912accf $ hg rev -i b b: no such file in rev b40d1912accf - diff --git a/a b/a - 1 hunks, 1 lines changed - examine changes to 'a'? [Ynesfdaq?] abort: response expected - [255] $ cd ..