Mercurial > evolve
diff hgext/evolve.py @ 1634:9ae4e79a28f3
evolve--list: initial implementation
This implementation does not work with '-T json' since it needs multiple levels
of depth.
There is various small issue with the current data, the test coverage is a bit
low and the output is likely to change, but this is a good step forward.
Sample output:
01a3e66ba030: e (amended)
unstable: 1995fc658ad6 (unstable parent)
divergent: 84e1c6ae319d d3b90e9c84ab (precursor 3efa43a7427b)
divergent: add9a356b8cf (precursor 3efa43a7427b)
add9a356b8cf: e (rebased)
divergent: 84e1c6ae319d d3b90e9c84ab (precursor 3efa43a7427b)
divergent: 01a3e66ba030 (precursor 3efa43a7427b)
84e1c6ae319d: e (e+f split)
unstable: 1995fc658ad6 (unstable parent)
divergent: 01a3e66ba030 (precursor 3efa43a7427b)
divergent: add9a356b8cf (precursor 3efa43a7427b)
d3b90e9c84ab: f (e+f split)
unstable: 84e1c6ae319d (unstable parent)
divergent: 01a3e66ba030 (precursor 3efa43a7427b)
divergent: add9a356b8cf (precursor 3efa43a7427b)
8febfaee0dd1: c
unstable: 43765473b851 (obsolete parent)
bumped: b36d99df9f41 (immutable precursor)
1995fc658ad6: d: commit with a long happy message, ababagalamaga, ababagal...
unstable: 8febfaee0dd1 (unstable parent)
fa8498ad030f: aa
unstable: d3b90e9c84ab (unstable parent)
author | Kostia Balytskyi <ikostia@fb.com> |
---|---|
date | Tue, 22 Mar 2016 14:08:16 -0700 |
parents | 9bcb24c3ba8d |
children | 91ba7e0daff6 |
line wrap: on
line diff
--- a/hgext/evolve.py Fri Mar 18 23:49:32 2016 -0700 +++ b/hgext/evolve.py Tue Mar 22 14:08:16 2016 -0700 @@ -1514,6 +1514,110 @@ ordering.extend(sorted(dependencies)) return ordering +def divergentsets(repo, ctx): + """Compute sets of commits divergent with a given one""" + cache = {} + succsets = {} + base = {} + for n in obsolete.allprecursors(repo.obsstore, [ctx.node()]): + if n == ctx.node(): + # a node can't be a base for divergence with itself + continue + nsuccsets = obsolete.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 + divergence = [] + for divset, b in base.iteritems(): + divergence.append({ + 'divergentnodes': divset, + 'commonprecursor': b + }) + + return divergence + +def _preparelistctxs(items, condition): + return [item.hex() for item in items if condition(item)] + +def _formatctx(fm, ctx): + fm.data(node=ctx.hex()) + fm.data(desc=ctx.description()) + fm.data(date=ctx.date()) + fm.data(user=ctx.user()) + +def listtroubles(ui, repo, troublecategories, **opts): + """Print all the troubles for the repo (or given revset)""" + troublecategories = troublecategories or ['divergent', 'unstable', 'bumped'] + showunstable = 'unstable' in troublecategories + showbumped = 'bumped' in troublecategories + showdivergent = 'divergent' in troublecategories + + revs = repo.revs('+'.join("%s()" % t for t in troublecategories)) + if opts.get('rev'): + revs = revs & repo.revs(opts.get('rev')) + + fm = ui.formatter('evolvelist', opts) + for rev in revs: + ctx = repo[rev] + unpars = _preparelistctxs(ctx.parents(), lambda p: p.unstable()) + obspars = _preparelistctxs(ctx.parents(), lambda p: p.obsolete()) + imprecs = _preparelistctxs(repo.set("allprecursors(%n)", ctx.node()), + lambda p: not p.mutable()) + dsets = divergentsets(repo, ctx) + + fm.startitem() + # plain formatter section + hashlen, desclen = 12, 60 + desc = ctx.description() + desc = (desc[:desclen] + '...') if len(desc) > desclen else desc + fm.plain('%s: ' % ctx.hex()[:hashlen]) + fm.plain('%s\n' % desc) + + for unpar in unpars if showunstable else []: + fm.plain(' unstable: %s (unstable parent)\n' % unpar[:hashlen]) + for obspar in obspars if showunstable else []: + fm.plain(' unstable: %s (obsolete parent)\n' % obspar[:hashlen]) + for imprec in imprecs if showbumped else []: + fm.plain(' bumped: %s (immutable precursor)\n' % imprec[:hashlen]) + + if dsets and showdivergent: + for dset in dsets: + fm.plain(' divergent: ') + first = True + for n in dset['divergentnodes']: + t = "%s" if first else " %s" + first = False + fm.plain(t % node.hex(n)[:hashlen]) + comprec = node.hex(dset['commonprecursor'])[:hashlen] + fm.plain(" (precursor %s)\n" % comprec) + fm.plain("\n") + + # templater-friendly section + _formatctx(fm, ctx) + troubles = [] + for unpar in unpars: + troubles.append({'troubletype': 'unstable', 'sourcenode': unpar, + 'sourcetype': 'unstableparent'}) + for obspar in obspars: + troubles.append({'troubletype': 'unstable', 'sourcenode': obspar, + 'sourcetype': 'obsoleteparent'}) + for imprec in imprecs: + troubles.append({'troubletype': 'bumped', 'sourcenode': imprec, + 'sourcetype': 'immutableprecursor'}) + for dset in dsets: + divnodes = [{'node': n} for n in dset['divergentnodes']] + troubles.append({'troubletype': 'divergent', + 'commonprecursor': dset['commonprecursor'], + 'divergentnodes': divnodes}) + fm.data(troubles=troubles) + + fm.end() + @command('^evolve|stabilize|solve', [('n', 'dry-run', False, _('do not perform actions, just print what would be done')), @@ -1529,6 +1633,7 @@ ('a', 'all', False, _('evolve all troubled changesets related to the ' 'current working directory and its descendants')), ('c', 'continue', False, _('continue an interrupted evolution')), + ('l', 'list', False, 'provide details on troubled changesets in the repo'), ] + mergetoolopts, _('[OPTIONS]...')) def evolve(ui, repo, **opts): @@ -1596,9 +1701,13 @@ (the default). You can combine ``--bumped`` or ``--divergent`` with ``--rev``, ``--all``, or ``--any``. + You can also use the evolve command to list the troubles affecting your + repository by using the --list flag. You can choose to display only some + categories of troubles with the --unstable, --divergent or --bumped flags. """ # Options + listopt = opts['list'] contopt = opts['continue'] anyopt = opts['any'] allopt = opts['all'] @@ -1608,6 +1717,10 @@ revopt = opts['rev'] troublecategories = ['bumped', 'divergent', 'unstable'] specifiedcategories = [t for t in troublecategories if opts[t]] + if listopt: + listtroubles(ui, repo, specifiedcategories, **opts) + return + targetcat = 'unstable' if 1 < len(specifiedcategories): msg = _('cannot specify more than one trouble category to solve (yet)')