--- a/mercurial/dagop.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/dagop.py Sun Oct 06 09:45:02 2019 -0400
@@ -9,12 +9,8 @@
import heapq
-from .node import (
- nullrev,
-)
-from .thirdparty import (
- attr,
-)
+from .node import nullrev
+from .thirdparty import attr
from . import (
error,
mdiff,
@@ -30,6 +26,7 @@
# possible maximum depth between null and wdir()
maxlogdepth = 0x80000000
+
def _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse):
"""Walk DAG using 'pfunc' from the given 'revs' nodes
@@ -72,7 +69,7 @@
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)
+ foundnew = currev != lastrev
if foundnew and curdepth >= startdepth:
lastrev = currev
yield currev
@@ -82,6 +79,7 @@
if prev != node.nullrev:
heapq.heappush(pendingheap, (heapsign * prev, pdepth))
+
def filectxancestors(fctxs, followfirst=False):
"""Like filectx.ancestors(), but can walk from multiple files/revisions,
and includes the given fctxs themselves
@@ -90,6 +88,7 @@
"""
visit = {}
visitheap = []
+
def addvisit(fctx):
rev = fctx.rev()
if rev not in visit:
@@ -105,7 +104,7 @@
for c in fctxs:
addvisit(c)
while visit:
- currev = -heapq.heappop(visitheap)
+ currev = -(heapq.heappop(visitheap))
curfctxs = visit.pop(currev)
yield currev, curfctxs
for c in curfctxs:
@@ -113,6 +112,7 @@
addvisit(parent)
assert not visitheap
+
def filerevancestors(fctxs, followfirst=False):
"""Like filectx.ancestors(), but can walk from multiple files/revisions,
and includes the given fctxs themselves
@@ -122,17 +122,20 @@
gen = (rev for rev, _cs in filectxancestors(fctxs, followfirst))
return generatorset(gen, iterasc=False)
+
def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth, cutfunc):
if followfirst:
cut = 1
else:
cut = None
cl = repo.changelog
+
def plainpfunc(rev):
try:
return cl.parentrevs(rev)[:cut]
except error.WdirUnsupported:
return (pctx.rev() for pctx in repo[rev].parents()[:cut])
+
if cutfunc is None:
pfunc = plainpfunc
else:
@@ -140,8 +143,10 @@
revs = revs.filter(lambda rev: not cutfunc(rev))
return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=True)
-def revancestors(repo, revs, followfirst=False, startdepth=None,
- stopdepth=None, cutfunc=None):
+
+def revancestors(
+ repo, revs, followfirst=False, startdepth=None, stopdepth=None, cutfunc=None
+):
r"""Like revlog.ancestors(), but supports additional options, includes
the given revs themselves, and returns a smartset
@@ -163,10 +168,12 @@
|/
A
"""
- gen = _genrevancestors(repo, revs, followfirst, startdepth, stopdepth,
- cutfunc)
+ gen = _genrevancestors(
+ repo, revs, followfirst, startdepth, stopdepth, cutfunc
+ )
return generatorset(gen, iterasc=False)
+
def _genrevdescendants(repo, revs, followfirst):
if followfirst:
cut = 1
@@ -194,6 +201,7 @@
yield i
break
+
def _builddescendantsmap(repo, startrev, followfirst):
"""Build map of 'rev -> child revs', offset from startrev"""
cl = repo.changelog
@@ -207,13 +215,17 @@
descmap[p2rev - startrev].append(currev)
return descmap
+
def _genrevdescendantsofdepth(repo, revs, followfirst, startdepth, stopdepth):
startrev = revs.min()
descmap = _builddescendantsmap(repo, startrev, followfirst)
+
def pfunc(rev):
return descmap[rev - startrev]
+
return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=False)
+
def revdescendants(repo, revs, followfirst, startdepth=None, stopdepth=None):
"""Like revlog.descendants() but supports additional options, includes
the given revs themselves, and returns a smartset
@@ -224,10 +236,12 @@
if startdepth is None and (stopdepth is None or stopdepth >= maxlogdepth):
gen = _genrevdescendants(repo, revs, followfirst)
else:
- gen = _genrevdescendantsofdepth(repo, revs, followfirst,
- startdepth, stopdepth)
+ gen = _genrevdescendantsofdepth(
+ repo, revs, followfirst, startdepth, stopdepth
+ )
return generatorset(gen, iterasc=True)
+
def descendantrevs(revs, revsfn, parentrevsfn):
"""Generate revision number descendants in revision order.
@@ -259,6 +273,7 @@
yield rev
break
+
def _reachablerootspure(pfunc, minroot, roots, heads, includepath):
"""See revlog.reachableroots"""
if not roots:
@@ -294,6 +309,7 @@
reached(rev)
return reachable
+
def reachableroots(repo, roots, heads, includepath=False):
"""See revlog.reachableroots"""
if not roots:
@@ -306,6 +322,7 @@
revs.sort()
return revs
+
def _changesrange(fctx1, fctx2, linerange2, diffopts):
"""Return `(diffinrange, linerange1)` where `diffinrange` is True
if diff from fctx2 to fctx1 has changes in linerange2 and
@@ -316,6 +333,7 @@
diffinrange = any(stype == '!' for _, stype in filteredblocks)
return diffinrange, linerange1
+
def blockancestors(fctx, fromline, toline, followfirst=False):
"""Yield ancestors of `fctx` with respect to the block of lines within
`fromline`-`toline` range.
@@ -349,6 +367,7 @@
if inrange:
yield c, linerange2
+
def blockdescendants(fctx, fromline, toline):
"""Yield descendants of `fctx` with respect to the block of lines within
`fromline`-`toline` range.
@@ -388,6 +407,7 @@
if inrange:
yield c, linerange1
+
@attr.s(slots=True, frozen=True)
class annotateline(object):
fctx = attr.ib()
@@ -396,6 +416,7 @@
skip = attr.ib(default=False)
text = attr.ib(default=None)
+
@attr.s(slots=True, frozen=True)
class _annotatedfile(object):
# list indexed by lineno - 1
@@ -405,16 +426,19 @@
# full file content
text = attr.ib()
+
def _countlines(text):
if text.endswith("\n"):
return text.count("\n")
return text.count("\n") + int(bool(text))
+
def _decoratelines(text, fctx):
n = _countlines(text)
linenos = pycompat.rangelist(1, n + 1)
return _annotatedfile([fctx] * n, linenos, [False] * n, text)
+
def _annotatepair(parents, childfctx, child, skipchild, diffopts):
r'''
Given parent and child fctxes and annotate data for parents, for all lines
@@ -426,8 +450,10 @@
See test-annotate.py for unit tests.
'''
- pblocks = [(parent, mdiff.allblocks(parent.text, child.text, opts=diffopts))
- for parent in parents]
+ pblocks = [
+ (parent, mdiff.allblocks(parent.text, child.text, opts=diffopts))
+ for parent in parents
+ ]
if skipchild:
# Need to iterate over the blocks twice -- make it a list
@@ -482,6 +508,7 @@
child.skips[bk] = True
return child
+
def annotate(base, parents, skiprevs=None, diffopts=None):
"""Core algorithm for filectx.annotate()
@@ -528,8 +555,9 @@
skipchild = False
if skiprevs is not None:
skipchild = f._changeid in skiprevs
- curr = _annotatepair([hist[p] for p in pl], f, curr, skipchild,
- diffopts)
+ curr = _annotatepair(
+ [hist[p] for p in pl], f, curr, skipchild, diffopts
+ )
for p in pl:
if needed[p] == 1:
del hist[p]
@@ -541,8 +569,11 @@
del pcache[f]
a = hist[base]
- return [annotateline(*r) for r in zip(a.fctxs, a.linenos, a.skips,
- mdiff.splitnewlines(a.text))]
+ return [
+ annotateline(*r)
+ for r in zip(a.fctxs, a.linenos, a.skips, mdiff.splitnewlines(a.text))
+ ]
+
def toposort(revs, parentsfunc, firstbranch=()):
"""Yield revisions from heads to roots one (topo) branch at a time.
@@ -695,7 +726,7 @@
#
# we also update the <parents> set to include the parents of the
# new nodes.
- if rev == currentrev: # only display stuff in rev
+ if rev == currentrev: # only display stuff in rev
gr[0].append(rev)
gr[1].remove(rev)
parents = [p for p in parentsfunc(rev) if p > node.nullrev]
@@ -742,6 +773,7 @@
for r in g[0]:
yield r
+
def headrevs(revs, parentsfn):
"""Resolve the set of heads from a set of revisions.
@@ -764,6 +796,7 @@
headrevs.difference_update(parents)
return headrevs
+
def headrevssubset(revsfn, parentrevsfn, startrev=None, stoprevs=None):
"""Returns the set of all revs that have no children with control.
@@ -800,6 +833,7 @@
return heads
+
def linearize(revs, parentsfn):
"""Linearize and topologically sort a list of revisions.