[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