[PATCH V2] histedit: add support for exec/x command to histedit (issue4036)

liscju piotr.listkiewicz at gmail.com
Sat Oct 24 16:09:22 UTC 2015


# HG changeset patch
# User liscju <piotr.listkiewicz at gmail.com>
# Date 1442157106 -7200
#      Sun Sep 13 17:11:46 2015 +0200
# Node ID 6f4d4635d6ac7c1af24c707f3f915c663b645727
# Parent  58a309e9cf80d74d96e8c56cb95be20a4b130092
histedit: add support for exec/x command to histedit (issue4036)

Point of this command is to be able to do some automatic munging
on one or several commits in a series.

The basic contract is that it receives a clean working copy and is
expected to leave a clean working copy if it exits 0. If either
the command leaves the working copy dirty, or it exits non-zero,
the histedit stops to give opportunity for user intervention.

Exec command functionality is implemented in execute class. It is
overriding fromrule class method to deal with initializing
object in different way than other histeditactions. It takes
state and cmd instead of state and node id of next changeset
action to perform on.

Run method of exec_ class at first updates to parent of current
changeset,apply it and commit to obtain copy of current changeset
in current directory. It is done to let cmd amend to this changeset
and correctly perform changing history containing this changeset.

In run method locks are released right before running command to
allow running hg commands inside it. Acquiring proper number of
locks is done in finally block in histedit.py:544-545 line, by
default repo.lock and repo.wlock wait forever for acquiring
them.

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -40,6 +40,9 @@
  #  d, drop = remove commit from history
  #  m, mess = edit commit message without changing commit content
  #
+ #  Between changes you can add this:
+ #  x, exec = run command (the rest of the line) using shell
+ #
 
 In this file, lines beginning with ``#`` are ignored. You must specify a rule
 for each revision in your history. For example, if you had meant to add gamma
@@ -62,6 +65,9 @@
  #  d, drop = remove commit from history
  #  m, mess = edit commit message without changing commit content
  #
+ #  Between changes you can add this:
+ #  x, exec = run command (the rest of the line) using shell
+ #
 
 At which point you close the editor and ``histedit`` starts working. When you
 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
@@ -200,6 +206,9 @@
 #  d, drop = remove commit from history
 #  m, mess = edit commit message without changing commit content
 #
+#  Between changes you can add this:
+#  x, exec = run command (the rest of the line) using shell
+#
 """)
 
 class histeditstate(object):
@@ -502,6 +511,79 @@
                          editor=editor)
     return repo.commitctx(new)
 
+def _isdirtywc(repo):
+    s = repo.status()
+    return s.modified or s.added or s.removed or s.deleted
+
+class execute(histeditaction):
+    def __init__(self, state, cmd):
+        self.state = state
+        self.cmd = cmd
+
+    @classmethod
+    def fromrule(cls, state, cmd):
+        return cls(state, cmd)
+
+    def run(self):
+        repo = self.state.repo
+        node = self.state.parentctxnode
+
+        hg.update(repo, repo[node].parents()[0])
+        applychanges(repo.ui, repo, repo[node], {})
+        self._commit()
+
+        lockheld = self.state.lock.releaseall()
+        wlockheld = self.state.wlock.releaseall()
+        try:
+            return_code = repo.ui.system(self.cmd, cwd=repo.root)
+        except OSError:
+            raise error.InterventionRequired(
+                self._getinterventionmsg(
+                    _('Execution of "%s" failed.') % self.cmd))
+        finally:
+            self.state.wlock = repo.wlock(times=wlockheld)
+            self.state.lock = repo.lock(times=lockheld)
+
+        if return_code == 0:
+            if _isdirtywc(repo):
+                raise error.InterventionRequired(
+                    self._getinterventionmsg(
+                        _('Working copy dirty after exec "%s".') % self.cmd))
+            else:
+                return self.continueclean()
+        else:
+            raise error.InterventionRequired(
+                self._getinterventionmsg(
+                    _('Return code of "%s" is %d (expected zero).')
+                    % (self.cmd, return_code)))
+
+    def continuedirty(self):
+        raise error.InterventionRequired(
+            self._getinterventionmsg(
+                _('Working copy dirty after exec "%s".') % self.cmd))
+
+    def continueclean(self):
+        ctx = self.state.repo['.']
+        node = self.state.parentctxnode
+        return ctx, [(node, (ctx.node(),))]
+
+    def _commit(self):
+        repo = self.state.repo
+        node = self.state.parentctxnode
+        rulectx = repo[node]
+
+        editor = self.commiteditor()
+        commit = commitfuncfor(repo, rulectx)
+
+        commit(text=rulectx.description(), user=rulectx.user(),
+               date=rulectx.date(), extra=rulectx.extra(), editor=editor)
+
+    def _getinterventionmsg(self, errormsg):
+        return _(errormsg + "\n" +
+              'Make changes as needed, you may commit or record as needed '
+              'now.\nWhen you are finished, run hg histedit --continue to '
+              'resume.')
+
 class pick(histeditaction):
     def run(self):
         rulectx = self.repo[self.node]
@@ -685,6 +767,8 @@
                'drop': drop,
                'm': message,
                'mess': message,
+               'x': execute,
+               'exec': execute,
                }
 
 @command('histedit',
@@ -971,12 +1055,10 @@
 
         actobj = actiontable[action].fromrule(state, currentnode)
 
-        s = repo.status()
-        if s.modified or s.added or s.removed or s.deleted:
+        if _isdirtywc(repo):
             actobj.continuedirty()
-            s = repo.status()
-            if s.modified or s.added or s.removed or s.deleted:
-                raise error.Abort(_("working copy still dirty"))
+            if _isdirtywc(repo):
+                raise util.Abort(_("working copy still dirty"))
 
         parentctx, replacements = actobj.continueclean()
 
@@ -1051,21 +1133,26 @@
         if ' ' not in r:
             raise error.Abort(_('malformed line "%s"') % r)
         action, rest = r.split(' ', 1)
-        ha = rest.strip().split(' ', 1)[0]
-        try:
-            ha = repo[ha].hex()
-        except error.RepoError:
-            raise error.Abort(_('unknown changeset %s listed') % ha[:12])
-        if ha not in expected:
-            raise error.Abort(
-                _('may not use changesets other than the ones listed'))
-        if ha in seen:
-            raise error.Abort(_('duplicated command for changeset %s') %
-                    ha[:12])
-        seen.add(ha)
-        if action not in actiontable or action.startswith('_'):
-            raise error.Abort(_('unknown action "%s"') % action)
-        parsed.append([action, ha])
+
+        if action == "x" or action == "exec":
+            parsed.append([action, rest])
+        else:
+            ha = rest.strip().split(' ', 1)[0]
+            try:
+                ha = repo[ha].hex()
+            except error.RepoError:
+                raise util.Abort(_('unknown changeset %s listed') % ha[:12])
+            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[:12])
+            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 error.Abort(_('missing rules for changeset %s') %
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1234,7 +1234,7 @@
             ce.refresh()
 
     def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc,
-              inheritchecker=None, parentenvvar=None):
+              inheritchecker=None, parentenvvar=None, times=1):
         parentlock = None
         # the contents of parentenvvar are used by the underlying lock to
         # determine whether it can be inherited
@@ -1244,7 +1244,7 @@
             l = lockmod.lock(vfs, lockname, 0, releasefn=releasefn,
                              acquirefn=acquirefn, desc=desc,
                              inheritchecker=inheritchecker,
-                             parentlock=parentlock)
+                             parentlock=parentlock, times=times)
         except error.LockHeld as inst:
             if not wait:
                 raise
@@ -1254,7 +1254,7 @@
             l = lockmod.lock(vfs, lockname,
                              int(self.ui.config("ui", "timeout", "600")),
                              releasefn=releasefn, acquirefn=acquirefn,
-                             desc=desc)
+                             desc=desc, times=times)
             self.ui.warn(_("got lock after %s seconds\n") % l.delay)
         return l
 
@@ -1271,7 +1271,7 @@
         else: # no lock have been found.
             callback()
 
-    def lock(self, wait=True):
+    def lock(self, wait=True, times=1):
         '''Lock the repository store (.hg/store) and return a weak reference
         to the lock. Use this before modifying the store (e.g. committing or
         stripping). If you are opening a transaction, get a lock as well.)
@@ -1280,11 +1280,11 @@
         'wlock' first to avoid a dead-lock hazard.'''
         l = self._lockref and self._lockref()
         if l is not None and l.held:
-            l.lock()
+            l.lock(times)
             return l
 
         l = self._lock(self.svfs, "lock", wait, None,
-                       self.invalidate, _('repository %s') % self.origroot)
+                       self.invalidate, _('repository %s') % self.origroot, times=times)
         self._lockref = weakref.ref(l)
         return l
 
@@ -1293,7 +1293,7 @@
             raise error.LockInheritanceContractViolation(
                 'wlock cannot be inherited in the middle of a transaction')
 
-    def wlock(self, wait=True):
+    def wlock(self, wait=True, times=1):
         '''Lock the non-store parts of the repository (everything under
         .hg except .hg/store) and return a weak reference to the lock.
 
@@ -1303,7 +1303,7 @@
         'wlock' first to avoid a dead-lock hazard.'''
         l = self._wlockref and self._wlockref()
         if l is not None and l.held:
-            l.lock()
+            l.lock(times)
             return l
 
         # We do not need to check for non-waiting lock acquisition.  Such
@@ -1326,7 +1326,7 @@
                        self.invalidatedirstate, _('working directory of %s') %
                        self.origroot,
                        inheritchecker=self._wlockchecktransaction,
-                       parentenvvar='HG_WLOCK_LOCKER')
+                       parentenvvar='HG_WLOCK_LOCKER', times=times)
         self._wlockref = weakref.ref(l)
         return l
 
diff --git a/mercurial/lock.py b/mercurial/lock.py
--- a/mercurial/lock.py
+++ b/mercurial/lock.py
@@ -40,7 +40,7 @@
     _host = None
 
     def __init__(self, vfs, file, timeout=-1, releasefn=None, acquirefn=None,
-                 desc=None, inheritchecker=None, parentlock=None):
+                 desc=None, inheritchecker=None, parentlock=None, times=1):
         self.vfs = vfs
         self.f = file
         self.held = 0
@@ -54,7 +54,7 @@
         self._inherited = False
         self.postrelease  = []
         self.pid = self._getpid()
-        self.delay = self.lock()
+        self.delay = self.lock(times)
         if self.acquirefn:
             self.acquirefn()
 
@@ -74,11 +74,11 @@
         # wrapper around os.getpid() to make testing easier
         return os.getpid()
 
-    def lock(self):
+    def lock(self, times=1):
         timeout = self.timeout
         while True:
             try:
-                self._trylock()
+                self._trylock(times)
                 return self.timeout - timeout
             except error.LockHeld as inst:
                 if timeout != 0:
@@ -89,9 +89,9 @@
                 raise error.LockHeld(errno.ETIMEDOUT, inst.filename, self.desc,
                                      inst.locker)
 
-    def _trylock(self):
+    def _trylock(self, times=1):
         if self.held:
-            self.held += 1
+            self.held += times
             return
         if lock._host is None:
             lock._host = socket.gethostname()
@@ -101,7 +101,7 @@
             retry -= 1
             try:
                 self.vfs.makelock(lockname, self.f)
-                self.held = 1
+                self.held = times
             except (OSError, IOError) as why:
                 if why.errno == errno.EEXIST:
                     locker = self._readlock()
@@ -111,7 +111,7 @@
                     # but the lockfile to not be removed.
                     if locker == self.parentlock:
                         self._parentheld = True
-                        self.held = 1
+                        self.held = times
                         return
                     locker = self._testlock(locker)
                     if locker is not None:
@@ -203,6 +203,12 @@
                 self.acquirefn()
             self._inherited = False
 
+    def releaseall(self):
+        origheld = self.held
+        while self.held > 0:
+            self.release()
+        return origheld
+
     def release(self):
         """release the lock and execute callback function if any
 
diff --git a/tests/test-histedit-arguments.t b/tests/test-histedit-arguments.t
--- a/tests/test-histedit-arguments.t
+++ b/tests/test-histedit-arguments.t
@@ -71,6 +71,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Run on a revision not ancestors of the current working directory.
@@ -295,6 +298,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Test --continue with --keep
diff --git a/tests/test-histedit-bookmark-motion.t b/tests/test-histedit-bookmark-motion.t
--- a/tests/test-histedit-bookmark-motion.t
+++ b/tests/test-histedit-bookmark-motion.t
@@ -77,6 +77,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg histedit 1 --commands - --verbose << EOF | grep histedit
   > pick 177f92b77385 2 c
@@ -138,6 +141,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg histedit 1 --commands - --verbose << EOF | grep histedit
   > pick b346ab9a313d 1 c
diff --git a/tests/test-histedit-commute.t b/tests/test-histedit-commute.t
--- a/tests/test-histedit-commute.t
+++ b/tests/test-histedit-commute.t
@@ -71,6 +71,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 edit the history
@@ -349,6 +352,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 should also work if a commit message is missing
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,242 @@
+  $ . "$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 g; do
+  >         echo $x > $x
+  >         hg add $x
+  >         hg ci -m $x
+  >     done
+  > }
+
+  $ initrepo
+
+log before exec
+  $ hg log --graph
+  @  changeset:   6:3c6a8ed2ebe8
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     g
+  |
+  o  changeset:   5:652413bf663e
+  |  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 echo "Hello World" on directory after picking last changeset
+  $ hg histedit 6 --commands - 2>&1 << EOF
+  > pick 6
+  > exec echo "Hello World"
+  > EOF
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  adding g
+  Hello World
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/r/.hg/strip-backup/3c6a8ed2ebe8-f7abffd4-backup.hg (glob)
+
+exec ls after revision 1
+  $ hg histedit 1 --commands - 2>&1 << EOF
+  > pick 1
+  > exec echo "ls output start:" && ls && echo "ls output ends"
+  > pick 2
+  > pick 3
+  > pick 4
+  > pick 5
+  > pick 6
+  > EOF
+  0 files updated, 0 files merged, 6 files removed, 0 files unresolved
+  adding b
+  ls output start:
+  a
+  b
+  ls output ends
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-1c1cf14d-backup.hg (glob)
+
+
+exec adding b1 file in revision 1
+  $ hg histedit 1 --commands - 2>&1 << EOF
+  > pick 1
+  > exec echo b1 >> b1 && hg add b1 && hg commit --amend -m "b1"
+  > pick 2
+  > pick 3
+  > pick 4
+  > pick 5
+  > pick 6
+  > EOF
+  0 files updated, 0 files merged, 6 files removed, 0 files unresolved
+  adding b
+  saved backup bundle to $TESTTMP/r/.hg/strip-backup/18a73c9c72cf-c8c1f3b6-amend-backup.hg (glob)
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/r/.hg/strip-backup/0808241031aa-aa7f6930-backup.hg (glob)
+
+  $ hg log --graph
+  @  changeset:   6:4696a3362537
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     g
+  |
+  o  changeset:   5:401045adec09
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     f
+  |
+  o  changeset:   4:e450e0e843f7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     e
+  |
+  o  changeset:   3:dcf604978dad
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     d
+  |
+  o  changeset:   2:e6d5272deb83
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     c
+  |
+  o  changeset:   1:887fd832d217
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b1
+  |
+  o  changeset:   0:cb9a9f314b8b
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+  $ hg log -f b -f b1
+  changeset:   1:887fd832d217
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b1
+  
+exec creating new file f1 after changeset 5 leaving working dir dirty
+  $ hg histedit 5 --commands - 2>&1 << EOF
+  > pick 5
+  > exec echo "f1" >> f
+  > pick 6
+  > EOF
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  adding f
+  Working copy dirty after exec "echo "f1" >> f".
+  Make changes as needed, you may commit or record as needed now.
+  When you are finished, run hg histedit --continue to resume.
+  [1]
+
+try to continue while working directory is dirty
+  $ hg histedit --continue
+  Working copy dirty after exec "echo "f1" >> f".
+  Make changes as needed, you may commit or record as needed now.
+  When you are finished, run hg histedit --continue to resume.
+  [1]
+
+  $ hg commit -m "f1"
+  $ hg histedit --continue
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/r/.hg/strip-backup/401045adec09-e5efc200-backup.hg (glob)
+
+  $ hg log --graph -r 5:
+  @  changeset:   7:037517e744e6
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     g
+  |
+  o  changeset:   6:bd6d5e3cbcf3
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     f1
+  |
+  o  changeset:   5:06ff77bf2665
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     f
+  |
+
+  $ hg log -f f
+  changeset:   6:bd6d5e3cbcf3
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     f1
+  
+  changeset:   5:06ff77bf2665
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     f
+  
+exec when command returns non zero value  
+  $ hg histedit 7 --commands - 2>&1 << EOF
+  > exec exit 1
+  > pick 7
+  > EOF
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  reverting f
+  Return code of "exit 1" is 1 (expected zero).
+  Make changes as needed, you may commit or record as needed now.
+  When you are finished, run hg histedit --continue to resume.
+  [1]
+
+  $ hg histedit --continue
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/r/.hg/strip-backup/bd6d5e3cbcf3-8113adfc-backup.hg (glob)
+
+  $ hg log --graph -r 6:
+  @  changeset:   7:d994db4c657b
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     g
+  |
+  o  changeset:   6:41b4840c21f7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     f1
+  |
diff --git a/tests/test-histedit-obsolete.t b/tests/test-histedit-obsolete.t
--- a/tests/test-histedit-obsolete.t
+++ b/tests/test-histedit-obsolete.t
@@ -56,6 +56,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
   > pick 177f92b77385 2 c
diff --git a/tests/test-histedit-outgoing.t b/tests/test-histedit-outgoing.t
--- a/tests/test-histedit-outgoing.t
+++ b/tests/test-histedit-outgoing.t
@@ -53,6 +53,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd ..
 
@@ -85,6 +88,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd ..
 
@@ -109,6 +115,9 @@
   #  d, drop = remove commit from history
   #  m, mess = edit commit message without changing commit content
   #
+  #  Between changes you can add this:
+  #  x, exec = run command (the rest of the line) using shell
+  #
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 test to check number of roots in outgoing revisions


More information about the Mercurial-devel mailing list