Patchwork [STABLE] hook: protect commit hooks against stripping of temporary commit (issue4422)

login
register
mail settings
Submitter Pierre-Yves David
Date Nov. 1, 2014, 11:37 p.m.
Message ID <cc57f4132091ab129259.1414885045@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/6514/
State Accepted
Headers show

Comments

Pierre-Yves David - Nov. 1, 2014, 11:37 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1414883870 0
#      Sat Nov 01 23:17:50 2014 +0000
# Branch stable
# Node ID cc57f4132091ab1292593f1803b56cbfc1a817d9
# Parent  2ad893298ac110ef52af5823dfb567af8a8d9eef
hook: protect commit hooks against stripping of temporary commit (issue4422)

History rewriting commands like histedit tend to use temporary commit. This may
schedule hooks execution on these temporary commit for after the lock have been
released. But temporary commit are likely to have been stripped before the lock
is released (and the hook run). Hook executed for missing revision leads to
various crashes.

We disable hooks execution for revision missing in the repo. This provide a dirty
but simple fix to user issues.
Matt Mackall - Nov. 1, 2014, 11:40 p.m.
On Sat, 2014-11-01 at 23:37 +0000, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1414883870 0
> #      Sat Nov 01 23:17:50 2014 +0000
> # Branch stable
> # Node ID cc57f4132091ab1292593f1803b56cbfc1a817d9
> # Parent  2ad893298ac110ef52af5823dfb567af8a8d9eef
> hook: protect commit hooks against stripping of temporary commit (issue4422)

Nice and simple, queued for stable, thanks.

Patch

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1368,11 +1368,15 @@  class localrepository(object):
             ms.reset()
         finally:
             wlock.release()
 
         def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
-            self.hook("commit", node=node, parent1=parent1, parent2=parent2)
+            # hack for command that use a temporary commit (eg: histedit)
+            # temporary commit got stripped before hook release
+            if node in self:
+                self.hook("commit", node=node, parent1=parent1,
+                          parent2=parent2)
         self._afterlock(commithook)
         return ret
 
     @unfilteredmethod
     def commitctx(self, ctx, error=False):
diff --git a/tests/test-histedit-fold.t b/tests/test-histedit-fold.t
--- a/tests/test-histedit-fold.t
+++ b/tests/test-histedit-fold.t
@@ -444,5 +444,47 @@  Folding with initial rename (issue3729)
   $ hg logt --follow b.txt
   1:cf858d235c76 rename
   0:6c795aa153cb a
 
   $ cd ..
+
+Folding with swapping
+---------------------
+
+This is an excuse to test hook with histedit temporary commit (issue4422)
+
+
+  $ hg init issue4422
+  $ cd issue4422
+  $ echo a > a.txt
+  $ hg add a.txt
+  $ hg commit -m a
+  $ echo b > b.txt
+  $ hg add b.txt
+  $ hg commit -m b
+  $ echo c > c.txt
+  $ hg add c.txt
+  $ hg commit -m c
+
+  $ hg logt
+  2:a1a953ffb4b0 c
+  1:199b6bb90248 b
+  0:6c795aa153cb a
+
+  $ hg histedit 6c795aa153cb --config hooks.commit="echo commit \$HG_NODE" --commands - 2>&1 << EOF | fixbundle
+  > pick 199b6bb90248 b
+  > fold a1a953ffb4b0 c
+  > pick 6c795aa153cb a
+  > EOF
+  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  2 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
+  commit 9599899f62c05f4377548c32bf1c9f1a39634b0c
+
+  $ hg logt
+  1:9599899f62c0 a
+  0:79b99e9c8e49 b
+
+  $ cd ..