diff -r 5ec4bda3097a -r 2f7cb6e6acdd mercurial/repoview.py --- a/mercurial/repoview.py Tue Mar 31 22:29:12 2015 -0700 +++ b/mercurial/repoview.py Wed Apr 01 12:50:10 2015 -0700 @@ -6,6 +6,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +import collections import copy import error import phases @@ -13,6 +14,7 @@ import obsolete import struct import tags as tagsmod +from node import nullrev def hideablerevs(repo): """Revisions candidates to be hidden @@ -20,23 +22,37 @@ This is a standalone function to help extensions to wrap it.""" return obsolete.getrevs(repo, 'obsolete') -def _getstaticblockers(repo): +def _getstatichidden(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 = set() if hideable: - # We use cl to avoid recursive lookup from repo[xxx] - cl = repo.changelog - firsthideable = min(hideable) - revs = cl.revs(start=firsthideable) - tofilter = repo.revs( - '(%ld) and children(%ld)', list(revs), list(hideable)) - blockers.update([r for r in tofilter if r not in hideable]) - return blockers + actuallyhidden = {} + getphase = repo._phasecache.phase + getparentrevs = repo.changelog.parentrevs + queue = collections.deque((r, False) for r in repo.changelog.headrevs()) + while queue: + rev, blocked = queue.popleft() + 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): + 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): + queue.append((parent, blocked)) + return set(rev for rev, hidden in actuallyhidden.iteritems() if hidden) def _getdynamicblockers(repo): """Non-cacheable revisions blocking hidden changesets from being filtered. @@ -137,8 +153,7 @@ cl = repo.changelog hidden = tryreadcache(repo, hideable) if hidden is None: - blocked = cl.ancestors(_getstaticblockers(repo), inclusive=True) - hidden = frozenset(r for r in hideable if r not in blocked) + hidden = frozenset(_getstatichidden(repo)) trywritehiddencache(repo, hideable, hidden) # check if we have wd parents, bookmarks or tags pointing to hidden