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.
--- 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 --
--- 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)
--- 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
--- 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]