lazyancestors: extract __iter__ to free function
authorMartin von Zweigbergk <martinvonz@google.com>
Sun, 09 Sep 2018 23:16:55 -0700
changeset 39498 b6a0e06b0f7d
parent 39497 89630d0b3e23
child 39499 77a2f6d805f2
lazyancestors: extract __iter__ to free function The next patch will keep a reference to the returned iterator in a field, which would otherwise result in a reference cycle. Differential Revision: https://phab.mercurial-scm.org/D4517
mercurial/ancestor.py
--- a/mercurial/ancestor.py	Thu Aug 30 01:53:21 2018 +0200
+++ b/mercurial/ancestor.py	Sun Sep 09 23:16:55 2018 -0700
@@ -259,6 +259,37 @@
         missing.reverse()
         return missing
 
+# Extracted from lazyancestors.__iter__ to avoid a reference cycle
+def _lazyancestorsiter(parentrevs, initrevs, stoprev, inclusive):
+    seen = {nullrev}
+    revs = initrevs
+
+    schedule = heapq.heappush
+    nextitem = heapq.heappop
+    see = seen.add
+
+    if inclusive:
+        visit = [-r for r in revs]
+        seen.update(revs)
+        heapq.heapify(visit)
+    else:
+        visit = []
+        heapq.heapify(visit)
+        for r in revs:
+            for parent in parentrevs(r):
+                if parent not in seen:
+                    schedule(visit, -parent)
+                    see(parent)
+
+    while visit:
+        current = -nextitem(visit)
+        if current >= stoprev:
+            yield current
+            for parent in parentrevs(current):
+                if parent not in seen:
+                    schedule(visit, -parent)
+                    see(parent)
+
 class lazyancestors(object):
     def __init__(self, pfunc, revs, stoprev=0, inclusive=False):
         """Create a new object generating ancestors for the given revs. Does
@@ -311,36 +342,9 @@
 
         If inclusive is True, the source revisions are also yielded. The
         reverse revision number order is still enforced."""
-        seen = {nullrev}
-        revs = self._initrevs
-
-        parentrevs = self._parentrevs
-        stoprev = self._stoprev
-        schedule = heapq.heappush
-        nextitem = heapq.heappop
-        see = seen.add
-
-        if self._inclusive:
-            visit = [-r for r in revs]
-            seen.update(revs)
-            heapq.heapify(visit)
-        else:
-            visit = []
-            heapq.heapify(visit)
-            for r in revs:
-                for parent in parentrevs(r):
-                    if parent not in seen:
-                        schedule(visit, -parent)
-                        see(parent)
-
-        while visit:
-            current = -nextitem(visit)
-            if current >= stoprev:
-                yield current
-                for parent in parentrevs(current):
-                    if parent not in seen:
-                        schedule(visit, -parent)
-                        see(parent)
+        for rev in _lazyancestorsiter(self._parentrevs, self._initrevs,
+                                      self._stoprev, self._inclusive):
+            yield rev
 
     def __contains__(self, target):
         """Test whether target is an ancestor of self._initrevs."""