bookmark: add a dedicated pretxnclose-bookmark hook
This new hook mirror the newly introduced 'txnclose-bookmark' but can abort the
transaction.
--- a/mercurial/help/config.txt Tue Oct 10 17:53:42 2017 +0200
+++ b/mercurial/help/config.txt Sun Oct 08 18:50:14 2017 +0200
@@ -988,6 +988,20 @@
phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
respectively, etc.
+``pretxnclose-bookmark``
+ Run right before a bookmark change 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. A non-zero status will cause the transaction to be rolled back.
+ The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
+ bookmark location will be available in ``$HG_NODE`` while the previous
+ location will be available in ``$HG_OLDNODE``. In case of a bookmark
+ creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
+ will be empty.
+ In addition, the reason for the transaction opening will be in
+ ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
+ ``HG_TXNID``.
+
``txnclose``
Run after any repository transaction has been committed. At this
point, the transaction can no longer be rolled back. The hook will run
@@ -997,14 +1011,8 @@
``txnclose-bookmark``
Run after any bookmark change has been committed. At this point, the
transaction can no longer be rolled back. The hook will run after the lock
- is released.
- The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
- bookmark location will be available in ``$HG_NODE`` while the previous
- location will be available in ``$HG_OLDNODE``. In case of a bookmark
- creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
- will be empty. In addition, the reason for the transaction opening will be
- in ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
- ``HG_TXNID``.
+ is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
+ about available variables.
``txnabort``
Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
--- a/mercurial/localrepo.py Tue Oct 10 17:53:42 2017 +0200
+++ b/mercurial/localrepo.py Sun Oct 08 18:50:14 2017 +0200
@@ -1235,8 +1235,17 @@
# This will have to be fixed before we remove the experimental
# gating.
tracktags(tr2)
- reporef().hook('pretxnclose', throw=True,
- txnname=desc, **pycompat.strkwargs(tr.hookargs))
+ repo = reporef()
+ if hook.hashook(repo.ui, 'pretxnclose-bookmark'):
+ for name, (old, new) in sorted(tr.changes['bookmarks'].items()):
+ args = tr.hookargs.copy()
+ args.update(bookmarks.preparehookargs(name, old, new))
+ repo.hook('pretxnclose-bookmark', throw=True,
+ txnname=desc,
+ **pycompat.strkwargs(args))
+
+ repo.hook('pretxnclose', throw=True,
+ txnname=desc, **pycompat.strkwargs(tr.hookargs))
def releasefn(tr, success):
repo = reporef()
if success:
--- a/tests/test-bookmarks.t Tue Oct 10 17:53:42 2017 +0200
+++ b/tests/test-bookmarks.t Sun Oct 08 18:50:14 2017 +0200
@@ -1063,3 +1063,99 @@
rollback completed
abort: pretxnclose hook exited with status 1
[255]
+
+Check pretxnclose-bookmark can abort a transaction
+--------------------------------------------------
+
+add hooks:
+
+* to prevent NEW bookmark on a non-public changeset
+* to prevent non-forward move of NEW bookmark
+
+ $ cat << EOF >> .hg/hgrc
+ > [hooks]
+ > pretxnclose-bookmark.force-public = (echo \$HG_BOOKMARK| grep -v NEW > /dev/null) || [ -z "\$HG_NODE" ] || (hg log -r "\$HG_NODE" -T '{phase}' | grep public > /dev/null)
+ > pretxnclose-bookmark.force-forward = (echo \$HG_BOOKMARK| grep -v NEW > /dev/null) || [ -z "\$HG_NODE" ] || (hg log -r "max(\$HG_OLDNODE::\$HG_NODE)" -T 'MATCH' | grep MATCH > /dev/null)
+ > EOF
+
+ $ hg log -G -T phases
+ @ changeset: 6:81dcce76aa0b
+ | tag: tip
+ | phase: draft
+ | parent: 4:125c9a1d6df6
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: xx
+ |
+ | o changeset: 5:5fb12f0f2d51
+ | | branch: test
+ | | bookmark: Z
+ | | phase: draft
+ | | parent: 3:9ba5f110a0b3
+ | | user: test
+ | | date: Thu Jan 01 00:00:00 1970 +0000
+ | | summary: yy
+ | |
+ o | changeset: 4:125c9a1d6df6
+ | | bookmark: Y
+ | | bookmark: Z@2
+ | | phase: public
+ | | parent: 2:db815d6d32e6
+ | | user: test
+ | | date: Thu Jan 01 00:00:00 1970 +0000
+ | | summary: x
+ | |
+ | o changeset: 3:9ba5f110a0b3
+ |/ branch: test
+ | bookmark: foo
+ | bookmark: four
+ | phase: public
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: y
+ |
+ o changeset: 2:db815d6d32e6
+ | bookmark: foo@2
+ | bookmark: should-end-on-two
+ | bookmark: x y
+ | phase: public
+ | parent: 0:f7b1eb17ad24
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: 2
+ |
+ | o changeset: 1:925d80f479bb
+ |/ bookmark: X2
+ | bookmark: Z@1
+ | phase: public
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: 1
+ |
+ o changeset: 0:f7b1eb17ad24
+ bookmark: foo@1
+ phase: public
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: 0
+
+
+attempt to create on a default changeset
+
+ $ hg bookmark -r 81dcce76aa0b NEW
+ transaction abort!
+ rollback completed
+ abort: pretxnclose-bookmark.force-public hook exited with status 1
+ [255]
+
+create on a public changeset
+
+ $ hg bookmark -r 9ba5f110a0b3 NEW
+
+move to the other branch
+
+ $ hg bookmark -f -r 125c9a1d6df6 NEW
+ transaction abort!
+ rollback completed
+ abort: pretxnclose-bookmark.force-forward hook exited with status 1
+ [255]