[PATCH 2 of 2 v2] histedit: add 'x'/'exec' verb

David Soria Parra davidsp at fb.com
Tue Sep 16 19:58:40 CDT 2014


# HG changeset patch
# User David Soria Parra <davidsp at fb.com>
# Date 1410900110 25200
#      Tue Sep 16 13:41:50 2014 -0700
# Node ID b37ac883fe2d267fdbff2fbfc72477738493531c
# Parent  d4e975e2707a0ea606c22ed472d56fab4fda7ae2
histedit: add 'x'/'exec' verb

Add the 'x'/'exec' verb to execute a command. As exec lives in it's own line
and doesn't have a changeset attached to but applies to the previous changeset,
we have add some special handling. In particular when we restore we don't want
to execute the command again.

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -429,7 +429,11 @@
         raise error.InterventionRequired(
             _('Working copy dirty, please check the files listed above.\n'
               'When you are finished, run hg histedit --continue to resume.'))
-    return ctx, []
+
+    newctx = repo['.']
+    if ctx.node() != newctx.node():
+        return newctx, [(ctx.node(), (newctx.node(),))]
+    return newctx, []
 
 def message(ui, repo, ctx, ha, opts):
     oldctx = repo[ha]
@@ -486,6 +490,8 @@
                'drop': drop,
                'm': message,
                'mess': message,
+               'x': execute,
+               'exec': execute,
                }
 
 @command('histedit',
@@ -707,7 +713,14 @@
 
 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
     action, currentnode = rules.pop(0)
-    ctx = repo[currentnode]
+    if action in ['x', 'exec']:
+        action, currentnode = rules.pop(0)
+        # ensure we jump to the next node after an exec
+        if action not in ['x', 'exec']:
+            ctx = repo[currentnode]
+            hg.update(repo, ctx.node())
+    else:
+        ctx = repo[currentnode]
 
     newchildren = gatherchildren(repo, parentctx)
 
@@ -825,20 +838,23 @@
         if ' ' not in r:
             raise util.Abort(_('malformed line "%s"') % r)
         action, rest = r.split(' ', 1)
-        ha = rest.strip().split(' ', 1)[0]
-        try:
-            ha = str(repo[ha])  # ensure its a short hash
-        except error.RepoError:
-            raise util.Abort(_('unknown changeset %s listed') % ha)
-        if ha not in expected:
-            raise util.Abort(
-                _('may not use changesets other than the ones listed'))
-        if ha in seen:
-            raise util.Abort(_('duplicated command for changeset %s') % ha)
-        seen.add(ha)
-        if action not in actiontable:
-            raise util.Abort(_('unknown action "%s"') % action)
-        parsed.append([action, ha])
+        if action in ['x', 'exec']:
+            parsed.append([action, rest])
+        else:
+            ha = rest.strip().split(' ', 1)[0]
+            try:
+                ha = str(repo[ha])  # ensure its a short hash
+            except error.RepoError:
+                raise util.Abort(_('unknown changeset %s listed') % ha)
+            if ha not in expected:
+                raise util.Abort(
+                    _('may not use changesets other than the ones listed'))
+            if ha in seen:
+                raise util.Abort(_('duplicated command for changeset %s') % ha)
+            seen.add(ha)
+            if action not in actiontable:
+                raise util.Abort(_('unknown action "%s"') % action)
+            parsed.append([action, ha])
     missing = sorted(expected - seen)  # sort to stabilize output
     if missing:
         raise util.Abort(_('missing rules for changeset %s') % missing[0],
diff --git a/tests/test-histedit-exec.t b/tests/test-histedit-exec.t
new file mode 100644
--- /dev/null
+++ b/tests/test-histedit-exec.t
@@ -0,0 +1,191 @@
+  $ . "$TESTDIR/histedit-helpers.sh"
+
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > histedit=
+  > EOF
+
+  $ initrepo ()
+  > {
+  >     hg init r
+  >     cd r
+  >     for x in a b c d e f ; do
+  >         echo $x > $x
+  >         hg add $x
+  >         hg ci -m $x
+  >     done
+  > }
+
+  $ initrepo
+
+log before edit
+
+  $ hg log --graph
+  @  changeset:   5:652413bf663e
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     f
+  |
+  o  changeset:   4:e860deea161a
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     e
+  |
+  o  changeset:   3:055a42cdd887
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     d
+  |
+  o  changeset:   2:177f92b77385
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     c
+  |
+  o  changeset:   1:d2ae7f538514
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:cb9a9f314b8b
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+
+exec & continue should preserve hashes
+
+  $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
+  > pick 177f92b77385 c
+  > pick 055a42cdd887 d
+  > pick e860deea161a e
+  > exec echo "this should be printed to stdout"
+  > exec echo "this should be printed to stderr" >&2
+  > pick 652413bf663e f
+  > EOF
+  this should be printed to stdout
+  this should be printed to stderr
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg log --graph
+  @  changeset:   5:652413bf663e
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     f
+  |
+  o  changeset:   4:e860deea161a
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     e
+  |
+  o  changeset:   3:055a42cdd887
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     d
+  |
+  o  changeset:   2:177f92b77385
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     c
+  |
+  o  changeset:   1:d2ae7f538514
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:cb9a9f314b8b
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+ensure we are properly executed in a shell
+  $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
+  > pick 177f92b77385 c
+  > pick 055a42cdd887 d
+  > pick e860deea161a e
+  > exec echo "foo" >/dev/null && exit 0
+  > pick 652413bf663e f
+  > EOF
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+a failing command should drop us into the shell
+
+  $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
+  > pick 177f92b77385 c
+  > pick 055a42cdd887 d
+  > pick e860deea161a e
+  > exec exit 1
+  > pick 652413bf663e f
+  > EOF
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  Command 'exit 1' failed with exit status 1.
+
+continue should work
+
+  $ hg histedit --continue
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg log --template '{node|short} {desc}' --graph
+  @  652413bf663e f
+  |
+  o  e860deea161a e
+  |
+  o  055a42cdd887 d
+  |
+  o  177f92b77385 c
+  |
+  o  d2ae7f538514 b
+  |
+  o  cb9a9f314b8b a
+  
+
+abort should work
+
+  $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
+  > pick 177f92b77385 c
+  > pick 055a42cdd887 d
+  > pick e860deea161a e
+  > exec exit 1
+  > pick 652413bf663e f
+  > EOF
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  Command 'exit 1' failed with exit status 1.
+
+  $ hg histedit --abort
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg log --template '{node|short} {desc}' --graph
+  @  652413bf663e f
+  |
+  o  e860deea161a e
+  |
+  o  055a42cdd887 d
+  |
+  o  177f92b77385 c
+  |
+  o  d2ae7f538514 b
+  |
+  o  cb9a9f314b8b a
+  
+
+abort on a failing command, e.g when we have children
+
+
+  $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
+  > pick 177f92b77385 c
+  > pick 055a42cdd887 d
+  > pick e860deea161a e
+  > exec echo 'added' > added && hg addremove && hg commit --amend
+  > pick 652413bf663e f
+  > EOF
+  abort: cannot amend changeset with children
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+  $ hg id -r . -i
+  e860deea161a
+


More information about the Mercurial-devel mailing list