Skip to content
Snippets Groups Projects

more in-depth refactoring for obslog --origins and some unused yet functions/keyword arguments

Closed Anton Shestakov requested to merge topic/default/obslog-predecessors-1 into branch/default
All threads resolved!
Files
3
+ 141
81
@@ -97,10 +97,10 @@ def cmdobshistory(ui, repo, *revs, **opts):
opts['template'] = DEFAULT_TEMPLATE
if opts['graph']:
return _debugobshistorygraph(ui, repo, revs, opts)
return displaygraph(ui, repo, revs, opts)
revs.reverse()
_debugobshistoryrevs(ui, repo, revs, opts)
displayrevs(ui, repo, revs, opts)
TEMPLATE_MISSING_NODE = b"""{label("evolve.node evolve.missing_change_ctx", node|short)}"""
TEMPLATE_PRESENT_NODE = b"""{label("evolve.node", node|short)} {label("evolve.rev", "({rev})")} {label("evolve.short_description", desc|firstline)}"""
@@ -108,12 +108,13 @@ TEMPLATE_FIRST_LINE = b"""{if(rev, "%(presentnode)s", "%(missingnode)s")}""" % {
b"presentnode": TEMPLATE_PRESENT_NODE,
b"missingnode": TEMPLATE_MISSING_NODE
}
TEMPLATE_VERB = b"""{label("evolve.verb", verb)}"""
TEMPLATE_PREDNODES = b"""{label("evolve.node", join(prednodes % "{prednode|short}", ", "))}"""
TEMPLATE_SUCCNODES = b"""{label("evolve.node", join(succnodes % "{succnode|short}", ", "))}"""
TEMPLATE_REWRITE = b"""{if(succnodes, "%(verb)s{if(effects, "({join(effects, ", ")})")} as %(succnodes)s", "pruned")}""" % {
b"verb": TEMPLATE_VERB,
TEMPLATE_NODES = b"""{if(prednodes, "from %(prednodes)s")}{if(succnodes, "as %(succnodes)s")}""" % {
b"prednodes": TEMPLATE_PREDNODES,
b"succnodes": TEMPLATE_SUCCNODES
}
TEMPLATE_REWRITE = b"""{label("evolve.verb", verb)}{if(effects, "({join(effects, ", ")})")}"""
TEMPLATE_OPERATIONS = b"""{if(operations, "using {label("evolve.operation", join(operations, ", "))}")}"""
TEMPLATE_USERS = b"""by {label("evolve.user", join(users, ", "))}"""
TEMPLATE_ONE_DATE = b"""({date(max(dates), "%a %b %d %H:%M:%S %Y %1%2")})"""
@@ -125,10 +126,11 @@ TEMPLATE_DATES = b"""{label("evolve.date", ifeq(min(dates), max(dates), "%(oneda
TEMPLATE_NOTES = b"""{if(notes, notes % "\n note: {label("evolve.note", note)}")}"""
TEMPLATE_PATCH = b"""{if(patch, "{patch}")}{if(nopatchreason, "\n(No patch available, {nopatchreason})")}"""
DEFAULT_TEMPLATE = (b"""%(firstline)s
{markers %% " {separate(" ", "%(rewrite)s", "%(operations)s", "%(users)s", "%(dates)s")}%(notes)s{indent(descdiff, " ")}{indent("%(patch)s", " ")}\n"}
{markers %% " {separate(" ", "%(rewrite)s", "%(nodes)s", "%(operations)s", "%(users)s", "%(dates)s")}%(notes)s{indent(descdiff, " ")}{indent("%(patch)s", " ")}\n"}
""") % {
b"firstline": TEMPLATE_FIRST_LINE,
b"rewrite": TEMPLATE_REWRITE,
b"nodes": TEMPLATE_NODES,
b"operations": TEMPLATE_OPERATIONS,
b"users": TEMPLATE_USERS,
b"dates": TEMPLATE_DATES,
@@ -136,6 +138,19 @@ DEFAULT_TEMPLATE = (b"""%(firstline)s
b"patch": TEMPLATE_PATCH,
}
def _nodesandmarkers(repo, ctx, filternonlocal):
if filternonlocal:
r = obsutil.successorsandmarkers(repo, ctx)
if r is None:
r = []
for succset in sorted(r):
if succset[b'markers']:
yield (succset[b'successors'], succset[b'markers'])
else:
markers = repo.obsstore.successors.get(ctx.node(), ())
for marker in sorted(markers):
yield (marker[1], [marker])
class obsmarker_printer(logcmdutil.changesetprinter):
"""show (available) information about a node
@@ -169,35 +184,14 @@ class obsmarker_printer(logcmdutil.changesetprinter):
_props = {b"template": self.template}
fm = self.ui.formatter(b'debugobshistory', _props)
_debugobshistorydisplaynode(fm, self.repo, changenode)
displaynode(fm, self.repo, changenode)
markerfm = fm.nested(b"markers")
# Succs markers
if self.filter is False:
succs = self.repo.obsstore.successors.get(changenode, ())
succs = sorted(succs)
for successor in succs:
_debugobshistorydisplaymarker(self.ui, markerfm,
successor[1], [successor],
ctx.node(), self.repo,
self._includediff)
else:
r = obsutil.successorsandmarkers(self.repo, ctx)
if r is None:
r = []
for succset in sorted(r):
markers = succset[b"markers"]
if not markers:
continue
successors = succset[b"successors"]
_debugobshistorydisplaymarker(self.ui, markerfm,
successors, markers,
ctx.node(), self.repo,
self._includediff)
data = _nodesandmarkers(self.repo, ctx, self.filter)
for nodes, markers in data:
displaymarkers(self.ui, markerfm, nodes, markers, ctx.node(),
self.repo, self._includediff)
markerfm.end()
@@ -208,7+202,7 @@
else:
### graph output is buffered only
msg = b'cannot be used outside of the graphlog (yet)'
raise error.ProgrammingError(msg)
def flush(self, ctx):
''' changeset_printer has some logic around buffering data
@@ -216,7+210,7 @@
'''
pass
def patchavailable(node, repo, successors):
def patchavailable(node, repo, candidates, successive=True):
if node not in repo:
return False, b"context is not local"
if len(successors) == 0:
return False, b"no successors"
elif len(successors) > 1:
return False, b"too many successors (%d)" % len(successors)
if len(candidates) == 0:
if successive:
msg = b"no successors"
else:
msg = b"no predecessors"
return False, msg
elif len(candidates) > 1:
if successive:
msg = b"too many successors (%d)"
else:
msg = b"too many predecessors (%d)"
return False, msg % len(candidates)
succ = successors[0]
cand = candidates[0]
if succ not in repo:
return False, b"successor is unknown locally"
if cand not in repo:
if successive:
msg = b"successor is unknown locally"
else:
msg = b"predecessor is unknown locally"
return False, msg
# Check that both node and succ have the same parents
# Check that both node and cand have the same parents
nodep1, nodep2 = repo[node].p1(), repo[node].p2()
succp1, succp2 = repo[succ].p1(), repo[succ].p2()
candp1, candp2 = repo[cand].p1(), repo[cand].p2()
if nodep1 != succp1 or nodep2 != succp2:
if nodep1 != candp1 or nodep2 != candp2:
return False, b"changesets rebased"
return True, succ
return True, cand
def getmarkerdescriptionpatch(repo, basedesc, succdesc):
# description are stored without final new line,
@@ -427,7 +433,7 @@ def _obshistorywalker_links(repo, revs, walksuccessors=False):
return sorted(seen), nodesucc, nodeprec
def _debugobshistorygraph(ui, repo, revs, opts):
def displaygraph(ui, repo, revs, opts):
displayer = obsmarker_printer(ui, repo.unfiltered(), obspatch=True,
diffopts=pycompat.byteskwargs(opts),
@@ -437,47 +443,68 @@ def _debugobshistorygraph(ui, repo, revs, opts):
opts.get('filternonlocal', False))
logcmdutil.displaygraph(ui, repo, walker, displayer, edges)
def _debugobshistoryrevs(ui, repo, revs, opts):
def displayrevs(ui, repo, revs, opts):
""" Display the obsolescence history for revset
"""
fm = ui.formatter(b'debugobshistory', pycompat.byteskwargs(opts))
precursors = repo.obsstore.predecessors
predecessors = repo.obsstore.predecessors
successors = repo.obsstore.successors
nodec = repo.changelog.node
unfi = repo.unfiltered()
nodes = [nodec(r) for r in revs]
seen = set(nodes)
toshow = []
walksuccessors = opts and opts.get('all')
filternonlocal = opts and opts.get('filternonlocal')
includediff = opts and opts.get('patch')
while nodes:
ctxnode = nodes.pop()
_debugobshistorydisplaynode(fm, unfi, ctxnode)
if ctxnode in unfi:
toshow.append(unfi[ctxnode])
else:
if filternonlocal is False:
toshow.append(missingchangectx(unfi, ctxnode))
preds = predecessors.get(ctxnode, ())
for p in sorted(preds):
# Only show nodes once
if p[0] not in seen:
seen.add(p[0])
nodes.append(p[0])
if walksuccessors:
for successor in successors.get(ctxnode, ()):
for s in successor[1]:
if s not in seen:
seen.add(s)
nodes.append(s)
succs = successors.get(ctxnode, ())
for ctx in toshow:
displaynode(fm, unfi, ctx.node())
markerfm = fm.nested(b"markers")
for successor in sorted(succs):
includediff = opts and opts.get("patch")
_debugobshistorydisplaymarker(ui, markerfm, successor[1], [successor], ctxnode, unfi, includediff)
data = _nodesandmarkers(repo, ctx, filternonlocal)
for nodes_, markers in data:
displaymarkers(ui, markerfm, nodes_, markers, ctx.node(), unfi,
includediff)
markerfm.end()
fm.plain(b'\n')
precs = precursors.get(ctxnode, ())
for p in sorted(precs):
# Only show nodes once
if p[0] not in seen:
seen.add(p[0])
nodes.append(p[0])
fm.end()
def _debugobshistorydisplaynode(fm, repo, node):
def displaynode(fm, repo, node):
if node in repo:
_debugobshistorydisplayctx(fm, repo[node])
displayctx(fm, repo[node])
else:
_debugobshistorydisplaymissingctx(fm, node)
displaymissingctx(fm, node)
def _debugobshistorydisplayctx(fm, ctx):
def displayctx(fm, ctx):
shortdescription = ctx.description().strip()
if shortdescription:
shortdescription = shortdescription.splitlines()[0]
@@ -495,17 +522,21 @@ def _debugobshistorydisplayctx(fm, ctx):
label=b"evolve.short_description")
fm.plain(b'\n')
def _debugobshistorydisplaymissingctx(fm, nodewithoutctx):
def displaymissingctx(fm, nodewithoutctx):
fm.startitem()
fm.data(node=nodemod.hex(nodewithoutctx))
fm.plain(nodemod.short(nodewithoutctx),
label=b"evolve.node evolve.missing_change_ctx")
fm.plain(b'\n')
def _debugobshistorydisplaymarker(ui, fm, succnodes, markers, node, repo, includediff=False):
def displaymarkers(ui, fm, nodes, markers, node, repo, includediff=False,
successive=True):
fm.startitem()
verb = _successorsetverb(succnodes, markers)[b"verb"]
if successive:
verb = _successorsetverb(nodes, markers)[b"verb"]
else:
verb = _predecessorsverb(nodes, markers)
fm.data(verb=verb)
@@ -514,10 +545,14 @@ def _debugobshistorydisplaymarker(ui, fm, succnodes, markers, node, repo, includ
fmteffects = fm.formatlist(effects, b'effect', sep=b', ')
fm.data(effects=fmteffects)
if len(succnodes) > 0:
hexnodes = (nodemod.hex(succnode) for succnode in sorted(succnodes))
nodes = fm.formatlist(hexnodes, b'succnode')
fm.data(succnodes=nodes)
if len(nodes) > 0:
hexnodes = (nodemod.hex(node) for node in sorted(nodes))
if successive:
nodelist = fm.formatlist(hexnodes, b'succnode')
fm.data(succnodes=nodelist)
else:
nodelist = fm.formatlist(hexnodes, b'prednode')
fm.data(prednodes=nodelist)
# Operations
operations = obsutil.markersoperations(markers)
@@ -539,22 +574,27 @@ def _debugobshistorydisplaymarker(ui, fm, succnodes, markers, node, repo, includ
# Patch display
if includediff is True:
_patchavailable = patchavailable(node, repo, succnodes)
_patchavailable = patchavailable(node, repo, nodes,
successive=successive)
if _patchavailable[0] is True:
succ = _patchavailable[1]
diffnode = _patchavailable[1]
basectx = repo[node]
succctx = repo[succ]
if successive:
actx = repo[node]
bctx = repo[diffnode]
else:
actx = repo[diffnode]
bctx = repo[node]
# Description patch
descriptionpatch = getmarkerdescriptionpatch(repo,
basectx.description(),
succctx.description())
actx.description(),
bctx.description())
if descriptionpatch:
# add the diffheader
diffheader = b"diff -r %s -r %s changeset-description\n" %\
(basectx, succctx)
(actx, bctx)
descriptionpatch = diffheader + descriptionpatch
def tolist(text):
@@ -574,8 +614,8 @@ def _debugobshistorydisplaymarker(ui, fm, succnodes, markers, node, repo, includ
matchfn = scmutil.matchall(repo)
firstline = True
linestart = True
for chunk, label in patch.diffui(repo, node, succ, matchfn,
opts=diffopts):
for chunk, label in patch.diffui(repo, actx.node(), bctx.node(),
matchfn, opts=diffopts):
if firstline:
ui.write(b'\n')
firstline = False
@@ -708,6 +748,26 @@ def _successorsetverb(successorset, markers):
verb = b'split'
return {b'verb': verb}
def _predecessorsverb(predecessors, markers):
""" Return the verb summarizing a set of predecessors and related markers.
"""
verb = None
if not predecessors:
# we got successors instead of predecessors, and they are empty
# (this is a special case for showing prunes)
verb = b'pruned'
elif len(markers) == 1 and len(markers[0][1]) > 1:
# peeked at the successors to see if this is a split
verb = b'split'
elif len(predecessors) == 1:
verb = _markerspreciseverb(markers)
if verb is None:
verb = b'rewritten'
else:
verb = b'folded'
return verb
# Use a more advanced version of obsfateverb that uses effect-flag
@eh.wrapfunction(obsutil, 'obsfateverb')
def obsfateverb(orig, *args, **kwargs):
Loading