# HG changeset patch # User Anton Shestakov <a...@dwimlabs.net> # Date 1519649041 -28800 # Mon Feb 26 20:44:01 2018 +0800 # Node ID 0aa1728931cc2c2c7d6ee0f18e0618fc17add42a # Parent aefb75730ea34f545f0756bf8441fc9ae07bf8dc debug: add debugexplainunstable that explains instabilities
This is a port of evolve's feature of listing all unstable changesets in detail (`hg evolve --list`). diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -816,6 +816,17 @@ def debugdownload(ui, repo, url, output= if output: dest.close() +@command('debugexplainunstable', [], _('REV')) +def debugexplainunstable(ui, repo, rev): + """explain instabilities of a changeset""" + for entry in obsolete.explainunstable(repo, repo[rev]): + dnodes = '' + if entry.get('divergentnodes'): + dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr()) + for ctx in entry['divergentnodes']) + ' ' + ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes, + entry['reason'], entry['node'])) + @command('debugextensions', cmdutil.formatteropts, [], norepo=True) def debugextensions(ui, **opts): '''show information about active extensions''' diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py --- a/mercurial/obsolete.py +++ b/mercurial/obsolete.py @@ -1039,3 +1039,35 @@ def createmarkers(repo, relations, flag= date=date, metadata=localmetadata, ui=repo.ui) repo.filteredrevcache.clear() + +def explainunstable(repo, ctx): + result = [] + if ctx.orphan(): + for parent in ctx.parents(): + kind = None + if parent.orphan(): + kind = 'orphan' + elif parent.obsolete(): + kind = 'obsolete' + if kind is not None: + result.append({'instability': 'orphan', + 'reason': '%s parent' % kind, + 'node': parent.hex()}) + if ctx.phasedivergent(): + predecessors = obsutil.allpredecessors(repo.obsstore, [ctx.node()], + ignoreflags=bumpedfix) + immutable = [repo[p] for p in predecessors + if p in repo and not repo[p].mutable()] + for predecessor in immutable: + result.append({'instability': 'phase-divergent', + 'reason': 'immutable predecessor', + 'node': predecessor.hex()}) + if ctx.contentdivergent(): + dsets = obsutil.divergentsets(repo, ctx) + for dset in dsets: + divnodes = [repo[n] for n in dset['divergentnodes']] # hmm + result.append({'instability': 'content-divergent', + 'divergentnodes': divnodes, + 'reason': 'predecessor', + 'node': node.hex(dset['commonpredecessor'])}) + return result diff --git a/mercurial/obsutil.py b/mercurial/obsutil.py --- a/mercurial/obsutil.py +++ b/mercurial/obsutil.py @@ -889,3 +889,23 @@ def _getfilteredreason(repo, changeid, c args = (changeid, firstsuccessors, remainingnumber) return filteredmsgtable['superseded_split_several'] % args + +def divergentsets(repo, ctx): + """Compute sets of commits divergent with a given one""" + cache = {} + base = {} + for n in allpredecessors(repo.obsstore, [ctx.node()]): + if n == ctx.node(): + # a node can't be a base for divergence with itself + continue + nsuccsets = successorssets(repo, n, cache) + for nsuccset in nsuccsets: + if ctx.node() in nsuccset: + # we are only interested in *other* successor sets + continue + if tuple(nsuccset) in base: + # we already know the latest base for this divergency + continue + base[tuple(nsuccset)] = n + return [{'divergentnodes': divset, 'commonpredecessor': b} + for divset, b in base.iteritems()] diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -86,6 +86,7 @@ Show debug commands if there are no othe debugdirstate debugdiscovery debugdownload + debugexplainunstable debugextensions debugfileset debugformat @@ -266,6 +267,7 @@ Show all commands + options debugdirstate: nodates, datesort debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure debugdownload: output + debugexplainunstable: debugextensions: template debugfileset: rev debugformat: template diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -928,6 +928,8 @@ Test list of internal help commands runs the changeset discovery protocol in isolation debugdownload download a resource using Mercurial logic and config + debugexplainunstable + explain instabilities of a changeset debugextensions show information about active extensions debugfileset parse and apply a fileset specification diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t --- a/tests/test-obsolete-divergent.t +++ b/tests/test-obsolete-divergent.t @@ -717,3 +717,6 @@ Use scmutil.cleanupnodes API to create d a178212c3433c4e77b573f6011e29affb8aefa33 1a2a9b5b0030632400aa78e00388c20f99d3ec44 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '1', 'operation': 'amend', 'user': 'test'} a178212c3433c4e77b573f6011e29affb8aefa33 ad6478fb94ecec98b86daae98722865d494ac561 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'operation': 'test', 'user': 'test'} ad6478fb94ecec98b86daae98722865d494ac561 70d5a63ca112acb3764bc1d7320ca90ea688d671 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'test', 'user': 'test'} + + $ hg debugexplainunstable 1a2a9b5b0030 + content-divergent: 70d5a63ca112acb3764bc1d7320ca90ea688d671 (draft) predecessor a178212c3433c4e77b573f6011e29affb8aefa33 diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t --- a/tests/test-obsolete.t +++ b/tests/test-obsolete.t @@ -1033,6 +1033,12 @@ test summary output orphan: 2 changesets phase-divergent: 1 changesets +test debugexplainunstable output + + $ hg debugexplainunstable 50c51b361e60 + orphan: obsolete parent 3de5eca88c00aa039da7399a220f4a5221faa585 + phase-divergent: immutable predecessor 245bde4270cd1072a27757984f9cda8ba26f08ca + #if serve $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel