# HG changeset patch # User Yuya Nishihara # Date 2015-08-13 07:15:43 # Node ID cc3a30ff9490cbc9f9ab59ccd1093c2279701c76 # Parent 85f5352c7ca7aaf141e320fc7b7a2f0ae5755f2d revpair: restrict odd-range handling to top-level x:y expression (issue4774) The odd-range hack was introduced by 2a0efa1112ac for backward compatibility, but it was too widely applied. I've checked cmdutil.revpair() at 1.6, and found that ".:", ":0" and ":" are also handled as pairs. So let's enable the hack only for "x:y", "x:", "y:" and ":". test-revset.t is updated because "tip^::tip^ or tip^" shouldn't be taken as an odd range. This patch adds "tip^:tip^" instead. This patch is written for the default branch because parse() of the stable branch lacks compatibility hack for "foo+bar" tag. If we want to mitigate the issue in stable, we can add something like "and '::' in revs[0]". diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -690,6 +690,11 @@ def revsingle(repo, revspec, default='.' raise util.Abort(_('empty revision set')) return repo[l.last()] +def _pairspec(revspec): + tree = revset.parse(revspec) + tree = revset.optimize(tree, True)[1] # fix up "x^:y" -> "(x^):y" + return tree and tree[0] in ('range', 'rangepre', 'rangepost', 'rangeall') + def revpair(repo, revs): if not revs: return repo.dirstate.p1(), None @@ -711,13 +716,12 @@ def revpair(repo, revs): if first is None: raise util.Abort(_('empty revision range')) - if first == second and len(revs) == 1 and _revrangesep not in revs[0]: + # if top-level is range expression, the result must always be a pair + if first == second and len(revs) == 1 and not _pairspec(revs[0]): return repo.lookup(first), None return repo.lookup(first), repo.lookup(second) -_revrangesep = ':' - def revrange(repo, revs): """Yield revision as strings from a list of revision specifications.""" allspecs = [] diff --git a/tests/test-diff-change.t b/tests/test-diff-change.t --- a/tests/test-diff-change.t +++ b/tests/test-diff-change.t @@ -31,19 +31,53 @@ Testing diff --change $ cd .. -Test dumb revspecs (issue3474) +Test dumb revspecs: top-level "x:y", "x:", ":y" and ":" ranges should be handled +as pairs even if x == y, but not for "f(x:y)" nor "x::y" (issue3474, issue4774) $ hg clone -q a dumbspec $ cd dumbspec $ echo "wdir" > file.txt $ hg diff -r 2:2 + $ hg diff -r 2:. + $ hg diff -r 2: + $ hg diff -r :0 + $ hg diff -r '2:first(2:2)' + $ hg diff -r 'first(2:2)' --nodates + diff -r bf5ff72eb7e0 file.txt + --- a/file.txt + +++ b/file.txt + @@ -1,1 +1,1 @@ + -third + +wdir + $ hg diff -r 2::2 --nodates + diff -r bf5ff72eb7e0 file.txt + --- a/file.txt + +++ b/file.txt + @@ -1,1 +1,1 @@ + -third + +wdir $ hg diff -r "2 and 1" abort: empty revision range [255] $ cd .. + $ hg clone -qr0 a dumbspec-rev0 + $ cd dumbspec-rev0 + $ echo "wdir" > file.txt + + $ hg diff -r : + $ hg diff -r 'first(:)' --nodates + diff -r 4bb65dda5db4 file.txt + --- a/file.txt + +++ b/file.txt + @@ -1,1 +1,1 @@ + -first + +wdir + + $ cd .. + Testing diff --change when merge: $ cd a diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -1515,10 +1515,16 @@ test usage in revpair (with "+") (single rev) $ hg diff -r 'tip^' -r 'tip^' - $ hg diff -r 'tip^::tip^ or tip^' + $ hg diff -r 'tip^:tip^' (single rev that does not looks like a range) + $ hg diff -r 'tip^::tip^ or tip^' + diff -r d5d0dcbdc4d9 .hgtags + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/.hgtags * (glob) + @@ -0,0 +1,1 @@ + +e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0 $ hg diff -r 'tip^ or tip^' diff -r d5d0dcbdc4d9 .hgtags --- /dev/null Thu Jan 01 00:00:00 1970 +0000