fold: overhaul handling of revisions with --rev (BC)
authorJordi Gutiérrez Hermoso <jordigh@octave.org>
Mon, 30 Jun 2014 13:29:49 -0400
changeset 996 b98dd5d3065c
parent 995 0f3a7efd6ee9
child 997 f48cd2f48d14
fold: overhaul handling of revisions with --rev (BC) The fold command parsed the revision arguments in a very peculiar and idiosyncratic fashion: if revisions were passed without a --rev argument, then they would all be extended to ".", but if they were passed with --rev, then no extension would happen. Passing revisions both with and without --rev would abort. This is inconsistent with the way all other hg commands parse revision arguments. We have several examples of command where several revisions are passed, and the --rev option is optional for specifying those revisions (update, strip, export). This patch alters the way in which fold parses its revision arguments. No distinction is made between revisions passed with or without the --rev argument. Regardless if a single or multiple revision is specified, all will be folded together into the parent of the working directory. If the --exact argument is passed, then the parent of the working directory is ignored and the specified revisions must be a single contiguous line. The docstring and tests are modified accordingly.
hgext/evolve.py
tests/test-evolve.t
tests/test-tutorial.t
--- a/hgext/evolve.py	Mon Jun 30 10:25:08 2014 -0400
+++ b/hgext/evolve.py	Mon Jun 30 13:29:49 2014 -0400
@@ -2074,32 +2074,61 @@
         lockmod.release(lock, wlock)
 
 @command('^fold|squash',
-    [('r', 'rev', [], _("explicitly specify the full set of revision to fold")),
+    [('r', 'rev', [], _("revision to fold")),
+     ('', 'exact', None, _("only fold specified revisions"))
     ] + commitopts + commitopts2,
-    # allow to choose the seed ?
-    _('rev'))
+    _('hg fold [OPTION]... [-r] REV'))
 def fold(ui, repo, *revs, **opts):
-    """Fold multiple revisions into a single one
+    """fold multiple revisions into a single one
+
+    Folds a set of revisions with the parent of the working directory.
+    All revisions linearly between the given revisions and the parent
+    of the working directory will also be folded.
+
+    Use --exact for folding only the specified revisions while ignoring the
+    parent of the working directory. In this case, the given revisions must
+    form a linear unbroken chain.
+
+    .. container:: verbose
+
+     Some examples:
+
+     - Fold the current revision with its parent::
 
-    The revisions from your current working directory to the given one are folded
-    into a single successor revision.
+         hg fold .^
+
+     - Fold all draft revisions with working directory parent::
+
+         hg fold 'draft()'
 
-    you can alternatively use --rev to explicitly specify revisions to be folded,
-    ignoring the current working directory parent.
+       See :hg:`help phases` for more about draft revisions and
+       :hg:`help revsets` for more about the `draft()` keyword
+
+     - Fold revisions 3, 4, 5, and 6 with the working directory parent::
+
+         hg fold 3:6
+
+     - Only fold revisions linearly between foo and @::
+
+         hg fold foo::@ --exact
     """
     revs = list(revs)
-    if revs:
-        if opts.get('rev', ()):
-            raise util.Abort("cannot specify both --rev and a target revision")
-        targets = scmutil.revrange(repo, revs)
-        revs = repo.revs('(%ld::.) or (.::%ld)', targets, targets)
-    elif 'rev' in opts:
-        revs = scmutil.revrange(repo, opts['rev'])
-    else:
-        revs = ()
+    revs.extend(opts['rev'])
     if not revs:
         raise util.Abort(_('no revisions specified'))
 
+    revs = scmutil.revrange(repo, revs)
+
+    if not opts['exact']:
+        # Try to extend given revision starting from the working directory
+        extrevs = repo.revs('(%ld::.) or (.::%ld)', revs, revs)
+        discardedrevs = [r for r in revs if r not in extrevs]
+        if discardedrevs:
+            raise util.Abort(_("cannot fold non-linear revisions"),
+                               hint=_("given revisions are unrelated to parent "
+                                      "of working directory"))
+        revs = extrevs
+
     if len(revs) == 1:
         ui.write_err(_('single revision specified, nothing to fold\n'))
         return 1
--- a/tests/test-evolve.t	Mon Jun 30 10:25:08 2014 -0400
+++ b/tests/test-evolve.t	Mon Jun 30 13:29:49 2014 -0400
@@ -616,27 +616,23 @@
   $ hg fold
   abort: no revisions specified
   [255]
-  $ hg fold 6 --rev 10
-  abort: cannot specify both --rev and a target revision
-  [255]
   $ hg fold .
   single revision specified, nothing to fold
   [1]
-  $ hg fold 6 # want to run hg fold 6
-  2 changesets folded
+  $ hg fold 10 1
+  abort: cannot fold non-linear revisions
+  (given revisions are unrelated to parent of working directory)
+  [255]
+  $ hg fold -r 5
+  3 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ glog
-  @  11:dd4682c1a481@default(draft) add 1
-  |
-  o  5:0b9e50c35132@default(draft) add 3
-  |
-  o  4:ce341209337f@default(draft) add 4
-  |
-  | o  1:73d38bb17fd7@default(draft) add 1
-  |/
-  o  0:8685c6d34325@default(draft) add 0
+  $ hg fold 6 # want to run hg fold 6
+  abort: unknown revision '6'!
+  [255]
+  $ hg log -r 11 --template '{desc}\n'
+  add 3
   
-  $ hg log -r 11 --template '{desc}\n'
+  
   add 1
   
   
@@ -648,8 +644,8 @@
 
   $ hg up 4
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
-  $ hg fold --rev 4::11 --user victor
-  3 changesets folded
+  $ hg fold --rev 4::11 --user victor --exact
+  2 changesets folded
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ glog
   @  12:d26d339c513f@default(draft) add 4
@@ -680,8 +676,7 @@
 
   $ hg olog
   4	: add 4 - test
-  5	: add 3 - test
-  11	: add 1 - test
+  11	: add 3 - test
 
 Test obsstore stat
 
--- a/tests/test-tutorial.t	Mon Jun 30 10:25:08 2014 -0400
+++ b/tests/test-tutorial.t	Mon Jun 30 13:29:49 2014 -0400
@@ -473,21 +473,24 @@
 The tutorial part is not written yet but can use `hg fold`:
 
   $ hg help fold
-  hg fold rev
+  hg fold [OPTION]... [-r] REV
   
   aliases: squash
   
-  Fold multiple revisions into a single one
+  fold multiple revisions into a single one
   
-      The revisions from your current working directory to the given one are
-      folded into a single successor revision.
+      Folds a set of revisions with the parent of the working directory. All
+      revisions linearly between the given revisions and the parent of the
+      working directory will also be folded.
   
-      you can alternatively use --rev to explicitly specify revisions to be
-      folded, ignoring the current working directory parent.
+      Use --exact for folding only the specified revisions while ignoring the
+      parent of the working directory. In this case, the given revisions must
+      form a linear unbroken chain.
   
   options:
   
-   -r --rev VALUE [+] explicitly specify the full set of revision to fold
+   -r --rev VALUE [+] revision to fold
+      --exact         only fold specified revisions
    -m --message TEXT  use text as commit message
    -l --logfile FILE  read commit message from file
    -d --date DATE     record the specified date as commit date
@@ -495,7 +498,7 @@
   
   [+] marked option can be specified multiple times
   
-  use "hg -v help fold" to show the global options
+  use "hg -v help fold" to show more complete help and the global options
 
 
 -----------------------