Submitter | Boris Feld |
---|---|
Date | Oct. 14, 2017, 3:46 p.m. |
Message ID | <d1409d777e72f23fa1c7.1507995984@FB> |
Download | mbox | patch |
Permalink | /patch/24904/ |
State | Accepted |
Headers | show |
Comments
On Sat, Oct 14, 2017 at 05:46:24PM +0200, Boris Feld wrote: > # HG changeset patch > # User Boris Feld <boris.feld@octobus.net> > # Date 1507476198 -7200 > # Sun Oct 08 17:23:18 2017 +0200 > # Node ID d1409d777e72f23fa1c776beefd26a046091ef41 > # Parent 06eeae1828afe149886e18e6b4fc8180a3803fdb > # EXP-Topic b2.phases.hooks > # Available At https://bitbucket.org/octobus/mercurial-devel/ > # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r d1409d777e72 > phase: add a dedicated pretxnclose-phase hook queued, thanks
> On Oct 14, 2017, at 17:46, Boris Feld <boris.feld@octobus.net> wrote: > > # HG changeset patch > # User Boris Feld <boris.feld@octobus.net> > # Date 1507476198 -7200 > # Sun Oct 08 17:23:18 2017 +0200 > # Node ID d1409d777e72f23fa1c776beefd26a046091ef41 > # Parent 06eeae1828afe149886e18e6b4fc8180a3803fdb > # EXP-Topic b2.phases.hooks > # Available At https://bitbucket.org/octobus/mercurial-devel/ > # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r d1409d777e72 > phase: add a dedicated pretxnclose-phase hook Could you please send a follow up to improve the help documentation. Specifically: * Note that the hook can be fired multiple times * Clarify whether each change revision has a hook fire or whether it is only phase root/head revisions. If the latter, explain what that means. > > This new hook mirror the newly introduced 'txnclose-phase' but can 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 > @@ -990,6 +990,17 @@ > ``$HG_TXNNAME``, and a unique identifier for the transaction will be in > ``HG_TXNID``. > > +``pretxnclose-phase`` > + Run right before a phase 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 affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE`` > + while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE`` > + 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 > @@ -1005,12 +1016,8 @@ > ``txnclose-phase`` > Run after any phase 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 affected node is available in ``$HG_NODE``, the new phase will be > - available in ``$HG_PHASE`` while the previous phase will be available in > - ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE`` 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-phase` for details about > + available variables. > > ``txnabort`` > Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose` > diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py > --- a/mercurial/localrepo.py > +++ b/mercurial/localrepo.py > @@ -1243,6 +1243,14 @@ > repo.hook('pretxnclose-bookmark', throw=True, > txnname=desc, > **pycompat.strkwargs(args)) > + if hook.hashook(repo.ui, 'pretxnclose-phase'): > + cl = repo.unfiltered().changelog > + for rev, (old, new) in tr.changes['phases'].items(): > + args = tr.hookargs.copy() > + node = hex(cl.node(rev)) > + args.update(phases.preparehookargs(node, old, new)) > + repo.hook('pretxnclose-phase', throw=True, txnname=desc, > + **pycompat.strkwargs(args)) > > repo.hook('pretxnclose', throw=True, > txnname=desc, **pycompat.strkwargs(tr.hookargs)) > diff --git a/tests/test-phases.t b/tests/test-phases.t > --- a/tests/test-phases.t > +++ b/tests/test-phases.t > @@ -732,3 +732,94 @@ > rollback completed > abort: pretxnclose hook exited with status 1 > [255] > + > +Check that pretxnclose-phase hook can control phase movement > + > + $ hg phase --force b3325c91a4d9 --secret > + test-debug-phase: move rev 3: 0 -> 2 > + test-debug-phase: move rev 4: 0 -> 2 > + test-debug-phase: move rev 5: 1 -> 2 > + test-debug-phase: move rev 7: 0 -> 2 > + test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: 0 -> 2 > + test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: 0 -> 2 > + test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: 1 -> 2 > + test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: 0 -> 2 > + $ hg log -G -T phases > + @ changeset: 7:17a481b3bccb > + |\ tag: tip > + | | phase: secret > + | | parent: 6:cf9fe039dfd6 > + | | parent: 4:a603bfb5a83e > + | | user: test > + | | date: Thu Jan 01 00:00:00 1970 +0000 > + | | summary: merge B' and E > + | | > + | o changeset: 6:cf9fe039dfd6 > + | | phase: public > + | | parent: 1:27547f69f254 > + | | user: test > + | | date: Thu Jan 01 00:00:00 1970 +0000 > + | | summary: B' > + | | > + o | changeset: 4:a603bfb5a83e > + | | phase: secret > + | | user: test > + | | date: Thu Jan 01 00:00:00 1970 +0000 > + | | summary: E > + | | > + o | changeset: 3:b3325c91a4d9 > + | | phase: secret > + | | user: test > + | | date: Thu Jan 01 00:00:00 1970 +0000 > + | | summary: D > + | | > + o | changeset: 2:f838bfaca5c7 > + |/ phase: public > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: C > + | > + o changeset: 1:27547f69f254 > + | phase: public > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: B > + | > + o changeset: 0:4a2df7238c3b > + phase: public > + user: test > + date: Thu Jan 01 00:00:00 1970 +0000 > + summary: A > + > + > +Install a hook that prevent b3325c91a4d9 to become public > + > + $ cat >> .hg/hgrc << EOF > + > [hooks] > + > pretxnclose-phase.nopublish_D = (echo \$HG_NODE| grep -v b3325c91a4d9>/dev/null) || [ 0 -lt \$HG_PHASE ] > + > EOF > + > +Try various actions. only the draft move should succeed > + > + $ hg phase --public b3325c91a4d9 > + transaction abort! > + rollback completed > + abort: pretxnclose-phase.nopublish_D hook exited with status 1 > + [255] > + $ hg phase --public a603bfb5a83e > + transaction abort! > + rollback completed > + abort: pretxnclose-phase.nopublish_D hook exited with status 1 > + [255] > + $ hg phase --draft 17a481b3bccb > + test-debug-phase: move rev 3: 2 -> 1 > + test-debug-phase: move rev 4: 2 -> 1 > + test-debug-phase: move rev 7: 2 -> 1 > + test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: 2 -> 1 > + test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: 2 -> 1 > + test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: 2 -> 1 > + $ hg phase --public 17a481b3bccb > + transaction abort! > + rollback completed > + abort: pretxnclose-phase.nopublish_D hook exited with status 1 > + [255] > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Patch
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -990,6 +990,17 @@ ``$HG_TXNNAME``, and a unique identifier for the transaction will be in ``HG_TXNID``. +``pretxnclose-phase`` + Run right before a phase 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 affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE`` + while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE`` + 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 @@ -1005,12 +1016,8 @@ ``txnclose-phase`` Run after any phase 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 affected node is available in ``$HG_NODE``, the new phase will be - available in ``$HG_PHASE`` while the previous phase will be available in - ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE`` 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-phase` for details about + available variables. ``txnabort`` Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose` diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1243,6 +1243,14 @@ repo.hook('pretxnclose-bookmark', throw=True, txnname=desc, **pycompat.strkwargs(args)) + if hook.hashook(repo.ui, 'pretxnclose-phase'): + cl = repo.unfiltered().changelog + for rev, (old, new) in tr.changes['phases'].items(): + args = tr.hookargs.copy() + node = hex(cl.node(rev)) + args.update(phases.preparehookargs(node, old, new)) + repo.hook('pretxnclose-phase', throw=True, txnname=desc, + **pycompat.strkwargs(args)) repo.hook('pretxnclose', throw=True, txnname=desc, **pycompat.strkwargs(tr.hookargs)) diff --git a/tests/test-phases.t b/tests/test-phases.t --- a/tests/test-phases.t +++ b/tests/test-phases.t @@ -732,3 +732,94 @@ rollback completed abort: pretxnclose hook exited with status 1 [255] + +Check that pretxnclose-phase hook can control phase movement + + $ hg phase --force b3325c91a4d9 --secret + test-debug-phase: move rev 3: 0 -> 2 + test-debug-phase: move rev 4: 0 -> 2 + test-debug-phase: move rev 5: 1 -> 2 + test-debug-phase: move rev 7: 0 -> 2 + test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: 0 -> 2 + test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: 0 -> 2 + test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: 1 -> 2 + test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: 0 -> 2 + $ hg log -G -T phases + @ changeset: 7:17a481b3bccb + |\ tag: tip + | | phase: secret + | | parent: 6:cf9fe039dfd6 + | | parent: 4:a603bfb5a83e + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: merge B' and E + | | + | o changeset: 6:cf9fe039dfd6 + | | phase: public + | | parent: 1:27547f69f254 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B' + | | + o | changeset: 4:a603bfb5a83e + | | phase: secret + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: E + | | + o | changeset: 3:b3325c91a4d9 + | | phase: secret + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: D + | | + o | changeset: 2:f838bfaca5c7 + |/ phase: public + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + o changeset: 1:27547f69f254 + | phase: public + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + o changeset: 0:4a2df7238c3b + phase: public + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: A + + +Install a hook that prevent b3325c91a4d9 to become public + + $ cat >> .hg/hgrc << EOF + > [hooks] + > pretxnclose-phase.nopublish_D = (echo \$HG_NODE| grep -v b3325c91a4d9>/dev/null) || [ 0 -lt \$HG_PHASE ] + > EOF + +Try various actions. only the draft move should succeed + + $ hg phase --public b3325c91a4d9 + transaction abort! + rollback completed + abort: pretxnclose-phase.nopublish_D hook exited with status 1 + [255] + $ hg phase --public a603bfb5a83e + transaction abort! + rollback completed + abort: pretxnclose-phase.nopublish_D hook exited with status 1 + [255] + $ hg phase --draft 17a481b3bccb + test-debug-phase: move rev 3: 2 -> 1 + test-debug-phase: move rev 4: 2 -> 1 + test-debug-phase: move rev 7: 2 -> 1 + test-hook-close-phase: b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e: 2 -> 1 + test-hook-close-phase: a603bfb5a83e312131cebcd05353c217d4d21dde: 2 -> 1 + test-hook-close-phase: 17a481b3bccb796c0521ae97903d81c52bfee4af: 2 -> 1 + $ hg phase --public 17a481b3bccb + transaction abort! + rollback completed + abort: pretxnclose-phase.nopublish_D hook exited with status 1 + [255]