addset: split simple and ordered iteration
We have two goals here. First, we would like to restore the former iteration
order we had in 2.9. Second, we want this logic to be reusable for `fastasc`
and `fastdesc` methods.
--- a/mercurial/revset.py Fri Oct 03 01:55:09 2014 -0500
+++ b/mercurial/revset.py Thu Oct 02 23:28:18 2014 -0500
@@ -2638,52 +2638,20 @@
same time, yielding only one value at a time in the given order.
"""
if not self._iter:
- def gen():
- if self._ascending is None:
+ if self._ascending is None:
+ def gen():
for r in self._r1:
yield r
s = self._r1.set()
for r in self._r2:
if r not in s:
yield r
- else:
- iter1 = iter(self._r1)
- iter2 = iter(self._r2)
-
- val1 = None
- val2 = None
-
- choice = max
- if self._ascending:
- choice = min
- try:
- # Consume both iterators in an ordered way until one is
- # empty
- while True:
- if val1 is None:
- val1 = iter1.next()
- if val2 is None:
- val2 = iter2.next()
- next = choice(val1, val2)
- yield next
- if val1 == next:
- val1 = None
- if val2 == next:
- val2 = None
- except StopIteration:
- # Flush any remaining values and consume the other one
- it = iter2
- if val1 is not None:
- yield val1
- it = iter1
- elif val2 is not None:
- # might have been equality and both are empty
- yield val2
- for val in it:
- yield val
-
- self._iter = _generatorset(gen())
-
+ gen = gen()
+ else:
+ iter1 = iter(self._r1)
+ iter2 = iter(self._r2)
+ gen = self._iterordered(self._ascending, iter1, iter2)
+ self._iter = _generatorset(gen)
return self._iter
def __iter__(self):
@@ -2691,6 +2659,47 @@
return iter(self._genlist)
return iter(self._iterator())
+ def _iterordered(self, ascending, iter1, iter2):
+ """produce an ordered iteration from two iterators with the same order
+
+ The ascending is used to indicated the iteration direction.
+ """
+ choice = max
+ if ascending:
+ choice = min
+
+ val1 = None
+ val2 = None
+
+ choice = max
+ if self._ascending:
+ choice = min
+ try:
+ # Consume both iterators in an ordered way until one is
+ # empty
+ while True:
+ if val1 is None:
+ val1 = iter1.next()
+ if val2 is None:
+ val2 = iter2.next()
+ next = choice(val1, val2)
+ yield next
+ if val1 == next:
+ val1 = None
+ if val2 == next:
+ val2 = None
+ except StopIteration:
+ # Flush any remaining values and consume the other one
+ it = iter2
+ if val1 is not None:
+ yield val1
+ it = iter1
+ elif val2 is not None:
+ # might have been equality and both are empty
+ yield val2
+ for val in it:
+ yield val
+
def __contains__(self, x):
return x in self._r1 or x in self._r2