hgext/evolve.py
changeset 1404 848a04c078c7
parent 1403 9a8ecfdfa866
child 1405 eaf82490af76
--- a/hgext/evolve.py	Fri Jun 19 13:57:16 2015 -0700
+++ b/hgext/evolve.py	Tue Jun 16 15:14:37 2015 -0700
@@ -1183,15 +1183,22 @@
         mean = sum(len(x[1]) for x in allpclusters) // nbcluster
         ui.write('        mean length:        %9i\n' % mean)
 
-def _solveone(ui, repo, ctx, dryrun, confirm, progresscb):
+def _solveone(ui, repo, ctx, dryrun, confirm, progresscb, category):
     """Resolve the troubles affecting one revision"""
     wlock = lock = tr = None
     try:
         wlock = repo.wlock()
         lock = repo.lock()
         tr = repo.transaction("evolve")
-        result = _evolveany(ui, repo, ctx, dryrun, confirm,
-                            progresscb=progresscb)
+        if 'unstable' == category:
+            result = _solveunstable(ui, repo, ctx, dryrun, confirm, progresscb)
+        elif 'bumped' == category:
+            result = _solvebumped(ui, repo, ctx, dryrun, confirm, progresscb)
+        elif 'divergent' == category:
+            result = _solvedivergent(ui, repo, ctx, dryrun, confirm,
+                                   progresscb)
+        else:
+            assert False, "unknown trouble category: %s" % (category)
         tr.close()
         return result
     finally:
@@ -1335,6 +1342,9 @@
         'ask for confirmation before performing the action'),
     ('A', 'any', False, 'also consider troubled changesets unrelated to current working directory'),
     ('r', 'rev', '', 'solves troubles of these revisions'),
+    ('', 'bumped', False, 'solves only bumped changesets'),
+    ('', 'divergent', False, 'solves only divergent changesets'),
+    ('', 'unstable', False, 'solves only unstable changesets (default)'),
     ('a', 'all', False, 'evolve all troubled changesets in the repo '
                         '(implies any)'),
     ('c', 'continue', False, 'continue an interrupted evolution'),
@@ -1358,15 +1368,16 @@
     working copy will be updated on the result (this last behavior will most
     likely to change in the future).
 
-    See --all and --any options to change this behavior.
-
-    - For unstable, this means taking the first which could be rebased as a
-      child of the working directory parent revision or one of its descendants
-      and rebasing it.
-
-    - For divergent, this means taking "." if applicable.
-
-    With --any, evolve picks any troubled changeset to repair.
+    You can decide to evolve other categories of trouble using the --divergent
+    and --bumped flags. If no other option are specified, this will try to
+    solve the specified troubles for the working copy parent.
+
+    You can also evolve changesets affected by troubles of the selected
+    category using the --rev options. You can pick the next one anywhere in the
+    repo using --any.
+
+    You can evolve all the changesets affected by troubles of the selected
+    category using --all.
 
     The working directory is updated to the newly created revision.
     """
@@ -1379,6 +1390,15 @@
     dryrunopt = opts['dry_run']
     confirmopt = opts['confirm']
     revopt = opts['rev']
+    troublecategories = ['bumped', 'divergent', 'unstable']
+    specifiedcategories = [t for t in troublecategories if opts[t]]
+    targetcat = 'unstable'
+    if 1 < len(specifiedcategories):
+        msg = _('cannot specify more than one trouble category to solve (yet)')
+        raise util.Abort(msg)
+    elif len(specifiedcategories) == 1:
+        targetcat = specifiedcategories[0]
+
     ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
     troubled = set(repo.revs('troubled()'))
 
@@ -1401,61 +1421,42 @@
         return graftcmd(ui, repo, old_obsolete=True, **{'continue': True})
     cmdutil.bailifchanged(repo)
 
-    # Rev specified on the commands line
-    if revopt:
-        revs = repo.revs(revopt)
-        troubled = repo.revs('troubled()')
-        _revs = revs & troubled
-        if not _revs:
-            ui.write_err("No troubled changes in the specified revisions\n")
-        else:
-            # For the progress bar to show
-            count = len(_revs)
-            # Order the revisions
-            _revs = orderrevs(repo, _revs)
-            for rev in _revs:
-                progresscb()
-                _solveone(ui, repo, repo[rev], dryrunopt, confirmopt,
-                        progresscb)
-                seen += 1
-            progresscb()
-            _cleanup(ui, repo, startnode, showprogress)
-        return
-    nexttrouble = _picknexttroubled(ui, repo, anyopt or allopt)
-    # No trouble to resolve
-    if not nexttrouble:
-        return _handlenotrouble(ui, repo, startnode, dryrunopt)
-
-    if allopt:
-        # Resolving all the troubles
-        while nexttrouble:
-            progresscb()
-            _solveone(ui, repo, nexttrouble, dryrunopt, confirmopt, progresscb)
-            seen += 1
-            progresscb()
-            nexttrouble= _picknexttroubled(ui, repo, anyopt or allopt)
-    else:
-        # Resolving a single trouble
-        _solveone(ui, repo, nexttrouble, dryrunopt, confirmopt, progresscb)
-
+
+    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 not revs:
+        msg = "no troubled changes in the specified revisions"
+        raise util.Abort(msg)
+
+    # For the progress bar to show
+    count = len(revs)
+    # Order the revisions
+    if targetcat == 'unstable':
+        revs = orderrevs(repo, revs)
+    for rev in revs:
+        progresscb()
+        _solveone(ui, repo, repo[rev], dryrunopt, confirmopt,
+                progresscb, targetcat)
+        seen += 1
+    progresscb()
     _cleanup(ui, repo, startnode, showprogress)
 
-
-def _evolveany(ui, repo, tro, dryrunopt, confirmopt, progresscb):
-    repo = repo.unfiltered()
-    tro = repo[tro.rev()]
-    troubles = tro.troubles()
-    if 'unstable' in troubles:
-        return _solveunstable(ui, repo, tro, dryrunopt, confirmopt, progresscb)
-    elif 'bumped' in troubles:
-        return _solvebumped(ui, repo, tro, dryrunopt, confirmopt, progresscb)
-    elif 'divergent' in troubles:
-        return _solvedivergent(ui, repo, tro, dryrunopt, confirmopt,
-                               progresscb)
-    else:
-        assert False  # WHAT? unknown troubles
-
-def _picknexttroubled(ui, repo, pickany=False, progresscb=None):
+def _picknexttroubled(ui, repo, category, pickany=False, progresscb=None):
     """Pick a the next trouble changeset to solve"""
     if progresscb: progresscb()
     tro = _stabilizableunstable(repo, repo['.'])
@@ -1555,6 +1556,8 @@
 def _solvebumped(ui, repo, bumped, dryrun=False, confirm=False,
                  progresscb=None):
     """Stabilize a bumped changeset"""
+    repo = repo.unfiltered()
+    bumped = repo[bumped.rev()]
     # For now we deny bumped merge
     if len(bumped.parents()) > 1:
         raise util.Abort('late comer stabilization is confused by bumped'
@@ -1661,6 +1664,8 @@
 
 def _solvedivergent(ui, repo, divergent, dryrun=False, confirm=False,
                     progresscb=None):
+    repo = repo.unfiltered()
+    divergent = repo[divergent.rev()]
     base, others = divergentdata(divergent)
     if len(others) > 1:
         othersstr = "[%s]" % (','.join([str(i) for i in others]))