spanset: enforce the order lazily to gain `fastasc` and `fastdesc` methods
authorPierre-Yves David <pierre-yves.david@fb.com>
Thu, 02 Oct 2014 18:02:17 -0500
changeset 22717 b89f7e3a414d
parent 22716 6877ba8d85ff
child 22718 7b123e5639f4
spanset: enforce the order lazily to gain `fastasc` and `fastdesc` methods Instead of having the direction of iteration enforced through the ordering of `start` and `end` attributes of spanset, we encode the iteration direction in an explicit attribute and always store start < end. The logic for sort and reverse has to be updated. The __iter__ is now based on the newly introduced `fastasc` and `fastdesc` methods. This will allow other code simplifications in the future.
mercurial/revset.py
--- a/mercurial/revset.py	Tue Sep 30 22:26:34 2014 -0500
+++ b/mercurial/revset.py	Thu Oct 02 18:02:17 2014 -0500
@@ -2855,27 +2855,44 @@
 
         Spanset will be descending if `end` < `start`.
         """
+        if end is None:
+            end = len(repo)
+        self._ascending = start <= end
+        if not self._ascending:
+            start, end = end + 1, start +1
         self._start = start
-        if end is not None:
-            self._end = end
-        else:
-            self._end = len(repo)
+        self._end = end
         self._hiddenrevs = repo.changelog.filteredrevs
 
+    def sort(self, reverse=False):
+        self._ascending = not reverse
+
+    def reverse(self):
+        self._ascending = not self._ascending
+
+    def _iterfilter(self, iterrange):
+        s = self._hiddenrevs
+        for r in iterrange:
+            if r not in s:
+                yield r
+
     def __iter__(self):
-        if self.isascending():
-            iterrange = xrange(self._start, self._end)
+        if self._ascending:
+            return self.fastasc()
         else:
-            iterrange = xrange(self._start, self._end, -1)
-
+            return self.fastdesc()
+
+    def fastasc(self):
+        iterrange = xrange(self._start, self._end)
         if self._hiddenrevs:
-            s = self._hiddenrevs
-            for r in iterrange:
-                if r not in s:
-                    yield r
-        else:
-            for r in iterrange:
-                yield r
+            return self._iterfilter(iterrange)
+        return iter(iterrange)
+
+    def fastdesc(self):
+        iterrange = xrange(self._end - 1, self._start - 1, -1)
+        if self._hiddenrevs:
+            return self._iterfilter(iterrange)
+        return iter(iterrange)
 
     def __contains__(self, rev):
         start = self._start
@@ -2923,17 +2940,6 @@
         l = baseset([r for r in self])
         return l[x]
 
-    def sort(self, reverse=False):
-        if bool(reverse) != (self._start > self._end):
-            self.reverse()
-
-    def reverse(self):
-        # Just switch the _start and _end parameters
-        if self.isascending():
-            self._start, self._end = self._end - 1, self._start - 1
-        else:
-            self._start, self._end = self._end + 1, self._start + 1
-
     def set(self):
         return self