addset: split simple and ordered iteration
authorPierre-Yves David <pierre-yves.david@fb.com>
Thu, 02 Oct 2014 23:28:18 -0500
changeset 22741 ef2c1ea8fb2c
parent 22740 f40a57e8fda1
child 22742 6bbc26adcc6a
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.
mercurial/revset.py
--- 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