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.
--- 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