revset: added cached generated list on generatorset
authorLucas Moscovicz <lmoscovicz@fb.com>
Wed, 12 Feb 2014 18:45:49 -0800
changeset 20540 fa16c710a3d8
parent 20539 aa021ece4506
child 20541 44dcca9be1d5
revset: added cached generated list on generatorset This allows to iterate the generatorset more than once.
mercurial/revset.py
--- a/mercurial/revset.py	Thu Feb 20 00:46:13 2014 -0600
+++ b/mercurial/revset.py	Wed Feb 12 18:45:49 2014 -0800
@@ -2177,20 +2177,32 @@
         return set([r for r in self])
 
 class generatorset(object):
-    """Wrapper structure for generators that provides lazy membership."""
+    """Wrapper structure for generators that provides lazy membership and can
+    be iterated more than once.
+    When asked for membership it generates values until either it finds the
+    requested one or has gone through all the elements in the generator
+    """
     def __init__(self, gen):
         self._gen = gen
         self._iter = iter(gen)
         self._cache = {}
+        self._genlist = baseset([])
+        self._iterated = False
+
+    def _nextitem(self):
+        l = self._iter.next()
+        self._cache[l] = True
+        self._genlist.append(l)
+        return l
 
     def __contains__(self, x):
         if x in self._cache:
             return self._cache[x]
 
+        self._iterated = True
         while True:
             try:
-                l = self._iter.next()
-                self._cache[l] = True
+                l = self._nextitem()
                 if l == x:
                     return True
             except (StopIteration):
@@ -2200,9 +2212,21 @@
         return False
 
     def __iter__(self):
-        for item in self._gen:
-            self._cache[item] = True
-            yield item
+        if self._iterated:
+            for l in self._genlist:
+                yield l
+            while True:
+                try:
+                    item = self._nextitem()
+                    yield item
+                except (StopIteration):
+                    break
+        else:
+            self._iterated = True
+            for item in self._gen:
+                self._cache[item] = True
+                self._genlist.append(item)
+                yield item
 
     def set(self):
         return self