Patchwork [2,of,4,V2] repoview: split _gethiddenblockers

login
register
mail settings
Submitter David Soria Parra
Date Aug. 13, 2014, 9:43 p.m.
Message ID <fc977262986e18870209.1407966239@dev544.prn1.facebook.com>
Download mbox | patch
Permalink /patch/5378/
State Accepted
Headers show

Comments

David Soria Parra - Aug. 13, 2014, 9:43 p.m.
# HG changeset patch
# User David Soria Parra <davidsp@fb.com>
# Date 1407356764 25200
#      Wed Aug 06 13:26:04 2014 -0700
# Node ID fc977262986e188702091f7d98f1ccd076e36316
# Parent  eeafc9cb22a894e4c76ca464f5b5bfd37fd37f05
repoview: split _gethiddenblockers

Split up _gethiddenblockers into two categories: (1) "static' blockers
that solely rely on the contents of obstore and are visible children of
hidden changsets. (2) "dynamic" blockers, appearing by having wd parents,
bookmarks or tags pointing to hidden changesets.

We assume that (1) doesn't change often and can be easily cached with a good
invalidation strategy. (2) change often, but barely produce blockers, so we
can recompute them if necessary.

Patch

diff --git a/mercurial/repoview.py b/mercurial/repoview.py
--- a/mercurial/repoview.py
+++ b/mercurial/repoview.py
@@ -19,13 +19,14 @@ 
     This is a standalone function to help extensions to wrap it."""
     return obsolete.getrevs(repo, 'obsolete')
 
-def _gethiddenblockers(repo):
-    """Get revisions that will block hidden changesets from being filtered
+def _getstaticblockers(repo):
+    """Cacheable revisions blocking hidden changesets from being filtered.
 
+    Additional non-cached hidden blockers are computed in _getdynamicblockers.
     This is a standalone function to help extensions to wrap it."""
     assert not repo.changelog.filteredrevs
     hideable = hideablerevs(repo)
-    blockers = []
+    blockers = set([])
     if hideable:
         # We use cl to avoid recursive lookup from repo[xxx]
         cl = repo.changelog
@@ -33,15 +34,25 @@ 
         revs = cl.revs(start=firsthideable)
         tofilter = repo.revs(
             '(%ld) and children(%ld)', list(revs), list(hideable))
-        blockers = set([r for r in tofilter if r not in hideable])
-        for par in repo[None].parents():
-            blockers.add(par.rev())
-        for bm in repo._bookmarks.values():
-            blockers.add(cl.rev(bm))
-        tags = {}
-        tagsmod.readlocaltags(repo.ui, repo, tags, {})
-        if tags:
-            blockers.update(cl.rev(t[0]) for t in tags.values())
+        blockers.update([r for r in tofilter if r not in hideable])
+    return blockers
+
+def _getdynamicblockers(repo):
+    """Non-cacheable revisions blocking hidden changesets from being filtered.
+
+    Get revisions that will block hidden changesets and are likely to change,
+    but unlikely to create hidden blockers. They won't be cached, so be careful
+    with adding additional computation."""
+
+    cl = repo.changelog
+    blockers = set([])
+    blockers.update([par.rev() for par in repo[None].parents()])
+    blockers.update([cl.rev(bm) for bm in repo._bookmarks.values()])
+
+    tags = {}
+    tagsmod.readlocaltags(repo.ui, repo, tags, {})
+    if tags:
+        blockers.update([cl.rev(t[0]) for t in tags.values()])
     return blockers
 
 def computehidden(repo):
@@ -49,12 +60,20 @@ 
 
     During most operation hidden should be filtered."""
     assert not repo.changelog.filteredrevs
+    hidden = frozenset()
     hideable = hideablerevs(repo)
     if hideable:
         cl = repo.changelog
-        blocked = cl.ancestors(_gethiddenblockers(repo), inclusive=True)
-        return frozenset(r for r in hideable if r not in blocked)
-    return frozenset()
+        blocked = cl.ancestors(_getstaticblockers(repo), inclusive=True)
+        hidden = frozenset(r for r in hideable if r not in blocked)
+
+        # check if we have wd parents, bookmarks or tags pointing to hidden
+        # changesets and remove those.
+        dynamic = hidden & _getdynamicblockers(repo)
+        if dynamic:
+            blocked = cl.ancestors(dynamic, inclusive=True)
+            hidden &= frozenset(r for r in hideable if r not in blocked)
+    return hidden
 
 def computeunserved(repo):
     """compute the set of revision that should be filtered when used a server