[PATCH 8 of 9] dagop: make walk direction switchable so it can track descendants
Yuya Nishihara
yuya at tcha.org
Sun Jun 25 03:26:17 UTC 2017
# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1498314903 -32400
# Sat Jun 24 23:35:03 2017 +0900
# Node ID c3d660d2185847c26885b3467819c3c24ac769c6
# Parent 63b200dd478b6be7665d02c40a7c7ed62e2df6d1
dagop: make walk direction switchable so it can track descendants
# ancestors(tip) using hg repo
2) 0.068527
3) 0.069097
diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -23,10 +23,11 @@ generatorset = smartset.generatorset
# possible maximum depth between null and wdir()
_maxlogdepth = 0x80000000
-def _walkrevtree(pfunc, revs, startdepth, stopdepth):
+def _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse):
"""Walk DAG using 'pfunc' from the given 'revs' nodes
- 'pfunc(rev)' should return the parent revisions of the given 'rev'.
+ 'pfunc(rev)' should return the parent/child revisions of the given 'rev'
+ if 'reverse' is True/False respectively.
Scan ends at the stopdepth (exlusive) if specified. Revisions found
earlier than the startdepth are omitted.
@@ -39,25 +40,29 @@ def _walkrevtree(pfunc, revs, startdepth
return
if stopdepth < 0:
raise error.ProgrammingError('negative stopdepth')
+ if reverse:
+ heapsign = -1 # max heap
+ else:
+ heapsign = +1 # min heap
# load input revs lazily to heap so earlier revisions can be yielded
# without fully computing the input revs
- revs.sort(reverse=True)
+ revs.sort(reverse)
irevs = iter(revs)
- pendingheap = [] # [(-rev, depth), ...] (i.e. lower depth first)
+ pendingheap = [] # [(heapsign * rev, depth), ...] (i.e. lower depth first)
inputrev = next(irevs, None)
if inputrev is not None:
- heapq.heappush(pendingheap, (-inputrev, 0))
+ heapq.heappush(pendingheap, (heapsign * inputrev, 0))
lastrev = None
while pendingheap:
currev, curdepth = heapq.heappop(pendingheap)
- currev = -currev
+ currev = heapsign * currev
if currev == inputrev:
inputrev = next(irevs, None)
if inputrev is not None:
- heapq.heappush(pendingheap, (-inputrev, 0))
+ heapq.heappush(pendingheap, (heapsign * inputrev, 0))
# rescan parents until curdepth >= startdepth because queued entries
# of the same revision are iterated from the lowest depth
foundnew = (currev != lastrev)
@@ -68,7 +73,7 @@ def _walkrevtree(pfunc, revs, startdepth
if foundnew and pdepth < stopdepth:
for prev in pfunc(currev):
if prev != node.nullrev:
- heapq.heappush(pendingheap, (-prev, pdepth))
+ heapq.heappush(pendingheap, (heapsign * prev, pdepth))
def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth):
if followfirst:
@@ -81,7 +86,7 @@ def _genrevancestors(repo, revs, followf
return cl.parentrevs(rev)[:cut]
except error.WdirUnsupported:
return (pctx.rev() for pctx in repo[rev].parents()[:cut])
- return _walkrevtree(pfunc, revs, startdepth, stopdepth)
+ return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=True)
def revancestors(repo, revs, followfirst, startdepth=None, stopdepth=None):
"""Like revlog.ancestors(), but supports additional options, includes
More information about the Mercurial-devel
mailing list