Patchwork [5,of,6] revset: filter first/last members by __and__ operation

login
register
mail settings
Submitter Yuya Nishihara
Date June 11, 2017, 5:36 a.m.
Message ID <24b03ed1d589fac6ebbc.1497159375@mimosa>
Download mbox | patch
Permalink /patch/21328/
State Accepted
Headers show

Comments

Yuya Nishihara - June 11, 2017, 5:36 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1497091302 -32400
#      Sat Jun 10 19:41:42 2017 +0900
# Node ID 24b03ed1d589fac6ebbcd6eea00bf6f749a5cd72
# Parent  b2385441d13d1cefadd75188a8a90eedec2eca60
revset: filter first/last members by __and__ operation

This replaces 'if y in subset' with '& subset'. first(null) and last(wdir())
are fixed thanks to fullreposet.__and__.

This also revealed that first() and last() don't follow the order of the
input set. 'ls & subset' is valid only if the ordering requirement is 'define'
or 'any'.

No performance regression observed:

  revset #0: limit(0:9999, 100, 9000)
  0) 0.001164
  1) 0.001135
  revset #2: 9000 & limit(0:9999, 100, 9000)
  0) 0.001224
  1) 0.001181
  revset #3: last(0:9999, 100)
  0) 0.000237
  1) 0.000199

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -1179,10 +1179,9 @@  def limit(repo, subset, x):
         y = next(it, None)
         if y is None:
             break
-        elif y in subset:
-            result.append(y)
-    return baseset(result, datarepr=('<limit n=%d, offset=%d, %r, %r>',
-                                     lim, ofs, subset, os))
+        result.append(y)
+    ls = baseset(result, datarepr=('<limit n=%d, offset=%d, %r>', lim, ofs, os))
+    return ls & subset
 
 @predicate('last(set, [n])', safe=True)
 def last(repo, subset, x):
@@ -1204,10 +1203,10 @@  def last(repo, subset, x):
         y = next(it, None)
         if y is None:
             break
-        elif y in subset:
-            result.append(y)
-    return baseset(result[::-1], datarepr=('<last n=%d, %r, %r>',
-                                           lim, subset, os))
+        result.append(y)
+    ls = baseset(result, datarepr=('<last n=%d, %r>', lim, os))
+    ls.reverse()
+    return ls & subset
 
 @predicate('max(set)', safe=True)
 def maxrev(repo, subset, x):
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -1016,6 +1016,50 @@  Test first (=limit) and last
   8
   9
 
+Test order of first/last revisions
+
+  $ hg debugrevspec -s 'first(4:0, 3) & 3:'
+  * set:
+  <filteredset
+    <baseset
+      <limit n=3, offset=0,
+        <spanset- 0:4>>>,
+    <spanset+ 3:9>>
+  4
+  3
+
+  $ hg debugrevspec -s '3: & first(4:0, 3)'
+  * set:
+  <filteredset
+    <baseset
+      <limit n=3, offset=0,
+        <spanset- 0:4>>>,
+    <spanset+ 3:9>>
+  4
+  3
+BROKEN: should be '3 4'
+
+  $ hg debugrevspec -s 'last(4:0, 3) & :1'
+  * set:
+  <filteredset
+    <baseset
+      <last n=3,
+        <spanset+ 0:4>>>,
+    <spanset+ 0:1>>
+  1
+  0
+
+  $ hg debugrevspec -s ':1 & last(4:0, 3)'
+  * set:
+  <filteredset
+    <baseset
+      <last n=3,
+        <spanset+ 0:4>>>,
+    <spanset+ 0:1>>
+  1
+  0
+BROKEN: should be '0 1'
+
 Test matching
 
   $ log 'matching(6)'
@@ -1230,10 +1274,10 @@  Test null revision
   $ log 'reverse(null:)' | tail -2
   0
   -1
+  $ log 'first(null:)'
+  -1
+  $ log 'min(null:)'
 BROKEN: should be '-1'
-  $ log 'first(null:)'
-BROKEN: should be '-1'
-  $ log 'min(null:)'
   $ log 'tip:null and all()' | tail -2
   1
   0
@@ -1295,9 +1339,9 @@  For tests consistency
   9
   $ log '(all() + wdir()) & max(. + wdir())'
   2147483647
-  $ log '(all() + wdir()) & first(wdir() + .)'
+  $ log 'first(wdir() + .)'
   2147483647
-  $ log '(all() + wdir()) & last(. + wdir())'
+  $ log 'last(. + wdir())'
   2147483647
 
 Test working-directory integer revision and node id
@@ -1907,10 +1951,11 @@  ordering defined by it.
       follow)
     define)
   * set:
-  <baseset
-    <limit n=1, offset=0,
-      <spanset- 0:2>,
-      <baseset [1, 0, 2]>>>
+  <filteredset
+    <baseset
+      <limit n=1, offset=0,
+        <baseset [1, 0, 2]>>>,
+    <spanset- 0:2>>
   1
 
   $ try --optimize '2:0 & not last(0 + 2 + 1)'
@@ -1946,7 +1991,6 @@  ordering defined by it.
     <not
       <baseset
         <last n=1,
-          <fullreposet+ 0:9>,
           <baseset [1, 2, 0]>>>>>
   2
   0
@@ -3573,7 +3617,6 @@  issue2549 - correct optimizations
   <filteredset
     <baseset
       <limit n=2, offset=0,
-        <fullreposet+ 0:9>,
         <baseset [1, 2, 3]>>>,
     <not
       <baseset [2]>>>
@@ -3630,7 +3673,6 @@  issue2549 - correct optimizations
   <filteredset
     <baseset
       <last n=1,
-        <fullreposet+ 0:9>,
         <baseset [2, 1]>>>,
     <not
       <baseset [2]>>>