Patchwork [1,of,4,V2] bookmark: add a dedicated txnclose-bookmark hook

login
register
mail settings
Submitter Boris Feld
Date Oct. 14, 2017, 3:46 p.m.
Message ID <11d06ddaf572963d56dc.1507995981@FB>
Download mbox | patch
Permalink /patch/24901/
State Accepted
Headers show

Comments

Boris Feld - Oct. 14, 2017, 3:46 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1507650822 -7200
#      Tue Oct 10 17:53:42 2017 +0200
# Node ID 11d06ddaf572963d56dc612aec5ac758f4a49b16
# Parent  15b561fffde541a4ef3f6dcb0570efe45615cd35
# EXP-Topic b2.phases.hooks
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 11d06ddaf572
bookmark: add a dedicated txnclose-bookmark hook

The new 'txnclose-bookmark' hook expose the bookmark movement information
stored in 'tr.changes['bookmarks]'. To provide a simple and straightforward
hook API to the users, we introduce a new hook called for each bookmark
touched. Since a transaction can affect multiple bookmarks, updating the
existing 'txnclose' hook to expose that information would be more complex. The
data for all moves might not fit in environment variables and iterations over
each move would be cumbersome. So the introduction of a new dedicated hook is
preferred in this changeset.

This does not exclude the addition to the full bookmark information to the
existing 'txnclose' in the future to help write more complex hooks.

Patch

diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -846,3 +846,12 @@ 
 
         bmarks[bmark] = (n, prefix, label)
     _printbookmarks(ui, repo, bmarks, **opts)
+
+def preparehookargs(name, old, new):
+    if new is None:
+        new = ''
+    if old is None:
+        old = ''
+    return {'bookmark': name,
+            'node': hex(new),
+            'oldnode': hex(old)}
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -982,6 +982,18 @@ 
   after the lock is released. See :hg:`help config.hooks.pretxnclose` for
   details about available variables.
 
+``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``.
+
 ``txnabort``
   Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
   for details about available variables.
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1280,10 +1280,19 @@ 
             # fixes the function accumulation.
             hookargs = tr2.hookargs
 
-            def hook():
-                reporef().hook('txnclose', throw=False, txnname=desc,
-                               **pycompat.strkwargs(hookargs))
-            reporef()._afterlock(hook)
+            def hookfunc():
+                repo = reporef()
+                if hook.hashook(repo.ui, 'txnclose-bookmark'):
+                    bmchanges = sorted(tr.changes['bookmarks'].items())
+                    for name, (old, new) in bmchanges:
+                        args = tr.hookargs.copy()
+                        args.update(bookmarks.preparehookargs(name, old, new))
+                        repo.hook('txnclose-bookmark', throw=False,
+                                  txnname=desc, **pycompat.strkwargs(args))
+
+                repo.hook('txnclose', throw=False, txnname=desc,
+                          **pycompat.strkwargs(hookargs))
+            reporef()._afterlock(hookfunc)
         tr.addfinalize('txnclose-hook', txnclosehook)
         tr.addpostclose('warms-cache', self._buildcacheupdater(tr))
         def txnaborthook(tr2):
diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t
--- a/tests/test-bookmarks-pushpull.t
+++ b/tests/test-bookmarks-pushpull.t
@@ -9,6 +9,8 @@ 
   > stabilization=createmarkers,exchange
   > EOF
 
+  $ TESTHOOK='hooks.txnclose-bookmark.test=echo "test-hook-bookmark: $HG_BOOKMARK:  $HG_OLDNODE -> $HG_NODE"'
+
 initialize
 
   $ hg init a
@@ -30,7 +32,7 @@ 
   $ hg book Y
   $ hg book
    * Y                         -1:000000000000
-  $ hg pull ../a
+  $ hg pull ../a --config "$TESTHOOK"
   pulling from ../a
   requesting all changes
   adding changesets
@@ -41,6 +43,9 @@ 
   updating bookmark Y
   adding remote bookmark Z
   new changesets 4e3505fd9583
+  test-hook-bookmark: X:   -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
+  test-hook-bookmark: Y:  0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
+  test-hook-bookmark: Z:   -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
   (run 'hg update' to get a working copy)
   $ hg bookmarks
      X                         0:4e3505fd9583
@@ -94,10 +99,11 @@ 
 delete a remote bookmark
 
   $ hg book -d W
-  $ hg push -B W ../a
+  $ hg push -B W ../a --config "$TESTHOOK"
   pushing to ../a
   searching for changes
   no changes found
+  test-hook-bookmark: W:  0000000000000000000000000000000000000000 -> 
   deleting remote bookmark W
   [1]
 
@@ -165,7 +171,7 @@ 
      Z                         1:0d2164f0ce0d
 
   $ cd ../b
-  $ hg up
+  $ hg up --config
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updating bookmark foobar
   $ echo c2 > f2
@@ -181,7 +187,7 @@ 
      foo                       -1:000000000000
    * foobar                    1:9b140be10808
 
-  $ hg pull --config paths.foo=../a foo
+  $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
   pulling from $TESTTMP/a (glob)
   searching for changes
   adding changesets
@@ -192,6 +198,9 @@ 
   divergent bookmark X stored as X@foo
   updating bookmark Z
   new changesets 0d2164f0ce0d
+  test-hook-bookmark: @foo:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
+  test-hook-bookmark: X@foo:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
+  test-hook-bookmark: Z:  4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg book
      @                         1:9b140be10808
@@ -254,11 +263,13 @@ 
   $ hg update -r X
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (activating bookmark X)
-  $ hg pull --config paths.foo=../a foo -B .
+  $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
   pulling from $TESTTMP/a (glob)
   no changes found
   divergent bookmark @ stored as @foo
   importing bookmark X
+  test-hook-bookmark: @foo:  0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
+  test-hook-bookmark: X:  9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
 
 reinstall state for further testing:
 
@@ -283,13 +294,14 @@ 
   $ hg ci -Am3
   adding f2
   created new head
-  $ hg push ../a
+  $ hg push ../a --config "$TESTHOOK"
   pushing to ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
+  test-hook-bookmark: Y:  4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
   updating bookmark Y
   $ hg -R ../a book
      @                         1:0d2164f0ce0d
@@ -314,7 +326,11 @@ 
   > echo committed in pull-race
   > EOF
 
-  $ hg clone -q http://localhost:$HGPORT/ pull-race2
+  $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
+  test-hook-bookmark: @:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
+  test-hook-bookmark: X:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
+  test-hook-bookmark: Y:   -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
+  test-hook-bookmark: Z:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
   $ cd pull-race
   $ hg up -q Y
   $ echo c4 > f2
diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t
--- a/tests/test-bookmarks.t
+++ b/tests/test-bookmarks.t
@@ -1,6 +1,9 @@ 
+
   $ hg init repo
   $ cd repo
 
+  $ TESTHOOK='hooks.txnclose-bookmark.test=echo "test-hook-bookmark: $HG_BOOKMARK:  $HG_OLDNODE -> $HG_NODE"'
+
 no bookmarks
 
   $ hg bookmarks
@@ -12,7 +15,8 @@ 
 
 bookmark rev -1
 
-  $ hg bookmark X
+  $ hg bookmark X --config "$TESTHOOK"
+  test-hook-bookmark: X:   -> 0000000000000000000000000000000000000000
 
 list bookmarks
 
@@ -27,7 +31,8 @@ 
 
   $ echo a > a
   $ hg add a
-  $ hg commit -m 0
+  $ hg commit -m 0 --config "$TESTHOOK"
+  test-hook-bookmark: X:  0000000000000000000000000000000000000000 -> f7b1eb17ad24730a1651fccd46c43826d1bbc2ac
 
 bookmark X moved to rev 0
 
@@ -47,7 +52,8 @@ 
 
 second bookmark for rev 0, command should work even with ui.strict on
 
-  $ hg --config ui.strict=1 bookmark X2
+  $ hg --config ui.strict=1 bookmark X2 --config "$TESTHOOK"
+  test-hook-bookmark: X2:   -> f7b1eb17ad24730a1651fccd46c43826d1bbc2ac
 
 bookmark rev -1 again
 
@@ -62,7 +68,8 @@ 
 
   $ echo b > b
   $ hg add b
-  $ hg commit -m 1
+  $ hg commit -m 1 --config "$TESTHOOK"
+  test-hook-bookmark: X2:  f7b1eb17ad24730a1651fccd46c43826d1bbc2ac -> 925d80f479bb026b0fb3deb27503780b13f74123
 
   $ hg bookmarks -Tjson
   [
@@ -194,14 +201,17 @@ 
 rename bookmark using .
 
   $ hg book rename-me
-  $ hg book -m . renamed
+  $ hg book -m . renamed --config "$TESTHOOK"
+  test-hook-bookmark: rename-me:  db815d6d32e69058eadefc8cffbad37675707975 -> 
+  test-hook-bookmark: renamed:   -> db815d6d32e69058eadefc8cffbad37675707975
   $ hg bookmark
      X2                        1:925d80f479bb
      Y                         2:db815d6d32e6
      Z                         0:f7b1eb17ad24
    * renamed                   2:db815d6d32e6
   $ hg up -q Y
-  $ hg book -d renamed
+  $ hg book -d renamed --config "$TESTHOOK"
+  test-hook-bookmark: renamed:  db815d6d32e69058eadefc8cffbad37675707975 -> 
 
 rename bookmark using . with no active bookmark
 
@@ -354,11 +364,13 @@ 
   [255]
 
 bookmark with a name that matches a node id
-  $ hg bookmark 925d80f479bb db815d6d32e6
+  $ hg bookmark 925d80f479bb db815d6d32e6 --config "$TESTHOOK"
   bookmark 925d80f479bb matches a changeset hash
   (did you leave a -r out of an 'hg bookmark' command?)
   bookmark db815d6d32e6 matches a changeset hash
   (did you leave a -r out of an 'hg bookmark' command?)
+  test-hook-bookmark: 925d80f479bb:   -> db815d6d32e69058eadefc8cffbad37675707975
+  test-hook-bookmark: db815d6d32e6:   -> db815d6d32e69058eadefc8cffbad37675707975
   $ hg bookmark -d 925d80f479bb
   $ hg bookmark -d db815d6d32e6
 
@@ -406,7 +418,8 @@ 
 
 force bookmark with existing name
 
-  $ hg bookmark -f X2
+  $ hg bookmark -f X2 --config "$TESTHOOK"
+  test-hook-bookmark: X2:  925d80f479bb026b0fb3deb27503780b13f74123 -> db815d6d32e69058eadefc8cffbad37675707975
 
 force bookmark back to where it was, should deactivate it