[PATCH 2 of 4 RFC] hook: have a generic hook after transaction have been closed

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Mar 10 03:07:14 CDT 2015


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1425965816 25200
#      Mon Mar 09 22:36:56 2015 -0700
# Node ID b9b9d81a2ad56ca8951ed8c11c06bc965164120a
# Parent  82dea52f27319896a8d33a0b805f439107a94845
hook: have a generic hook after transaction have been closed

We are adding generic hooking for all transaction. We may have useful
information about what append during the transaction, user of the transaction
should have filled the 'hookargs' parameter of the transaction. This hook is
simple because he has to power to abort the transaction.

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -810,10 +810,21 @@ variables it is passed are listed with n
 
 ``txnopen``
   Run before any new repository transaction is open. Reason for the transaction
   opening will be in ``$HG_TXNNAME``. This hook can abort transaction opening.
 
+``txnclosing``
+  Run right before that transaction is actually commited for good. Any
+  repository change will be visible to the hook program. This lets you validate
+  the transaction content or changes it. Exit status 0 allows the commit to
+  proceed. Non-zero status will cause the transaction to be rolled back. Reason
+  for the transaction opening will be in ``$HG_TXNNAME``. The rest of the
+  available data will vary according the event who append during the
+  transaction. New changesets will add ``$HG_NODE`` (id of the first added
+  changesets, ``$HG_URL`` and ``$HG_SOURCE`` variables, bookmark and phases
+  changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc
+
 ``pretxnchangegroup``
   Run after a changegroup has been added via push, pull or unbundle,
   but before the transaction has been committed. Changegroup is
   visible to hook program. This lets you validate incoming changes
   before accepting them. Passed the ID of the first new changeset in
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -921,10 +921,20 @@ class localrepository(object):
                                      self.store.createmode)
         # note: writing the fncache only during finalize mean that the file is
         # outdated when running hooks. As fncache is used for streaming clone,
         # this is not expected to break anything that happen during the hooks.
         tr.addfinalize('flush-fncache', self.store.write)
+        # we must avoid cyclic reference between repo and transaction.
+        reporef = weakref.ref(self)
+        def txnclosedhook(tr2):
+            """To be run if transaction is successful, will schedule a hook run
+            """
+            def hook():
+                reporef().hook('txnclosed', throw=False, txnname=desc,
+                               **tr2.hookargs)
+            reporef()._afterlock(hook)
+        tr.addfinalize('txnclosed-hook', txnclosedhook)
         self._transref = weakref.ref(tr)
         return tr
 
     def _journalfiles(self):
         return ((self.svfs, 'journal'),
diff --git a/tests/test-hook.t b/tests/test-hook.t
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -11,18 +11,20 @@ commit hooks can see env vars
   > pretxncommit.tip = hg -q tip
   > pre-identify = python "$TESTDIR/printenv.py" pre-identify 1
   > pre-cat = python "$TESTDIR/printenv.py" pre-cat
   > post-cat = python "$TESTDIR/printenv.py" post-cat
   > txnopen = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" txnopen"
+  > txnclosed = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" txnclosed"
   > EOF
   $ echo a > a
   $ hg add a
   $ hg commit -m a
   precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
   txnopen hook: HG_TXNNAME=commit
   pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
   0:cb9a9f314b8b
+  txnclosed hook: HG_PHASES_MOVED=1 HG_TXNNAME=commit
   commit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
   commit.b hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
 
   $ hg clone . ../b
   updating to branch default
@@ -45,10 +47,11 @@ pretxncommit and commit hooks can see bo
   $ hg commit -m a1 -d "1 0"
   precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
   txnopen hook: HG_TXNNAME=commit
   pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
   1:ab228980c14d
+  txnclosed hook: HG_TXNNAME=commit
   commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
   commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
   $ hg update -C 0
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo b > b
@@ -56,10 +59,11 @@ pretxncommit and commit hooks can see bo
   $ hg commit -m b -d '1 0'
   precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
   txnopen hook: HG_TXNNAME=commit
   pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
   2:ee9deb46ab31
+  txnclosed hook: HG_TXNNAME=commit
   commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
   commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
   created new head
   $ hg merge 1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -67,10 +71,11 @@ pretxncommit and commit hooks can see bo
   $ hg commit -m merge -d '2 0'
   precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
   txnopen hook: HG_TXNNAME=commit
   pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
   3:07f3376c1e65
+  txnclosed hook: HG_TXNNAME=commit
   commit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
   commit.b hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
 
 test generic hooks
 
@@ -110,10 +115,11 @@ tag hooks can see env vars
   precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
   txnopen hook: HG_TXNNAME=commit
   pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
   4:539e4b31b6dc
   tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
+  txnclosed hook: HG_TXNNAME=commit
   commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
   commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
   $ hg tag -l la
   pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
   tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
@@ -204,10 +210,11 @@ pushkey hook
   $ hg push -B foo ../a
   pushing to ../a
   searching for changes
   no changes found
   txnopen hook: HG_TXNNAME=bookmarks
+  txnclosed hook: HG_BOOKMARK_MOVED=1 HG_TXNNAME=bookmarks
   pushkey hook: HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1
   exporting bookmark foo
   [1]
   $ cd ../a
 


More information about the Mercurial-devel mailing list