repoview: simplify process in _getstatichidden
authorPierre-Yves David <pierre-yves.david@fb.com>
Fri, 03 Apr 2015 14:35:53 -0700
changeset 24617 f76595f6ed7c
parent 24616 72d34c5a6614
child 24618 cde57a8d8fe7
repoview: simplify process in _getstatichidden Since all children are processed before their parents, we can apply the following algorithm: For each rev (descending order): * If I'm still hidden, no children will block me, * If I'm not hidden, I must remove my parent from the hidden set, This allows us to dynamically change the set of 'hidden' revisions, dropping the need for the 'actuallyhidden' dictionary and the 'blocked' boolean in the queue. As before, we start iterating from all heads and stop at the first public changesets. This ensures the hidden computation is 'O(not public())' instead of 'O(len(min(not public()):))'.
mercurial/repoview.py
--- a/mercurial/repoview.py	Fri Apr 03 14:16:50 2015 -0700
+++ b/mercurial/repoview.py	Fri Apr 03 14:35:53 2015 -0700
@@ -34,35 +34,30 @@
 
     """
     assert not repo.changelog.filteredrevs
-    hideable = hideablerevs(repo)
-    if hideable:
-        actuallyhidden = {}
+    hidden = set(hideablerevs(repo))
+    if hidden:
         getphase = repo._phasecache.phase
         getparentrevs = repo.changelog.parentrevs
-        heap = [(-r, False) for r in repo.changelog.headrevs()]
+        heap = [-r for r in repo.changelog.headrevs()]
         heapq.heapify(heap)
         heappop = heapq.heappop
         heappush = heapq.heappush
         while heap:
-            rev, blocked = heappop(heap)
-            rev = - rev
-            phase = getphase(repo, rev)
-            # Skip nodes which are public (guaranteed to not be hidden) and
-            # nodes which have already been processed and won't be blocked by
-            # the previous node.
-            if phase == 0 or (not blocked and rev in actuallyhidden):
+            rev = -heappop(heap)
+            # Skip nodes which are public (guaranteed to not be hidden)
+            if not getphase(repo, rev):
                 continue
-            if rev in hideable:
-                if blocked:
-                    actuallyhidden[rev] = False
-                else:
-                    actuallyhidden.setdefault(rev, True)
-            else:
-                blocked = True
-
-            for parent in (p for p in getparentrevs(rev) if p != nullrev):
-                heappush(heap, (- parent, blocked))
-    return set(rev for rev, hidden in actuallyhidden.iteritems() if hidden)
+            # All children have been processed so at that point, if no children
+            # removed 'rev' from the 'hidden' set, 'rev' is going to be hidden.
+            blocker = rev not in hidden
+            for parent in getparentrevs(rev):
+                if parent == nullrev:
+                    continue
+                if blocker:
+                    # If visible, ensure parent will be visible too
+                    hidden.discard(parent)
+                heappush(heap, -parent)
+    return hidden
 
 def _getdynamicblockers(repo):
     """Non-cacheable revisions blocking hidden changesets from being filtered.