Patchwork [1,of,1,STABLE] revset: evaluate sub expressions correctly (issue3775)

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Jan. 22, 2013, 3:26 p.m.
Message ID <379f6afd30a38198efad.1358868403@juju>
Download mbox | patch
Permalink /patch/711/
State Superseded
Headers show

Comments

Katsunori FUJIWARA - Jan. 22, 2013, 3:26 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1358868263 -32400
# Branch stable
# Node ID 379f6afd30a38198efad09becaf70f395fd5f108
# Parent  8a811fa9a9c0785b843e032ed82ce5316a645631
revset: evaluate sub expressions correctly (issue3775)

Before this patch, sub expression may return unexpected result, if it
is joined with another expression by "or":

  - "^"/parentspec():
    "R or R^1" is not equal to "R^1 or R". the former returns only "R".

  - "~"/ancestorspec():
    "R or R~1" is not equal to "R~1 or R". the former returns only "R".

  - ":"/rangeset():
    "10 or (10 or 15):" is not equal to "(10 or 15): or 10". the
    former returns only 10 and 15 or grater (11 to 14 are not
    included).

In "or"-ed expression "A or B", the "subset" passed to evaluation of
"B" doesn't contain revisions gotten from evaluation of "A", for
efficiency.

In the other hand, "stringset()" fails to look corresponding revision
for specified string/symbol up, if "subset" doesn't contain that
revision.

So, predicates looking revisions up indirectly should evaluate sub
expressions of themselves not with passed "subset" but with "entire
revisions in the repository", to prevent "stringset()" from unexpected
failing to look symbols in them up.

But predicates in above example don't so. For example, in the case of
"R or R^1":

  1. "R^1" is evaluated with "subset" containing revisions other than
     "R", because "R" is already gotten by the former of "or"-ed
     expressions

  2. "parentspec()" evaluates "R" of "R^1" with such "subset"

  3. "stringset()" fails to look "R" up, because "R" is not contained
     in "subset"

  4. so, evaluation of "R^1" returns no revision

This patch evaluates sub expressions for predicates above with "entire
revisions in the repository".
Katsunori FUJIWARA - Jan. 23, 2013, 5:13 a.m.
At Wed, 23 Jan 2013 00:26:43 +0900,
FUJIWARA Katsunori wrote:
> 
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1358868263 -32400
> # Branch stable
> # Node ID 379f6afd30a38198efad09becaf70f395fd5f108
> # Parent  8a811fa9a9c0785b843e032ed82ce5316a645631
> revset: evaluate sub expressions correctly (issue3775)

> +  $ log '(6 or 8): or 6' | sort
> +  6
> +  7
> +  8
> +  9
> +  $ log '6 or (6 or 8):' | sort
> +  6
> +  7
> +  8
> +  9
> +

Oops, this test is not enough, because looking up at "end" side of
range is not tested.

Please forget this patch. I'll send revised version, soon.

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy@lares.dti.ne.jp

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -223,13 +223,9 @@ 
     return stringset(repo, subset, x)
 
 def rangeset(repo, subset, x, y):
-    m = getset(repo, subset, x)
-    if not m:
-        m = getset(repo, list(repo), x)
-
-    n = getset(repo, subset, y)
-    if not n:
-        n = getset(repo, list(repo), y)
+    cl = repo.changelog
+    m = getset(repo, cl, x)
+    n = getset(repo, cl, y)
 
     if not m or not n:
         return []
@@ -326,7 +322,7 @@ 
         raise error.ParseError(_("~ expects a number"))
     ps = set()
     cl = repo.changelog
-    for r in getset(repo, subset, x):
+    for r in getset(repo, cl, x):
         for i in range(n):
             r = cl.parentrevs(r)[0]
         ps.add(r)
@@ -1139,7 +1135,7 @@ 
         raise error.ParseError(_("^ expects a number 0, 1, or 2"))
     ps = set()
     cl = repo.changelog
-    for r in getset(repo, subset, x):
+    for r in getset(repo, cl, x):
         if n == 0:
             ps.add(r)
         elif n == 1:
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -758,6 +758,31 @@ 
   $ hg log -r "${ISSUE3669_TIP}^" --template '{rev}\n'
   8
 
+test or-ed indirect predicates (issue3775)
+
+  $ log '6 or 6^1' | sort
+  5
+  6
+  $ log '6^1 or 6' | sort
+  5
+  6
+  $ log '4 or 4~1' | sort
+  2
+  4
+  $ log '4~1 or 4' | sort
+  2
+  4
+  $ log '(6 or 8): or 6' | sort
+  6
+  7
+  8
+  9
+  $ log '6 or (6 or 8):' | sort
+  6
+  7
+  8
+  9
+
 tests for 'remote()' predicate:
 #.  (csets in remote) (id)            (remote)
 1.  less than local   current branch  "default"