revset: filter first/last members by __and__ operation
authorYuya Nishihara <yuya@tcha.org>
Sat, 10 Jun 2017 19:41:42 +0900
changeset 32800 3e6f9bff7e3f
parent 32799 b36ec65ea583
child 32801 348b491c0934
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
mercurial/revset.py
tests/test-revset.t
--- a/mercurial/revset.py	Sat Jun 10 18:35:11 2017 +0900
+++ b/mercurial/revset.py	Sat Jun 10 19:41:42 2017 +0900
@@ -1179,10 +1179,9 @@
         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 @@
         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):
--- a/tests/test-revset.t	Sat Jun 10 18:35:11 2017 +0900
+++ b/tests/test-revset.t	Sat Jun 10 19:41:42 2017 +0900
@@ -1016,6 +1016,50 @@
   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 @@
   $ 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 @@
   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 @@
       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 @@
     <not
       <baseset
         <last n=1,
-          <fullreposet+ 0:9>,
           <baseset [1, 2, 0]>>>>>
   2
   0
@@ -3573,7 +3617,6 @@
   <filteredset
     <baseset
       <limit n=2, offset=0,
-        <fullreposet+ 0:9>,
         <baseset [1, 2, 3]>>>,
     <not
       <baseset [2]>>>
@@ -3630,7 +3673,6 @@
   <filteredset
     <baseset
       <last n=1,
-        <fullreposet+ 0:9>,
         <baseset [2, 1]>>>,
     <not
       <baseset [2]>>>