hook: add a generic hook right before we commit a transaction
We are adding a 'txnclose' hook that will be run right before a transaction is
closed. Hooks running at that time will have access to the full transaction
content through both 'hookargs' content and on-disk reading. They will be able
to abort the transaction.
--- a/mercurial/help/config.txt Mon Mar 09 22:43:36 2015 -0700
+++ b/mercurial/help/config.txt Mon Mar 09 22:50:49 2015 -0700
@@ -813,15 +813,23 @@
transaction will be in ``$HG_TXNNAME``. A non-zero status will
prevent the transaction from being opened.
+``pretxnclose``
+ Run right before the transaction is actually finalized. Any
+ repository change will be visible to the hook program. This lets you
+ validate the transaction content or change it. Exit status 0 allows
+ the commit to proceed. Non-zero status will cause the transaction to
+ be rolled back. The reason for the transaction opening will be in
+ ``$HG_TXNNAME``. The rest of the available data will vary according
+ the transaction type. New changesets will add
+ ``$HG_NODE`` (id of the first added changeset), ``$HG_URL`` and
+ ``$HG_SOURCE`` variables, bookmarks and phases changes will set
+ ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc.
+
``txnclose``
Run after any repository transaction has been commited. At this
point, the transaction can no longer be rolled back. The hook will run
- after the lock is released. The reason for the transaction will
- be in ``$HG_TXNNAME``. The rest of the available data will vary
- according the event that happened during the transaction. New changesets
- will add ``$HG_NODE`` (id of the first added changeset), ``$HG_URL``
- and ``$HG_SOURCE`` variables, bookmarks and phases changes will set
- ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc.
+ after the lock is released. see ``pretxnclose`` docs for details about
+ available variables.
``pretxnchangegroup``
Run after a changegroup has been added via push, pull or unbundle,
--- a/mercurial/localrepo.py Mon Mar 09 22:43:36 2015 -0700
+++ b/mercurial/localrepo.py Mon Mar 09 22:50:49 2015 -0700
@@ -915,17 +915,24 @@
renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
rp = report and report or self.ui.warn
vfsmap = {'plain': self.vfs} # root of .hg/
- tr = transaction.transaction(rp, self.svfs, vfsmap,
+ # we must avoid cyclic reference between repo and transaction.
+ reporef = weakref.ref(self)
+ def validate(tr):
+ """will run pre-closing hooks"""
+ pending = lambda: tr.writepending() and self.root or ""
+ reporef().hook('pretxnclose', throw=True, pending=pending,
+ xnname=desc)
+
+ tr = transaction.transaction(rp, self.sopener, vfsmap,
"journal",
"undo",
aftertrans(renames),
- self.store.createmode)
+ self.store.createmode,
+ validator=validate)
# 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 txnclosehook(tr2):
"""To be run if transaction is successful, will schedule a hook run
"""
--- a/tests/test-hook.t Mon Mar 09 22:43:36 2015 -0700
+++ b/tests/test-hook.t Mon Mar 09 22:50:49 2015 -0700
@@ -13,6 +13,7 @@
> pre-cat = python "$TESTDIR/printenv.py" pre-cat
> post-cat = python "$TESTDIR/printenv.py" post-cat
> pretxnopen = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" pretxnopen"
+ > pretxnclose = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" pretxnclose"
> txnclose = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" txnclose"
> EOF
$ echo a > a
@@ -22,6 +23,7 @@
pretxnopen hook: HG_TXNNAME=commit
pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
0:cb9a9f314b8b
+ pretxnclose hook: HG_PENDING=$TESTTMP/a HG_XNNAME=commit
txnclose 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
@@ -49,6 +51,7 @@
pretxnopen hook: HG_TXNNAME=commit
pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
1:ab228980c14d
+ pretxnclose hook: HG_PENDING=$TESTTMP/a HG_XNNAME=commit
txnclose hook: HG_TXNNAME=commit
commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
@@ -61,6 +64,7 @@
pretxnopen hook: HG_TXNNAME=commit
pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
2:ee9deb46ab31
+ pretxnclose hook: HG_PENDING=$TESTTMP/a HG_XNNAME=commit
txnclose hook: HG_TXNNAME=commit
commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
@@ -73,6 +77,7 @@
pretxnopen hook: HG_TXNNAME=commit
pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
3:07f3376c1e65
+ pretxnclose hook: HG_PENDING=$TESTTMP/a HG_XNNAME=commit
txnclose 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
@@ -116,6 +121,7 @@
pretxnopen hook: HG_TXNNAME=commit
pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
4:539e4b31b6dc
+ pretxnclose hook: HG_PENDING=$TESTTMP/a HG_XNNAME=commit
tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
txnclose hook: HG_TXNNAME=commit
commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
@@ -212,6 +218,7 @@
searching for changes
no changes found
pretxnopen hook: HG_TXNNAME=bookmarks
+ pretxnclose hook: HG_PENDING=$TESTTMP/a HG_XNNAME=bookmarks
txnclose 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