Patchwork [2,of,2,RFC] revpair: restrict odd-range handling to top-level x:y expression (issue4774)

login
register
mail settings
Submitter Yuya Nishihara
Date Aug. 13, 2015, 10:54 a.m.
Message ID <bdbece99ea9d7e3a7994.1439463281@mimosa>
Download mbox | patch
Permalink /patch/10206/
State Accepted
Headers show

Comments

Yuya Nishihara - Aug. 13, 2015, 10:54 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1439450143 -32400
#      Thu Aug 13 16:15:43 2015 +0900
# Node ID bdbece99ea9d7e3a7994a2387cfb9ba6d9a85331
# Parent  e7091f706d6590cfc07a8c75b3a75124a3906279
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]".
Matt Mackall - Aug. 13, 2015, 10:18 p.m.
On Thu, 2015-08-13 at 19:54 +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1439450143 -32400
> #      Thu Aug 13 16:15:43 2015 +0900
> # Node ID bdbece99ea9d7e3a7994a2387cfb9ba6d9a85331
> # Parent  e7091f706d6590cfc07a8c75b3a75124a3906279
> revpair: restrict odd-range handling to top-level x:y expression (issue4774)

These are queued for default, thanks.

Patch

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