# HG changeset patch # User Pierre-Yves David # Date 1434749193 25200 # Node ID 2c451fece7a64e8bdda6a54ca96327d72345200e # Parent 3276730e4b32ac8d75191dc4d3762ffb0c13429f evolve: unify revision handling and rework error message This changesets do a massive refactoring of the way evolve select changesets to be evolve. We now use a two stages approach: 1) read command line argument and produce a list of revision to evolve. 2) evolve all these revisions. This allow a much cleaner, robust and extensible code. In the process the error message issued when there is nothing to evolve have been updated to informs about other troubles in the repository and point at useful option to solve them. The 'update' case is handled independently at the start of the function. diff -r 3276730e4b32 -r 2c451fece7a6 README --- a/README Fri Jun 19 14:32:54 2015 -0700 +++ b/README Fri Jun 19 14:26:33 2015 -0700 @@ -57,6 +57,8 @@ - evolve: revision are processed in the order they stack on destination - evolve: properly skip unstable revision with non-evolved unstable parent - evolve: gain --unstable --divergent --bumped flag to select the trouble +- evolve: issue more useful error message and hint when evolve has nothing to + do as invocated. 5.1.5 -- diff -r 3276730e4b32 -r 2c451fece7a6 hgext/evolve.py --- a/hgext/evolve.py Fri Jun 19 14:32:54 2015 -0700 +++ b/hgext/evolve.py Fri Jun 19 14:26:33 2015 -0700 @@ -1204,54 +1204,100 @@ finally: lockmod.release(tr, lock, wlock) -def _handlenotrouble(ui, repo, startnode, dryrunopt): +def _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat): """Used by the evolve function to display an error message when no troubles can be resolved""" - if repo['.'].obsolete(): - displayer = cmdutil.show_changeset( - ui, repo, {'template': shorttemplate}) - successors = set() - - for successorsset in obsolete.successorssets(repo, repo['.'].node()): - for nodeid in successorsset: - successors.add(repo[nodeid]) - - if not successors: - ui.warn(_('parent is obsolete without successors; ' + - 'likely killed\n')) - return 2 - - elif len(successors) > 1: - ui.warn(_('parent is obsolete with multiple successors:\n')) - - for ctx in sorted(successors, key=lambda ctx: ctx.rev()): - displayer.show(ctx) - - return 2 - + troublecategories = ['bumped', 'divergent', 'unstable'] + unselectedcategories = [c for c in troublecategories if c != targetcat] + msg = None + hint = None + + troubled = { + "unstable": repo.revs("unstable()"), + "divergent": repo.revs("divergent()"), + "bumped": repo.revs("bumped()"), + "all": repo.revs("troubled()"), + } + + + hintmap = { + 'bumped': _("do you want to use --bumped"), + 'bumped+divergent': _("do you want to use --bumped or --divergent"), + 'bumped+unstable': _("do you want to use --bumped or --unstable"), + 'divergent': _("do you want to use --divergent"), + 'divergent+unstable': _("do you want to use --divergent" + " or --unstable"), + 'unstable': _("do you want to use --unstable"), + 'any+bumped': _("do you want to use --any (or --rev) and --bumped"), + 'any+bumped+divergent': _("do you want to use --any (or --rev) and" + " --bumped or --divergent"), + 'any+bumped+unstable': _("do you want to use --any (or --rev) and" + "--bumped or --unstable"), + 'any+divergent': _("do you want to use --any (or --rev) and" + " --divergent"), + 'any+divergent+unstable': _("do you want to use --any (or --rev)" + " and --divergent or --unstable"), + 'any+unstable': _("do you want to use --any (or --rev)" + "and --unstable"), + } + + if revopt: + revs = scmutil.revrange(repo, revopt) + if not revs: + msg = _("set of specified revisions is empty") else: - ctx = successors.pop() - - ui.status(_('update:')) - if not ui.quiet: - displayer.show(ctx) - - if dryrunopt: - return 0 + msg = _("no %s changesets in specified revisions") % targetcat + othertroubles = [] + for cat in unselectedcategories: + if revs & troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['+'.join(othertroubles)] + + elif allopt or anyopt: + msg = _("no %s changesets to evolve") % targetcat + othertroubles = [] + for cat in unselectedcategories: + if troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['+'.join(othertroubles)] + + else: + # evolve without any option = relative to the current wdir + if targetcat == 'unstable': + msg = _("nothing to evolve on current working copy parent") + else: + msg = _("current working copy parent is not %s") % targetcat + + p1 = repo['.'].rev() + othertroubles = [] + for cat in unselectedcategories: + if p1 in troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['+'.join(othertroubles)] + else: + l = len(troubled[targetcat]) + if l: + hint = (_("%d other %s in the repository, do you want --any or --rev") + % (l, targetcat)) else: - res = hg.update(repo, ctx.rev()) - if ctx != startnode: - ui.status(_('working directory is now at %s\n') % ctx) - return res - - troubled = repo.revs('troubled()') - if troubled: - ui.write_err(_('nothing to evolve here\n')) - ui.status(_('(%i troubled changesets, do you want --any ?)\n') - % len(troubled)) + othertroubles = [] + for cat in unselectedcategories: + if troubled[cat]: + othertroubles.append(cat) + if othertroubles: + hint = hintmap['any+'+('+'.join(othertroubles))] + else: + msg = _("no troubled changesets") + + assert msg is not None + ui.write_err(msg+"\n") + if hint: + ui.write_err("("+hint+")\n") return 2 else: - ui.write_err(_('no troubled changesets\n')) return 1 def _cleanup(ui, repo, startnode, showprogress): @@ -1316,6 +1362,24 @@ rdependencies[succ].add(r) return dependencies, rdependencies +def _selectrevs(repo, allopt, revopt, anyopt, targetcat): + """select troubles in repo matching according to given options""" + revs = set() + if allopt or revopt: + revs = repo.revs(targetcat+'()') + if revopt: + revs = scmutil.revrange(repo, revopt) & revs + elif anyopt: + revs = repo.revs('first(%s())' % (targetcat)) + elif targetcat == 'unstable': + tro = _stabilizableunstable(repo, repo['.']) + if tro is not None: + revs = set([tro]) + elif targetcat in repo['.'].troubles(): + revs = set([repo['.'].rev()]) + return revs + + def orderrevs(repo, revs): """ Compute an ordering to solve instability for the given revs @@ -1425,6 +1489,17 @@ return 2 + ui.status(_('update:')) + if not ui.quiet: + displayer.show(ctx) + + if dryrunopt: + return 0 + res = hg.update(repo, ctx.rev()) + if ctx != startnode: + ui.status(_('working directory is now at %s\n') % ctx) + return res + ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve') troubled = set(repo.revs('troubled()')) @@ -1450,26 +1525,13 @@ if revopt and allopt: raise util.Abort('cannot specify both "--rev" and "--all"') - - revs = set() - if allopt or revopt: - revs = repo.revs(targetcat+'()') - if revopt: - revs = repo.revs(revopt) & revs - elif anyopt: - revs = repo.revs('first(%s())' % (targetcat)) - elif targetcat == 'unstable': - tro = _stabilizableunstable(repo, repo['.']) - if tro is None: - return _handlenotrouble(ui, repo, startnode, dryrunopt) - revs = set([tro]) - elif targetcat in repo['.'].troubles(): - revs = set([repo['.'].rev()]) if revopt and anyopt: raise util.Abort('cannot specify both "--rev" and "--any"') + + revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat) + if not revs: - msg = "no troubled changes in the specified revisions" - raise util.Abort(msg) + return _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat) # For the progress bar to show count = len(revs) diff -r 3276730e4b32 -r 2c451fece7a6 tests/test-evolve.t --- a/tests/test-evolve.t Fri Jun 19 14:32:54 2015 -0700 +++ b/tests/test-evolve.t Fri Jun 19 14:26:33 2015 -0700 @@ -880,8 +880,8 @@ $ hg up 8 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg evolve - nothing to evolve here - (2 troubled changesets, do you want --any ?) + nothing to evolve on current working copy parent + (2 other unstable in the repository, do you want --any or --rev) [2] @@ -1017,12 +1017,13 @@ Evolving an empty revset should do nothing $ hg evolve --rev "16 and 15" - abort: no troubled changes in the specified revisions - [255] + set of specified revisions is empty + [1] $ hg evolve --rev "14::" --bumped - abort: no troubled changes in the specified revisions - [255] + no bumped changesets in specified revisions + (do you want to use --unstable) + [2] $ hg evolve --rev "14::" --unstable move:[15] add gg atop:[18] a3 diff -r 3276730e4b32 -r 2c451fece7a6 tests/test-stabilize-order.t --- a/tests/test-stabilize-order.t Fri Jun 19 14:32:54 2015 -0700 +++ b/tests/test-stabilize-order.t Fri Jun 19 14:26:33 2015 -0700 @@ -153,8 +153,8 @@ $ hg up 9 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg evolve -v - nothing to evolve here - (1 troubled changesets, do you want --any ?) + nothing to evolve on current working copy parent + (1 other unstable in the repository, do you want --any or --rev) [2] $ hg evolve --any -v move:[9] addc @@ -180,5 +180,5 @@ o 0:c471ef929e6a@default(draft) addroot $ hg evolve --any -v - abort: no troubled changes in the specified revisions - [255] + no unstable changesets to evolve + [1]