evolve: add selector for trouble types
authorLaurent Charignon <lcharignon@fb.com>
Tue, 16 Jun 2015 15:14:37 -0700
changeset 1404 848a04c078c7
parent 1403 9a8ecfdfa866
child 1405 eaf82490af76
evolve: add selector for trouble types This patch adds command line flags to select the kind of troubles to solve. Before this patch evolve was solving any kind of troubled. With this patch evolve --all and evolve --rev can be configured to only solve only some type of troubles (divergent, bumped or unstable). To give this choice to the user we add three new command line flags to the evolve command: --bumped, --divergent and --unstable.
README
hgext/evolve.py
tests/test-evolve-bumped.t
tests/test-evolve.t
tests/test-sharing.t
tests/test-stabilize-order.t
tests/test-stabilize-result.t
--- a/README	Fri Jun 19 13:57:16 2015 -0700
+++ b/README	Tue Jun 16 15:14:37 2015 -0700
@@ -56,6 +56,7 @@
 - evolve: gain a --rev option to control what revisions to evolve (issue4391)
 - 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
 
 5.1.5 --
 
--- 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]))
--- a/tests/test-evolve-bumped.t	Fri Jun 19 13:57:16 2015 -0700
+++ b/tests/test-evolve-bumped.t	Tue Jun 16 15:14:37 2015 -0700
@@ -72,7 +72,7 @@
   no changes found
   1 new bumped changesets
 
-  $ hg evolve -a
+  $ hg evolve -a --bumped
   recreate:[2] tweak a
   atop:[1] modify a
   computing new diff
--- a/tests/test-evolve.t	Fri Jun 19 13:57:16 2015 -0700
+++ b/tests/test-evolve.t	Tue Jun 16 15:14:37 2015 -0700
@@ -332,7 +332,7 @@
   |
   o  0	: base - test
   
-  $ hg evolve --any --traceback
+  $ hg evolve --any --traceback --bumped
   recreate:[8] another feature that rox
   atop:[7] another feature (child of ba0ec09b1bab)
   computing new diff
@@ -959,7 +959,7 @@
   |/
   o  0	: a0 - test
   
-  $ hg evolve -r 12
+  $ hg evolve -r 12 --bumped
   recreate:[12] add new file bumped
   atop:[11] a2
   computing new diff
@@ -1017,9 +1017,13 @@
 
 Evolving an empty revset should do nothing
   $ hg evolve --rev "16 and 15"
-  No troubled changes in the specified revisions
+  abort: no troubled changes in the specified revisions
+  [255]
 
-  $ hg evolve --rev "14::"
+  $ hg evolve --rev "14::" --bumped
+  abort: no troubled changes in the specified revisions
+  [255]
+  $ hg evolve --rev "14::" --unstable
   move:[15] add gg
   atop:[18] a3
   move:[16] add gh
--- a/tests/test-sharing.t	Fri Jun 19 13:57:16 2015 -0700
+++ b/tests/test-sharing.t	Tue Jun 16 15:14:37 2015 -0700
@@ -492,7 +492,7 @@
   7:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
 
 Use evolve to fix the divergence.
-  $ HGMERGE=internal:other hg evolve
+  $ HGMERGE=internal:other hg evolve --divergent
   merge:[6] fix bug 24 (v2 by bob)
   with: [7] fix bug 24 (v2 by alice)
   base: [4] fix bug 24 (v1)
--- a/tests/test-stabilize-order.t	Fri Jun 19 13:57:16 2015 -0700
+++ b/tests/test-stabilize-order.t	Tue Jun 16 15:14:37 2015 -0700
@@ -180,5 +180,5 @@
   o  0:c471ef929e6a@default(draft) addroot
   
   $ hg evolve --any -v
-  no troubled changesets
-  [1]
+  abort: no troubled changes in the specified revisions
+  [255]
--- a/tests/test-stabilize-result.t	Fri Jun 19 13:57:16 2015 -0700
+++ b/tests/test-stabilize-result.t	Tue Jun 16 15:14:37 2015 -0700
@@ -158,20 +158,20 @@
 
 Stabilize!
 
-  $ hg evolve --any --dry-run
+  $ hg evolve --any --dry-run --bumped
   recreate:[12] newer a
   atop:[8] newer a
   hg rebase --rev (73b15c7566e9|d5c7ef82d003) --dest 66719795a494; (re)
   hg update 1cf0aacfd363;
   hg revert --all --rev (73b15c7566e9|d5c7ef82d003); (re)
   hg commit --msg "bumped update to %s" (no-eol)
-  $ hg evolve --any --confirm
+  $ hg evolve --any --confirm --bumped
   recreate:[12] newer a
   atop:[8] newer a
   perform evolve? [Ny] n
   abort: evolve aborted by user
   [255]
-  $ echo y | hg evolve --any --confirm --config ui.interactive=True
+  $ echo y | hg evolve --any --confirm --config ui.interactive=True --bumped
   recreate:[12] newer a
   atop:[8] newer a
   perform evolve? [Ny] y
@@ -248,14 +248,14 @@
 
 Stabilize it
 
-  $ hg evolve -qn --confirm
+  $ hg evolve -qn --confirm --divergent
   merge:[19] More addition
   with: [17] More addition
   base: [15] More addition
   perform evolve? [Ny] n
   abort: evolve aborted by user
   [255]
-  $ echo y | hg evolve -qn --confirm --config ui.interactive=True
+  $ echo y | hg evolve -qn --confirm --config ui.interactive=True --divergent
   merge:[19] More addition
   with: [17] More addition
   base: [15] More addition
@@ -266,7 +266,7 @@
   hg up -C 3932c176bbaa &&
   hg revert --all --rev tip &&
   hg commit -m "`hg log -r eacc9c8240fe --template={desc}`";
-  $ hg evolve -v
+  $ hg evolve -v --divergent
   merge:[19] More addition
   with: [17] More addition
   base: [15] More addition
@@ -344,14 +344,14 @@
   $ hg phase 'divergent()'
   21: draft
   24: draft
-  $ hg evolve -qn
+  $ hg evolve -qn --divergent
   hg update -c 0b336205a5d0 &&
   hg merge f344982e63c4 &&
   hg commit -m "auto merge resolving conflict between 0b336205a5d0 and f344982e63c4"&&
   hg up -C 3932c176bbaa &&
   hg revert --all --rev tip &&
   hg commit -m "`hg log -r 0b336205a5d0 --template={desc}`";
-  $ hg evolve
+  $ hg evolve --divergent
   merge:[24] More addition (2)
   with: [21] More addition
   base: [15] More addition