Patchwork [4,of,4,NEW-CONCEPT] track-tags: write all tag changes to a file

login
register
mail settings
Submitter Pierre-Yves David
Date March 30, 2017, 3:03 p.m.
Message ID <46005886092380991a30.1490886222@nodosa.octopoid.net>
Download mbox | patch
Permalink /patch/19850/
State Deferred
Headers show

Comments

Pierre-Yves David - March 30, 2017, 3:03 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
# Date 1490688902 -7200
#      Tue Mar 28 10:15:02 2017 +0200
# Node ID 46005886092380991a30c2a02486c2876ecac341
# Parent  2dcaa99d6160561166269f192a89b25f84fd4667
# EXP-Topic tags
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 460058860923
track-tags: write all tag changes to a file

The tag changes information we compute are not written to disk. This gives
hooks full acces to that data.

The format picked for that file use a 2 characters prefix for the action:

    -R: tag removed
    +A: tag added
    -M: tag moved (old value)
    +M: tag moved (new value)

This format allows hooks to easily select the line that matters to them without
having to post process the file too much. Here is
a couple of example:

 * to select all newly tagged changeset, match "^+",
 * to detect tag move, match "^.M",
 * to detect tag deletion, match "-R".

Once again we rely on the fact the tag tests run through all possible
situations to test this change.
Augie Fackler - April 3, 2017, 8:50 p.m.
On Thu, Mar 30, 2017 at 05:03:42PM +0200, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
> # Date 1490688902 -7200
> #      Tue Mar 28 10:15:02 2017 +0200
> # Node ID 46005886092380991a30c2a02486c2876ecac341
> # Parent  2dcaa99d6160561166269f192a89b25f84fd4667
> # EXP-Topic tags
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 460058860923
> track-tags: write all tag changes to a file

Overall, the feature seems reasonable, and having the hook information
seems right. Should this be integrated with the journal code somehow?

>
> The tag changes information we compute are not written to disk. This gives
> hooks full acces to that data.
>
> The format picked for that file use a 2 characters prefix for the action:
>
>     -R: tag removed
>     +A: tag added
>     -M: tag moved (old value)
>     +M: tag moved (new value)
>
> This format allows hooks to easily select the line that matters to them without
> having to post process the file too much. Here is
> a couple of example:
>
>  * to select all newly tagged changeset, match "^+",
>  * to detect tag move, match "^.M",
>  * to detect tag deletion, match "-R".
>
> Once again we rely on the fact the tag tests run through all possible
> situations to test this change.
>
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -1015,6 +1015,25 @@ class localrepository(object):
>          # and do not use caches as much as it could.  The current focus is on
>          # the behavior of the feature so we disable it by default. The flag
>          # will be removed when we are happy with the performance impact.
> +        #
> +        # Once this feature is no longer experimental move the following
> +        # documentation to the appropriate help section:
> +        #
> +        # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
> +        # tags (new or changed or deleted tags). In addition the details of
> +        # these changes are made available in a file at:
> +        #     ``REPOROOT/.hg/changes/tags.changes``.
> +        # Make sure you check for HG_TAG_MOVED before reading that file as it
> +        # might exist from a previous transaction even if no tag were touched
> +        # in this one. Change are recorded in a line base format::
> +        #
> +        #     <action> <hex-node> <tag-name>\n
> +        #
> +        # Actions are defined as follow:
> +        #   "-R": tag is removed,
> +        #   "+A": tag is added,
> +        #   "-M": tag is moved (old value),
> +        #   "+M": tag is moved (new value),
>          tracktags = lambda x: None
>          # experimental config: experimental.hook-track-tags
>          shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags',
> @@ -1031,6 +1050,12 @@ class localrepository(object):
>                  changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
>                  if changes:
>                      tr2.hookargs['tag_moved'] = '1'
> +                    with repo.vfs('changes/tags.changes', 'w',
> +                                  atomictemp=True) as changesfile:
> +                        # note: we do not register the file to the transaction
> +                        # because we needs it to still exist on the transaction
> +                        # is close (for txnclose hooks)
> +                        tagsmod.writediff(changesfile, changes)
>          def validate(tr2):
>              """will run pre-closing hooks"""
>              # XXX the transaction API is a bit lacking here so we take a hacky
> diff --git a/mercurial/tags.py b/mercurial/tags.py
> --- a/mercurial/tags.py
> +++ b/mercurial/tags.py
> @@ -129,6 +129,44 @@ def difftags(ui, repo, oldfnodes, newfno
>      entries.sort()
>      return entries
>
> +def writediff(fp, difflist):
> +    """write tags diff information to a file.
> +
> +    Data are stored with a line based format:
> +
> +        <action> <hex-node> <tag-name>\n
> +
> +    Action are defined as follow:
> +       -R tag is removed,
> +       +A tag is added,
> +       -M tag is moved (old value),
> +       +M tag is moved (new value),
> +
> +    Example:
> +
> +         +A 875517b4806a848f942811a315a5bce30804ae85 t5
> +
> +    See documentation of difftags output for details about the input.
> +    """
> +    add = '+A %s %s\n'
> +    remove = '-R %s %s\n'
> +    updateold = '-M %s %s\n'
> +    updatenew = '+M %s %s\n'
> +    for tag, old, new in difflist:
> +        # translate to hex
> +        if old is not None:
> +            old = hex(old)
> +        if new is not None:
> +            new = hex(new)
> +        # write to file
> +        if old is None:
> +            fp.write(add % (new, tag))
> +        elif new is None:
> +            fp.write(remove % (old, tag))
> +        else:
> +            fp.write(updateold % (old, tag))
> +            fp.write(updatenew % (new, tag))
> +
>  def findglobaltags(ui, repo):
>      '''Find global tags in a repo: return a tagsmap
>
> diff --git a/tests/test-tag.t b/tests/test-tag.t
> --- a/tests/test-tag.t
> +++ b/tests/test-tag.t
> @@ -11,6 +11,7 @@
>    > # file...
>    > if [ -n "\$HG_TAG_MOVED" ]; then
>    >     echo 'hook: tag changes detected'
> +  >     sed 's/^/hook: /' .hg/changes/tags.changes
>    > fi
>    > EOF
>    $ chmod +x taghook.sh
> @@ -37,6 +38,7 @@ specified)
>
>    $ HGEDITOR=cat hg tag "bleah"
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
>    $ hg history
>    changeset:   1:d4f0d2909abc
>    tag:         tip
> @@ -86,13 +88,21 @@ specified)
>
>    $ hg tag -r 0 "bleah0"
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
>    $ hg tag -l -r 1 "bleah1"
>    $ hg tag gack gawk gorp
>    hook: tag changes detected
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gack
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gawk
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gorp
>    $ hg tag -f gack
>    hook: tag changes detected
> +  hook: -M 336fccc858a4eb69609a291105009e484a6b6b8d gack
> +  hook: +M 799667b6f2d9b957f73fa644a918c2df22bab58f gack
>    $ hg tag --remove gack gorp
>    hook: tag changes detected
> +  hook: -R 799667b6f2d9b957f73fa644a918c2df22bab58f gack
> +  hook: -R 336fccc858a4eb69609a291105009e484a6b6b8d gorp
>
>    $ hg tag "bleah "
>    abort: tag 'bleah' already exists (use -f to force)
> @@ -105,8 +115,10 @@ specified)
>    [255]
>    $ hg tag -r 0 "  bleahbleah  "
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
>    $ hg tag -r 0 " bleah bleah "
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
>
>    $ cat .hgtags
>    acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
> @@ -136,6 +148,7 @@ tagging on a non-head revision
>    [255]
>    $ hg tag -f "foobar"
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ cat .hgtags
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ cat .hg/localtags
> @@ -194,18 +207,23 @@ cloning local tags
>
>    $ hg clone -q -rbleah1 test test1
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
>    $ hg -R test1 parents --style=compact
>    1[tip]   d4f0d2909abc   1970-01-01 00:00 +0000   test
>      Added tag bleah for changeset acb14030fe0a
>
>    $ hg clone -q -r5 test#bleah1 test2
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gawk
>    $ hg -R test2 parents --style=compact
>    5[tip]   b4bb47aaff09   1970-01-01 00:00 +0000   test
>      Removed tag gack, gorp
>
>    $ hg clone -q -U test#bleah1 test3
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
>    $ hg -R test3 parents --style=compact
>
>    $ cd test
> @@ -234,6 +252,7 @@ doesn't end with EOL
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ hg tag newline
>    hook: tag changes detected
> +  hook: +A a0eea09de1eeec777b46f2085260a373b2fbc293 newline
>    $ cat .hgtags; echo
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    a0eea09de1eeec777b46f2085260a373b2fbc293 newline
> @@ -248,6 +267,7 @@ tag and branch using same name
>    $ hg tag tag-and-branch-same-name
>    warning: tag tag-and-branch-same-name conflicts with existing branch name
>    hook: tag changes detected
> +  hook: +A fc93d2ea1cd78e91216c6cfbbf26747c10ce11ae tag-and-branch-same-name
>
>  test custom commit messages
>
> @@ -333,6 +353,7 @@ then, test custom commit message itself
>    HG: changed .hgtags
>    ====
>    hook: tag changes detected
> +  hook: +A 75a534207be6b03576e0c7a4fa5708d045f1c876 custom-tag
>    $ hg log -l1 --template "{desc}\n"
>    custom tag message
>    second line
> @@ -342,6 +363,7 @@ local tag with .hgtags modified
>
>    $ hg tag hgtags-modified
>    hook: tag changes detected
> +  hook: +A 0f26aaea6f74c3ed6c4aad8844403c9ba128d23a hgtags-modified
>    $ hg rollback
>    repository tip rolled back to revision 13 (undo commit)
>    working directory now based on revision 13
> @@ -362,10 +384,16 @@ tagging when at named-branch-head that's
>    (branch merge, don't forget to commit)
>    $ hg ci -m 'merge named branch'
>    hook: tag changes detected
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
> +  hook: -R 336fccc858a4eb69609a291105009e484a6b6b8d gawk
>    $ hg up 13
>    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>    $ hg tag new-topo-head
>    hook: tag changes detected
> +  hook: +A 0f26aaea6f74c3ed6c4aad8844403c9ba128d23a new-topo-head
>
>  tagging on null rev
>
> @@ -433,6 +461,7 @@ commit hook on tag used to be run withou
>    > EOF
>    $ hg -R repo-tag --config hooks.commit="sh ../issue3344.sh" tag tag
>    hook: tag changes detected
> +  hook: +A be090ea6625635128e90f7d89df8beeb2bcc1653 tag
>    pushing to $TESTTMP/repo-tag-target (glob)
>    searching for changes
>    adding changesets
> @@ -440,6 +469,7 @@ commit hook on tag used to be run withou
>    adding file changes
>    added 2 changesets with 2 changes to 2 files
>    hook: tag changes detected
> +  hook: +A be090ea6625635128e90f7d89df8beeb2bcc1653 tag
>
>  automatically merge resolvable tag conflicts (i.e. tags that differ in rank)
>  create two clones with some different tags as well as some common tags
> @@ -452,6 +482,7 @@ check that we can merge tags that differ
>    adding f0
>    $ hg tag tbase
>    hook: tag changes detected
> +  hook: +A 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
>    $ hg up -qr '.^'
>    $ hg log -r 'wdir()' -T "{latesttagdistance}\n"
>    1
> @@ -468,15 +499,22 @@ check that we can merge tags that differ
>    adding f1
>    $ hg tag t1 t2 t3
>    hook: tag changes detected
> +  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
> +  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
> +  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
>    $ hg tag --remove t2
>    hook: tag changes detected
> +  hook: -R 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
>    $ hg tag t5
>    hook: tag changes detected
> +  hook: +A 875517b4806a848f942811a315a5bce30804ae85 t5
>    $ echo c2 > f2
>    $ hg ci -A -m2
>    adding f2
>    $ hg tag -f t3
>    hook: tag changes detected
> +  hook: -M 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
> +  hook: +M 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
>
>    $ cd ../repo-automatic-tag-merge
>    $ echo c3 > f3
> @@ -484,6 +522,9 @@ check that we can merge tags that differ
>    adding f3
>    $ hg tag -f t4 t5 t6
>    hook: tag changes detected
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
>
>    $ hg up -q '.^'
>    $ hg log -r 'wdir()' -T "{changessincelatesttag} changes since {latesttag}\n"
> @@ -497,6 +538,7 @@ check that we can merge tags that differ
>
>    $ hg tag --remove t5
>    hook: tag changes detected
> +  hook: -R 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
>    $ echo c4 > f4
>    $ hg log -r '.' -T "{changessincelatesttag} changes since {latesttag}\n"
>    2 changes since t4:t6
> @@ -516,8 +558,11 @@ check that we can merge tags that differ
>    4 changes since t4:t6
>    $ hg tag t2
>    hook: tag changes detected
> +  hook: +A 929bca7b18d067cbf3844c3896319a940059d748 t2
>    $ hg tag -f t6
>    hook: tag changes detected
> +  hook: -M 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
> +  hook: +M 09af2ce14077a94effef208b49a718f4836d4338 t6
>
>    $ cd ../repo-automatic-tag-merge-clone
>    $ hg pull
> @@ -528,6 +573,10 @@ check that we can merge tags that differ
>    adding file changes
>    added 6 changesets with 6 changes to 3 files (+1 heads)
>    hook: tag changes detected
> +  hook: +A 929bca7b18d067cbf3844c3896319a940059d748 t2
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
> +  hook: -R 875517b4806a848f942811a315a5bce30804ae85 t5
> +  hook: +A 09af2ce14077a94effef208b49a718f4836d4338 t6
>    (run 'hg heads' to see heads, 'hg merge' to merge)
>    $ hg merge --tool internal:tagmerge
>    merging .hgtags
> @@ -589,11 +638,16 @@ detect merge tag conflicts
>    3 files updated, 0 files merged, 2 files removed, 0 files unresolved
>    $ hg tag t7
>    hook: tag changes detected
> +  hook: +A b325cc5b642c5b465bdbe8c09627cb372de3d47d t7
>    $ hg update -C -r 'first(sort(head()))'
>    3 files updated, 0 files merged, 2 files removed, 0 files unresolved
>    $ printf "%s %s\n" `hg log -r . --template "{node} t7"` >> .hgtags
>    $ hg commit -m "manually add conflicting t7 tag"
>    hook: tag changes detected
> +  hook: -R 929bca7b18d067cbf3844c3896319a940059d748 t2
> +  hook: +A 875517b4806a848f942811a315a5bce30804ae85 t5
> +  hook: -M b325cc5b642c5b465bdbe8c09627cb372de3d47d t7
> +  hook: +M ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
>    $ hg merge --tool internal:tagmerge
>    merging .hgtags
>    automatic .hgtags merge failed
> @@ -629,6 +683,8 @@ handle the loss of tags
>    adding f5
>    $ hg tag -f t7
>    hook: tag changes detected
> +  hook: -M ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
> +  hook: +M fd3a9e394ce3afb354a496323bf68ac1755a30de t7
>    $ hg update -r 'p1(t7)'
>    1 files updated, 0 files merged, 1 files removed, 0 files unresolved
>    $ printf '' > .hgtags
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Pierre-Yves David - April 4, 2017, 11:09 a.m.
On 04/03/2017 10:50 PM, Augie Fackler wrote:
> On Thu, Mar 30, 2017 at 05:03:42PM +0200, Pierre-Yves David wrote:
>> # HG changeset patch
>> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
>> # Date 1490688902 -7200
>> #      Tue Mar 28 10:15:02 2017 +0200
>> # Node ID 46005886092380991a30c2a02486c2876ecac341
>> # Parent  2dcaa99d6160561166269f192a89b25f84fd4667
>> # EXP-Topic tags
>> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
>> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 460058860923
>> track-tags: write all tag changes to a file
>
> Overall, the feature seems reasonable, and having the hook information
> seems right.

Status of this series is a bit unclear to me. Do you need me to do 
anything ?


> Should this be integrated with the journal code somehow?

Eventually yes. As pointed in this series, we need similar information 
for bookmark, phase and obsolescence. And we need to refactor the 
transaction for this. Journal integration will likely happens when the 
core rework of the transaction happens.
I've founding for the obsolescence/phase part so this should happen in 
the next cycle.
Augie Fackler - April 5, 2017, 7:27 p.m.
> On Apr 4, 2017, at 07:09, Pierre-Yves David <pierre-yves.david@ens-lyon.org> wrote:
> 
> 
> 
> On 04/03/2017 10:50 PM, Augie Fackler wrote:
>> On Thu, Mar 30, 2017 at 05:03:42PM +0200, Pierre-Yves David wrote:
>>> # HG changeset patch
>>> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
>>> # Date 1490688902 -7200
>>> #      Tue Mar 28 10:15:02 2017 +0200
>>> # Node ID 46005886092380991a30c2a02486c2876ecac341
>>> # Parent  2dcaa99d6160561166269f192a89b25f84fd4667
>>> # EXP-Topic tags
>>> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
>>> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 460058860923
>>> track-tags: write all tag changes to a file
>> 
>> Overall, the feature seems reasonable, and having the hook information
>> seems right.
> 
> Status of this series is a bit unclear to me. Do you need me to do anything ?

I guess I'd like others to comment on the way you're passing data into the hooks. It feels a little odd to me.

> 
> 
>> Should this be integrated with the journal code somehow?
> 
> Eventually yes. As pointed in this series, we need similar information for bookmark, phase and obsolescence. And we need to refactor the transaction for this. Journal integration will likely happens when the core rework of the transaction happens.
> I've founding for the obsolescence/phase part so this should happen in the next cycle.
> 
> -- 
> Pierre-Yves David
Pierre-Yves David - April 5, 2017, 8:19 p.m.
On 04/05/2017 09:27 PM, Augie Fackler wrote:
>
>> On Apr 4, 2017, at 07:09, Pierre-Yves David <pierre-yves.david@ens-lyon.org> wrote:
>>
>>
>>
>> On 04/03/2017 10:50 PM, Augie Fackler wrote:
>>> On Thu, Mar 30, 2017 at 05:03:42PM +0200, Pierre-Yves David wrote:
>>>> # HG changeset patch
>>>> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
>>>> # Date 1490688902 -7200
>>>> #      Tue Mar 28 10:15:02 2017 +0200
>>>> # Node ID 46005886092380991a30c2a02486c2876ecac341
>>>> # Parent  2dcaa99d6160561166269f192a89b25f84fd4667
>>>> # EXP-Topic tags
>>>> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
>>>> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 460058860923
>>>> track-tags: write all tag changes to a file
>>>
>>> Overall, the feature seems reasonable, and having the hook information
>>> seems right.
>>
>> Status of this series is a bit unclear to me. Do you need me to do anything ?
>
> I guess I'd like others to comment on the way you're passing data into the hooks. It feels a little odd to me.

Can you elaborate on what feels odds?

The amount of data can be arbitrarily large so we cannot use an 
enviromnent variable. We could have a hooks call a dedicated mercurial 
commands but that would be a bit odd and slower since we loop back into 
Mercurial.
Jun Wu - April 5, 2017, 8:54 p.m.
I don't think "writing things that hook *may* need to filesystem" is a good
approach. It introduces unnecessary overhead if the hook does not need that
information.

I think a better way is to have per-hook config to let hooks explicitly
declare what they need, before we run them.

Excerpts from Pierre-Yves David's message of 2017-03-30 17:03:42 +0200:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
> # Date 1490688902 -7200
> #      Tue Mar 28 10:15:02 2017 +0200
> # Node ID 46005886092380991a30c2a02486c2876ecac341
> # Parent  2dcaa99d6160561166269f192a89b25f84fd4667
> # EXP-Topic tags
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ 
> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/  -r 460058860923
> track-tags: write all tag changes to a file
> 
> The tag changes information we compute are not written to disk. This gives
> hooks full acces to that data.
> 
> The format picked for that file use a 2 characters prefix for the action:
> 
>     -R: tag removed
>     +A: tag added
>     -M: tag moved (old value)
>     +M: tag moved (new value)
> 
> This format allows hooks to easily select the line that matters to them without
> having to post process the file too much. Here is
> a couple of example:
> 
>  * to select all newly tagged changeset, match "^+",
>  * to detect tag move, match "^.M",
>  * to detect tag deletion, match "-R".
> 
> Once again we rely on the fact the tag tests run through all possible
> situations to test this change.
> 
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -1015,6 +1015,25 @@ class localrepository(object):
>          # and do not use caches as much as it could.  The current focus is on
>          # the behavior of the feature so we disable it by default. The flag
>          # will be removed when we are happy with the performance impact.
> +        #
> +        # Once this feature is no longer experimental move the following
> +        # documentation to the appropriate help section:
> +        #
> +        # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
> +        # tags (new or changed or deleted tags). In addition the details of
> +        # these changes are made available in a file at:
> +        #     ``REPOROOT/.hg/changes/tags.changes``.
> +        # Make sure you check for HG_TAG_MOVED before reading that file as it
> +        # might exist from a previous transaction even if no tag were touched
> +        # in this one. Change are recorded in a line base format::
> +        #
> +        #     <action> <hex-node> <tag-name>\n
> +        #
> +        # Actions are defined as follow:
> +        #   "-R": tag is removed,
> +        #   "+A": tag is added,
> +        #   "-M": tag is moved (old value),
> +        #   "+M": tag is moved (new value),
>          tracktags = lambda x: None
>          # experimental config: experimental.hook-track-tags
>          shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags',
> @@ -1031,6 +1050,12 @@ class localrepository(object):
>                  changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
>                  if changes:
>                      tr2.hookargs['tag_moved'] = '1'
> +                    with repo.vfs('changes/tags.changes', 'w',
> +                                  atomictemp=True) as changesfile:
> +                        # note: we do not register the file to the transaction
> +                        # because we needs it to still exist on the transaction
> +                        # is close (for txnclose hooks)
> +                        tagsmod.writediff(changesfile, changes)
>          def validate(tr2):
>              """will run pre-closing hooks"""
>              # XXX the transaction API is a bit lacking here so we take a hacky
> diff --git a/mercurial/tags.py b/mercurial/tags.py
> --- a/mercurial/tags.py
> +++ b/mercurial/tags.py
> @@ -129,6 +129,44 @@ def difftags(ui, repo, oldfnodes, newfno
>      entries.sort()
>      return entries
>  
> +def writediff(fp, difflist):
> +    """write tags diff information to a file.
> +
> +    Data are stored with a line based format:
> +
> +        <action> <hex-node> <tag-name>\n
> +
> +    Action are defined as follow:
> +       -R tag is removed,
> +       +A tag is added,
> +       -M tag is moved (old value),
> +       +M tag is moved (new value),
> +
> +    Example:
> +
> +         +A 875517b4806a848f942811a315a5bce30804ae85 t5
> +
> +    See documentation of difftags output for details about the input.
> +    """
> +    add = '+A %s %s\n'
> +    remove = '-R %s %s\n'
> +    updateold = '-M %s %s\n'
> +    updatenew = '+M %s %s\n'
> +    for tag, old, new in difflist:
> +        # translate to hex
> +        if old is not None:
> +            old = hex(old)
> +        if new is not None:
> +            new = hex(new)
> +        # write to file
> +        if old is None:
> +            fp.write(add % (new, tag))
> +        elif new is None:
> +            fp.write(remove % (old, tag))
> +        else:
> +            fp.write(updateold % (old, tag))
> +            fp.write(updatenew % (new, tag))
> +
>  def findglobaltags(ui, repo):
>      '''Find global tags in a repo: return a tagsmap
>  
> diff --git a/tests/test-tag.t b/tests/test-tag.t
> --- a/tests/test-tag.t
> +++ b/tests/test-tag.t
> @@ -11,6 +11,7 @@
>    > # file...
>    > if [ -n "\$HG_TAG_MOVED" ]; then
>    >     echo 'hook: tag changes detected'
> +  >     sed 's/^/hook: /' .hg/changes/tags.changes
>    > fi
>    > EOF
>    $ chmod +x taghook.sh
> @@ -37,6 +38,7 @@ specified)
>  
>    $ HGEDITOR=cat hg tag "bleah"
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
>    $ hg history
>    changeset:   1:d4f0d2909abc
>    tag:         tip
> @@ -86,13 +88,21 @@ specified)
>  
>    $ hg tag -r 0 "bleah0"
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
>    $ hg tag -l -r 1 "bleah1"
>    $ hg tag gack gawk gorp
>    hook: tag changes detected
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gack
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gawk
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gorp
>    $ hg tag -f gack
>    hook: tag changes detected
> +  hook: -M 336fccc858a4eb69609a291105009e484a6b6b8d gack
> +  hook: +M 799667b6f2d9b957f73fa644a918c2df22bab58f gack
>    $ hg tag --remove gack gorp
>    hook: tag changes detected
> +  hook: -R 799667b6f2d9b957f73fa644a918c2df22bab58f gack
> +  hook: -R 336fccc858a4eb69609a291105009e484a6b6b8d gorp
>  
>    $ hg tag "bleah "
>    abort: tag 'bleah' already exists (use -f to force)
> @@ -105,8 +115,10 @@ specified)
>    [255]
>    $ hg tag -r 0 "  bleahbleah  "
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
>    $ hg tag -r 0 " bleah bleah "
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
>  
>    $ cat .hgtags
>    acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
> @@ -136,6 +148,7 @@ tagging on a non-head revision
>    [255]
>    $ hg tag -f "foobar"
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ cat .hgtags
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ cat .hg/localtags
> @@ -194,18 +207,23 @@ cloning local tags
>    
>    $ hg clone -q -rbleah1 test test1
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
>    $ hg -R test1 parents --style=compact
>    1[tip]   d4f0d2909abc   1970-01-01 00:00 +0000   test
>      Added tag bleah for changeset acb14030fe0a
>    
>    $ hg clone -q -r5 test#bleah1 test2
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
> +  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gawk
>    $ hg -R test2 parents --style=compact
>    5[tip]   b4bb47aaff09   1970-01-01 00:00 +0000   test
>      Removed tag gack, gorp
>    
>    $ hg clone -q -U test#bleah1 test3
>    hook: tag changes detected
> +  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
>    $ hg -R test3 parents --style=compact
>  
>    $ cd test
> @@ -234,6 +252,7 @@ doesn't end with EOL
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ hg tag newline
>    hook: tag changes detected
> +  hook: +A a0eea09de1eeec777b46f2085260a373b2fbc293 newline
>    $ cat .hgtags; echo
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    a0eea09de1eeec777b46f2085260a373b2fbc293 newline
> @@ -248,6 +267,7 @@ tag and branch using same name
>    $ hg tag tag-and-branch-same-name
>    warning: tag tag-and-branch-same-name conflicts with existing branch name
>    hook: tag changes detected
> +  hook: +A fc93d2ea1cd78e91216c6cfbbf26747c10ce11ae tag-and-branch-same-name
>  
>  test custom commit messages
>  
> @@ -333,6 +353,7 @@ then, test custom commit message itself
>    HG: changed .hgtags
>    ====
>    hook: tag changes detected
> +  hook: +A 75a534207be6b03576e0c7a4fa5708d045f1c876 custom-tag
>    $ hg log -l1 --template "{desc}\n"
>    custom tag message
>    second line
> @@ -342,6 +363,7 @@ local tag with .hgtags modified
>  
>    $ hg tag hgtags-modified
>    hook: tag changes detected
> +  hook: +A 0f26aaea6f74c3ed6c4aad8844403c9ba128d23a hgtags-modified
>    $ hg rollback
>    repository tip rolled back to revision 13 (undo commit)
>    working directory now based on revision 13
> @@ -362,10 +384,16 @@ tagging when at named-branch-head that's
>    (branch merge, don't forget to commit)
>    $ hg ci -m 'merge named branch'
>    hook: tag changes detected
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
> +  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
> +  hook: -R 336fccc858a4eb69609a291105009e484a6b6b8d gawk
>    $ hg up 13
>    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>    $ hg tag new-topo-head
>    hook: tag changes detected
> +  hook: +A 0f26aaea6f74c3ed6c4aad8844403c9ba128d23a new-topo-head
>  
>  tagging on null rev
>  
> @@ -433,6 +461,7 @@ commit hook on tag used to be run withou
>    > EOF
>    $ hg -R repo-tag --config hooks.commit="sh ../issue3344.sh" tag tag
>    hook: tag changes detected
> +  hook: +A be090ea6625635128e90f7d89df8beeb2bcc1653 tag
>    pushing to $TESTTMP/repo-tag-target (glob)
>    searching for changes
>    adding changesets
> @@ -440,6 +469,7 @@ commit hook on tag used to be run withou
>    adding file changes
>    added 2 changesets with 2 changes to 2 files
>    hook: tag changes detected
> +  hook: +A be090ea6625635128e90f7d89df8beeb2bcc1653 tag
>  
>  automatically merge resolvable tag conflicts (i.e. tags that differ in rank)
>  create two clones with some different tags as well as some common tags
> @@ -452,6 +482,7 @@ check that we can merge tags that differ
>    adding f0
>    $ hg tag tbase
>    hook: tag changes detected
> +  hook: +A 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
>    $ hg up -qr '.^'
>    $ hg log -r 'wdir()' -T "{latesttagdistance}\n"
>    1
> @@ -468,15 +499,22 @@ check that we can merge tags that differ
>    adding f1
>    $ hg tag t1 t2 t3
>    hook: tag changes detected
> +  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
> +  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
> +  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
>    $ hg tag --remove t2
>    hook: tag changes detected
> +  hook: -R 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
>    $ hg tag t5
>    hook: tag changes detected
> +  hook: +A 875517b4806a848f942811a315a5bce30804ae85 t5
>    $ echo c2 > f2
>    $ hg ci -A -m2
>    adding f2
>    $ hg tag -f t3
>    hook: tag changes detected
> +  hook: -M 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
> +  hook: +M 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
>  
>    $ cd ../repo-automatic-tag-merge
>    $ echo c3 > f3
> @@ -484,6 +522,9 @@ check that we can merge tags that differ
>    adding f3
>    $ hg tag -f t4 t5 t6
>    hook: tag changes detected
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
>  
>    $ hg up -q '.^'
>    $ hg log -r 'wdir()' -T "{changessincelatesttag} changes since {latesttag}\n"
> @@ -497,6 +538,7 @@ check that we can merge tags that differ
>  
>    $ hg tag --remove t5
>    hook: tag changes detected
> +  hook: -R 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
>    $ echo c4 > f4
>    $ hg log -r '.' -T "{changessincelatesttag} changes since {latesttag}\n"
>    2 changes since t4:t6
> @@ -516,8 +558,11 @@ check that we can merge tags that differ
>    4 changes since t4:t6
>    $ hg tag t2
>    hook: tag changes detected
> +  hook: +A 929bca7b18d067cbf3844c3896319a940059d748 t2
>    $ hg tag -f t6
>    hook: tag changes detected
> +  hook: -M 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
> +  hook: +M 09af2ce14077a94effef208b49a718f4836d4338 t6
>  
>    $ cd ../repo-automatic-tag-merge-clone
>    $ hg pull
> @@ -528,6 +573,10 @@ check that we can merge tags that differ
>    adding file changes
>    added 6 changesets with 6 changes to 3 files (+1 heads)
>    hook: tag changes detected
> +  hook: +A 929bca7b18d067cbf3844c3896319a940059d748 t2
> +  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
> +  hook: -R 875517b4806a848f942811a315a5bce30804ae85 t5
> +  hook: +A 09af2ce14077a94effef208b49a718f4836d4338 t6
>    (run 'hg heads' to see heads, 'hg merge' to merge)
>    $ hg merge --tool internal:tagmerge
>    merging .hgtags
> @@ -589,11 +638,16 @@ detect merge tag conflicts
>    3 files updated, 0 files merged, 2 files removed, 0 files unresolved
>    $ hg tag t7
>    hook: tag changes detected
> +  hook: +A b325cc5b642c5b465bdbe8c09627cb372de3d47d t7
>    $ hg update -C -r 'first(sort(head()))'
>    3 files updated, 0 files merged, 2 files removed, 0 files unresolved
>    $ printf "%s %s\n" `hg log -r . --template "{node} t7"` >> .hgtags
>    $ hg commit -m "manually add conflicting t7 tag"
>    hook: tag changes detected
> +  hook: -R 929bca7b18d067cbf3844c3896319a940059d748 t2
> +  hook: +A 875517b4806a848f942811a315a5bce30804ae85 t5
> +  hook: -M b325cc5b642c5b465bdbe8c09627cb372de3d47d t7
> +  hook: +M ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
>    $ hg merge --tool internal:tagmerge
>    merging .hgtags
>    automatic .hgtags merge failed
> @@ -629,6 +683,8 @@ handle the loss of tags
>    adding f5
>    $ hg tag -f t7
>    hook: tag changes detected
> +  hook: -M ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
> +  hook: +M fd3a9e394ce3afb354a496323bf68ac1755a30de t7
>    $ hg update -r 'p1(t7)'
>    1 files updated, 0 files merged, 1 files removed, 0 files unresolved
>    $ printf '' > .hgtags
Pierre-Yves David - April 5, 2017, 11:09 p.m.
On 04/05/2017 10:54 PM, Jun Wu wrote:
> I don't think "writing things that hook *may* need to filesystem" is a good
> approach. It introduces unnecessary overhead if the hook does not need that
> information.

I do not find the overhead concerning.

The thing to keep in mind is that if they are many things to write down, 
this also means many thing changed during the transaction. So the 
overhead is likely minimal. In the tags cases, just updating the various 
tags related cache is going to be much more expensive that writing this 
to disk.

> I think a better way is to have per-hook config to let hooks explicitly
> declare what they need, before we run them.

I afraid it is too fragile. Forgetting to configure the hook properly 
will be easy and the error will likely pass silently as hook will run 
normally with the same data as if the transaction touched no tags.

Cheers,
Jun Wu - April 5, 2017, 11:23 p.m.
Excerpts from Pierre-Yves David's message of 2017-04-06 01:09:47 +0200:
> 
> On 04/05/2017 10:54 PM, Jun Wu wrote:
> > I don't think "writing things that hook *may* need to filesystem" is a good
> > approach. It introduces unnecessary overhead if the hook does not need that
> > information.
> 
> I do not find the overhead concerning.

This is from your commit message:

  This code is disabled by default as there is still various performance
  concerns.  Some require a smarter use of our existing tag caches and some
  other require rework around the transaction logic to skip execution when
  unneeded.  These performance improvement have been delayed, I would like
  to be able to experiment and stabilize the feature behavior first.

> The thing to keep in mind is that if they are many things to write down, 
> this also means many thing changed during the transaction. So the 
> overhead is likely minimal. In the tags cases, just updating the various 
> tags related cache is going to be much more expensive that writing this 
> to disk.
> 
> > I think a better way is to have per-hook config to let hooks explicitly
> > declare what they need, before we run them.
> 
> I afraid it is too fragile. Forgetting to configure the hook properly 
> will be easy and the error will likely pass silently as hook will run 
> normally with the same data as if the transaction touched no tags.

Do you mean that a global config option is less fragile?

> 
> Cheers,
>
Pierre-Yves David - April 6, 2017, 6:33 a.m.
On 04/06/2017 01:23 AM, Jun Wu wrote:
> Excerpts from Pierre-Yves David's message of 2017-04-06 01:09:47 +0200:
>>
>> On 04/05/2017 10:54 PM, Jun Wu wrote:
>>> I don't think "writing things that hook *may* need to filesystem" is a good
>>> approach. It introduces unnecessary overhead if the hook does not need that
>>> information.
>>
>> I do not find the overhead concerning.
>
> This is from your commit message:
>
>   This code is disabled by default as there is still various performance
>   concerns.  Some require a smarter use of our existing tag caches and some
>   other require rework around the transaction logic to skip execution when
>   unneeded.  These performance improvement have been delayed, I would like
>   to be able to experiment and stabilize the feature behavior first.

The part about "skip execution when unneeded" refers to the equivalent 
of the "pending" feature of the transaction. If no hook exists, the 
pending transaction data are not made available to hook. I think it make 
senses to mirror this behavior for the "changes/" data. But I don't 
think is it worth being more discriminatory in what we write once we 
start writing. They are no such discrimination for the "pending" data.

All the rest is about the implementation needing some known optimization 
before it gets out of experimental. Nothing special or relevant long 
term there.


>> The thing to keep in mind is that if they are many things to write down,
>> this also means many thing changed during the transaction. So the
>> overhead is likely minimal. In the tags cases, just updating the various
>> tags related cache is going to be much more expensive that writing this
>> to disk.
>>
>>> I think a better way is to have per-hook config to let hooks explicitly
>>> declare what they need, before we run them.
>>
>> I afraid it is too fragile. Forgetting to configure the hook properly
>> will be easy and the error will likely pass silently as hook will run
>> normally with the same data as if the transaction touched no tags.
>
> Do you mean that a global config option is less fragile?

What global option are you talking about? The feature is currently gated 
behind an experimental flag until the cache usage and transaction API is 
fixed. But that's not part of the final API (since this just an 
experimental gating).

Cheers
Yuya Nishihara - April 6, 2017, 3:27 p.m.
On Thu, 6 Apr 2017 01:09:47 +0200, Pierre-Yves David wrote:
> On 04/05/2017 10:54 PM, Jun Wu wrote:
> > I don't think "writing things that hook *may* need to filesystem" is a good
> > approach. It introduces unnecessary overhead if the hook does not need that
> > information.
> 
> I do not find the overhead concerning.
> 
> The thing to keep in mind is that if they are many things to write down, 
> this also means many thing changed during the transaction. So the 
> overhead is likely minimal. In the tags cases, just updating the various 
> tags related cache is going to be much more expensive that writing this 
> to disk.

I agree Pierre-Yves in that I/O overhead wouldn't matter. On the other hand,
I think the slowness of calling back an hg command doesn't matter, too.

As the journal extension collects similar information for bookmarks, can't
we integrate the tag tracking with the journal? Maybe a hook will receive
some pointer to select the corresponding journal entry, and run "hg journal".
Jun Wu - April 6, 2017, 6:18 p.m.
Thanks for the clarification.

My concern about performance is not writing the file, but calculating the
content to be written. I'd like to see more clarification about whether and
when this new code path triggers a full manifest read, since reading a flat
manifest is painfully slow on a large repo.

Excerpts from Pierre-Yves David's message of 2017-04-06 08:33:12 +0200:
> 
> On 04/06/2017 01:23 AM, Jun Wu wrote:
> > Excerpts from Pierre-Yves David's message of 2017-04-06 01:09:47 +0200:
> >>
> >> On 04/05/2017 10:54 PM, Jun Wu wrote:
> >>> I don't think "writing things that hook *may* need to filesystem" is a good
> >>> approach. It introduces unnecessary overhead if the hook does not need that
> >>> information.
> >>
> >> I do not find the overhead concerning.
> >
> > This is from your commit message:
> >
> >   This code is disabled by default as there is still various performance
> >   concerns.  Some require a smarter use of our existing tag caches and some
> >   other require rework around the transaction logic to skip execution when
> >   unneeded.  These performance improvement have been delayed, I would like
> >   to be able to experiment and stabilize the feature behavior first.
> 
> The part about "skip execution when unneeded" refers to the equivalent 
> of the "pending" feature of the transaction. If no hook exists, the 
> pending transaction data are not made available to hook. I think it make 
> senses to mirror this behavior for the "changes/" data. But I don't 
> think is it worth being more discriminatory in what we write once we 
> start writing. They are no such discrimination for the "pending" data.
> 
> All the rest is about the implementation needing some known optimization 
> before it gets out of experimental. Nothing special or relevant long 
> term there.
> 
> >> The thing to keep in mind is that if they are many things to write down,
> >> this also means many thing changed during the transaction. So the
> >> overhead is likely minimal. In the tags cases, just updating the various
> >> tags related cache is going to be much more expensive that writing this
> >> to disk.
> >>
> >>> I think a better way is to have per-hook config to let hooks explicitly
> >>> declare what they need, before we run them.
> >>
> >> I afraid it is too fragile. Forgetting to configure the hook properly
> >> will be easy and the error will likely pass silently as hook will run
> >> normally with the same data as if the transaction touched no tags.
> >
> > Do you mean that a global config option is less fragile?
> 
> What global option are you talking about? The feature is currently gated 
> behind an experimental flag until the cache usage and transaction API is 
> fixed. But that's not part of the final API (since this just an 
> experimental gating).
> 
> Cheers
>
Pierre-Yves David - April 7, 2017, 1:11 p.m.
On 04/06/2017 05:27 PM, Yuya Nishihara wrote:
> On Thu, 6 Apr 2017 01:09:47 +0200, Pierre-Yves David wrote:
>> On 04/05/2017 10:54 PM, Jun Wu wrote:
>>> I don't think "writing things that hook *may* need to filesystem" is a good
>>> approach. It introduces unnecessary overhead if the hook does not need that
>>> information.
>>
>> I do not find the overhead concerning.
>>
>> The thing to keep in mind is that if they are many things to write down,
>> this also means many thing changed during the transaction. So the
>> overhead is likely minimal. In the tags cases, just updating the various
>> tags related cache is going to be much more expensive that writing this
>> to disk.
>
> I agree Pierre-Yves in that I/O overhead wouldn't matter. On the other hand,
> I think the slowness of calling back an hg command doesn't matter, too.

The cost of a round-trip to Mercurial is close to a minimum of 0.1s. And 
every hooks who needs fine transaction data will have to pay it. 
Possibly multiple time. One the other hand writing down a file is a one 
time operation that do not add overhead to each hook.
So I'm still leaning toward the file solution.

> As the journal extension collects similar information for bookmarks, can't
> we integrate the tag tracking with the journal?

Journal is currently an extension, and an experimental one. I would 
prefer not to be scope bloated into solving the two points aboves before 
getting theses features done.

Journal is also tracking name movement, not transaction. We would have 
to teach journal about transaction first (that is probably something 
useful to do, but more scope bloat :-) )

> Maybe a hook will receive
> some pointer to select the corresponding journal entry, and run "hg journal".

(we could use hg journal --pending, to refer to the current transaction, 
that is something to think about while adding transaction awareness to 
journal.)
Jun Wu - April 7, 2017, 2 p.m.
Excerpts from Pierre-Yves David's message of 2017-04-07 15:55:39 +0200:
> Yes, since we do not touch the manifest, we can reuse the entry from the 
> originalctx.
> 
> In the general case, you either touch the '.hgtags' (and you know its 
> value) or you don't and you can reuse the parent value.

Okay. I think this series is good as long as it does not introduce full
manifest read before being enabled by default.

Do you mind I add comments about the manifest performance (including the
metadataonlyctx case) as a follow-up after it gets pushed?
Pierre-Yves David - April 7, 2017, 2:02 p.m.
On 04/07/2017 04:00 PM, Jun Wu wrote:
> Excerpts from Pierre-Yves David's message of 2017-04-07 15:55:39 +0200:
>> Yes, since we do not touch the manifest, we can reuse the entry from the
>> originalctx.
>>
>> In the general case, you either touch the '.hgtags' (and you know its
>> value) or you don't and you can reuse the parent value.
>
> Okay. I think this series is good as long as it does not introduce full
> manifest read before being enabled by default.
>
> Do you mind I add comments about the manifest performance (including the
> metadataonlyctx case) as a follow-up after it gets pushed?

Nope, go for it. Thanks for flagging these corner cases!

Cheers,
Yuya Nishihara - April 7, 2017, 3:25 p.m.
On Fri, 7 Apr 2017 15:11:16 +0200, Pierre-Yves David wrote:
> On 04/06/2017 05:27 PM, Yuya Nishihara wrote:
> > On Thu, 6 Apr 2017 01:09:47 +0200, Pierre-Yves David wrote:
> >> On 04/05/2017 10:54 PM, Jun Wu wrote:
> >>> I don't think "writing things that hook *may* need to filesystem" is a good
> >>> approach. It introduces unnecessary overhead if the hook does not need that
> >>> information.
> >>
> >> I do not find the overhead concerning.
> >>
> >> The thing to keep in mind is that if they are many things to write down,
> >> this also means many thing changed during the transaction. So the
> >> overhead is likely minimal. In the tags cases, just updating the various
> >> tags related cache is going to be much more expensive that writing this
> >> to disk.
> >
> > I agree Pierre-Yves in that I/O overhead wouldn't matter. On the other hand,
> > I think the slowness of calling back an hg command doesn't matter, too.
> 
> The cost of a round-trip to Mercurial is close to a minimum of 0.1s. And 
> every hooks who needs fine transaction data will have to pay it. 
> Possibly multiple time. One the other hand writing down a file is a one 
> time operation that do not add overhead to each hook.
> So I'm still leaning toward the file solution.
> 
> > As the journal extension collects similar information for bookmarks, can't
> > we integrate the tag tracking with the journal?
> 
> Journal is currently an extension, and an experimental one. I would 
> prefer not to be scope bloated into solving the two points aboves before 
> getting theses features done.
> 
> Journal is also tracking name movement, not transaction. We would have 
> to teach journal about transaction first (that is probably something 
> useful to do, but more scope bloat :-) )

Okay, so this tags.changes file describes the current transaction, which is
a different concept than the journal. I agree.

I prefer not introducing new file format which we'll have to document and
maintain forever, but I have no better idea.
Pierre-Yves David - April 7, 2017, 4:56 p.m.
On 04/07/2017 05:25 PM, Yuya Nishihara wrote:
> On Fri, 7 Apr 2017 15:11:16 +0200, Pierre-Yves David wrote:
>> On 04/06/2017 05:27 PM, Yuya Nishihara wrote:
>>> On Thu, 6 Apr 2017 01:09:47 +0200, Pierre-Yves David wrote:
>>>> On 04/05/2017 10:54 PM, Jun Wu wrote:
>>>>> I don't think "writing things that hook *may* need to filesystem" is a good
>>>>> approach. It introduces unnecessary overhead if the hook does not need that
>>>>> information.
>>>>
>>>> I do not find the overhead concerning.
>>>>
>>>> The thing to keep in mind is that if they are many things to write down,
>>>> this also means many thing changed during the transaction. So the
>>>> overhead is likely minimal. In the tags cases, just updating the various
>>>> tags related cache is going to be much more expensive that writing this
>>>> to disk.
>>>
>>> I agree Pierre-Yves in that I/O overhead wouldn't matter. On the other hand,
>>> I think the slowness of calling back an hg command doesn't matter, too.
>>
>> The cost of a round-trip to Mercurial is close to a minimum of 0.1s. And
>> every hooks who needs fine transaction data will have to pay it.
>> Possibly multiple time. One the other hand writing down a file is a one
>> time operation that do not add overhead to each hook.
>> So I'm still leaning toward the file solution.
>>
>>> As the journal extension collects similar information for bookmarks, can't
>>> we integrate the tag tracking with the journal?
>>
>> Journal is currently an extension, and an experimental one. I would
>> prefer not to be scope bloated into solving the two points aboves before
>> getting theses features done.
>>
>> Journal is also tracking name movement, not transaction. We would have
>> to teach journal about transaction first (that is probably something
>> useful to do, but more scope bloat :-) )
>
> Okay, so this tags.changes file describes the current transaction, which is
> a different concept than the journal. I agree.
>
> I prefer not introducing new file format which we'll have to document and
> maintain forever, but I have no better idea.

Can we move forward with a file for now?
The feature is experimental so we have time to think of an alternative 
before we enforce backward compatibility.

Cheers,
Pierre-Yves David - April 14, 2017, 10:03 p.m.
On 04/07/2017 05:25 PM, Yuya Nishihara wrote:
> On Fri, 7 Apr 2017 15:11:16 +0200, Pierre-Yves David wrote:
>> On 04/06/2017 05:27 PM, Yuya Nishihara wrote:
>>> On Thu, 6 Apr 2017 01:09:47 +0200, Pierre-Yves David wrote:
>>>> On 04/05/2017 10:54 PM, Jun Wu wrote:
>>>>> I don't think "writing things that hook *may* need to filesystem" is a good
>>>>> approach. It introduces unnecessary overhead if the hook does not need that
>>>>> information.
>>>>
>>>> I do not find the overhead concerning.
>>>>
>>>> The thing to keep in mind is that if they are many things to write down,
>>>> this also means many thing changed during the transaction. So the
>>>> overhead is likely minimal. In the tags cases, just updating the various
>>>> tags related cache is going to be much more expensive that writing this
>>>> to disk.
>>>
>>> I agree Pierre-Yves in that I/O overhead wouldn't matter. On the other hand,
>>> I think the slowness of calling back an hg command doesn't matter, too.
>>
>> The cost of a round-trip to Mercurial is close to a minimum of 0.1s. And
>> every hooks who needs fine transaction data will have to pay it.
>> Possibly multiple time. One the other hand writing down a file is a one
>> time operation that do not add overhead to each hook.
>> So I'm still leaning toward the file solution.
>>
>>> As the journal extension collects similar information for bookmarks, can't
>>> we integrate the tag tracking with the journal?
>>
>> Journal is currently an extension, and an experimental one. I would
>> prefer not to be scope bloated into solving the two points aboves before
>> getting theses features done.
>>
>> Journal is also tracking name movement, not transaction. We would have
>> to teach journal about transaction first (that is probably something
>> useful to do, but more scope bloat :-) )
>
> Okay, so this tags.changes file describes the current transaction, which is
> a different concept than the journal. I agree.
>
> I prefer not introducing new file format which we'll have to document and
> maintain forever, but I have no better idea.

What is the status of this series ? It seems dropped of patchwork but I 
don't think we have defined an alternative way forward.

I really would like to have something to play with in 4.2, is it 
possible to move forward with this series (it is behind an experimental 
flag, so we won't guarantee BC).

Cheers,
Yuya Nishihara - April 15, 2017, 9:15 a.m.
On Sat, 15 Apr 2017 00:03:32 +0200, Pierre-Yves David wrote:
> On 04/07/2017 05:25 PM, Yuya Nishihara wrote:
> > On Fri, 7 Apr 2017 15:11:16 +0200, Pierre-Yves David wrote:
> >> On 04/06/2017 05:27 PM, Yuya Nishihara wrote:
> >>> On Thu, 6 Apr 2017 01:09:47 +0200, Pierre-Yves David wrote:
> >>>> On 04/05/2017 10:54 PM, Jun Wu wrote:
> >>>>> I don't think "writing things that hook *may* need to filesystem" is a good
> >>>>> approach. It introduces unnecessary overhead if the hook does not need that
> >>>>> information.
> >>>>
> >>>> I do not find the overhead concerning.
> >>>>
> >>>> The thing to keep in mind is that if they are many things to write down,
> >>>> this also means many thing changed during the transaction. So the
> >>>> overhead is likely minimal. In the tags cases, just updating the various
> >>>> tags related cache is going to be much more expensive that writing this
> >>>> to disk.
> >>>
> >>> I agree Pierre-Yves in that I/O overhead wouldn't matter. On the other hand,
> >>> I think the slowness of calling back an hg command doesn't matter, too.
> >>
> >> The cost of a round-trip to Mercurial is close to a minimum of 0.1s. And
> >> every hooks who needs fine transaction data will have to pay it.
> >> Possibly multiple time. One the other hand writing down a file is a one
> >> time operation that do not add overhead to each hook.
> >> So I'm still leaning toward the file solution.
> >>
> >>> As the journal extension collects similar information for bookmarks, can't
> >>> we integrate the tag tracking with the journal?
> >>
> >> Journal is currently an extension, and an experimental one. I would
> >> prefer not to be scope bloated into solving the two points aboves before
> >> getting theses features done.
> >>
> >> Journal is also tracking name movement, not transaction. We would have
> >> to teach journal about transaction first (that is probably something
> >> useful to do, but more scope bloat :-) )
> >
> > Okay, so this tags.changes file describes the current transaction, which is
> > a different concept than the journal. I agree.
> >
> > I prefer not introducing new file format which we'll have to document and
> > maintain forever, but I have no better idea.
> 
> What is the status of this series ? It seems dropped of patchwork but I 
> don't think we have defined an alternative way forward.
> 
> I really would like to have something to play with in 4.2, is it 
> possible to move forward with this series (it is behind an experimental 
> flag, so we won't guarantee BC).

Queued the series with minor typo fixes, thanks.

As I said, we'll need to consider thoroughly how to pass this kind of
information to user hooks, but that shouldn't block these experimental
patches in.

Patch

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1015,6 +1015,25 @@  class localrepository(object):
         # and do not use caches as much as it could.  The current focus is on
         # the behavior of the feature so we disable it by default. The flag
         # will be removed when we are happy with the performance impact.
+        #
+        # Once this feature is no longer experimental move the following
+        # documentation to the appropriate help section:
+        #
+        # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
+        # tags (new or changed or deleted tags). In addition the details of
+        # these changes are made available in a file at:
+        #     ``REPOROOT/.hg/changes/tags.changes``.
+        # Make sure you check for HG_TAG_MOVED before reading that file as it
+        # might exist from a previous transaction even if no tag were touched
+        # in this one. Change are recorded in a line base format::
+        #
+        #     <action> <hex-node> <tag-name>\n
+        #
+        # Actions are defined as follow:
+        #   "-R": tag is removed,
+        #   "+A": tag is added,
+        #   "-M": tag is moved (old value),
+        #   "+M": tag is moved (new value),
         tracktags = lambda x: None
         # experimental config: experimental.hook-track-tags
         shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags',
@@ -1031,6 +1050,12 @@  class localrepository(object):
                 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
                 if changes:
                     tr2.hookargs['tag_moved'] = '1'
+                    with repo.vfs('changes/tags.changes', 'w',
+                                  atomictemp=True) as changesfile:
+                        # note: we do not register the file to the transaction
+                        # because we needs it to still exist on the transaction
+                        # is close (for txnclose hooks)
+                        tagsmod.writediff(changesfile, changes)
         def validate(tr2):
             """will run pre-closing hooks"""
             # XXX the transaction API is a bit lacking here so we take a hacky
diff --git a/mercurial/tags.py b/mercurial/tags.py
--- a/mercurial/tags.py
+++ b/mercurial/tags.py
@@ -129,6 +129,44 @@  def difftags(ui, repo, oldfnodes, newfno
     entries.sort()
     return entries
 
+def writediff(fp, difflist):
+    """write tags diff information to a file.
+
+    Data are stored with a line based format:
+
+        <action> <hex-node> <tag-name>\n
+
+    Action are defined as follow:
+       -R tag is removed,
+       +A tag is added,
+       -M tag is moved (old value),
+       +M tag is moved (new value),
+
+    Example:
+
+         +A 875517b4806a848f942811a315a5bce30804ae85 t5
+
+    See documentation of difftags output for details about the input.
+    """
+    add = '+A %s %s\n'
+    remove = '-R %s %s\n'
+    updateold = '-M %s %s\n'
+    updatenew = '+M %s %s\n'
+    for tag, old, new in difflist:
+        # translate to hex
+        if old is not None:
+            old = hex(old)
+        if new is not None:
+            new = hex(new)
+        # write to file
+        if old is None:
+            fp.write(add % (new, tag))
+        elif new is None:
+            fp.write(remove % (old, tag))
+        else:
+            fp.write(updateold % (old, tag))
+            fp.write(updatenew % (new, tag))
+
 def findglobaltags(ui, repo):
     '''Find global tags in a repo: return a tagsmap
 
diff --git a/tests/test-tag.t b/tests/test-tag.t
--- a/tests/test-tag.t
+++ b/tests/test-tag.t
@@ -11,6 +11,7 @@ 
   > # file...
   > if [ -n "\$HG_TAG_MOVED" ]; then
   >     echo 'hook: tag changes detected'
+  >     sed 's/^/hook: /' .hg/changes/tags.changes
   > fi
   > EOF
   $ chmod +x taghook.sh
@@ -37,6 +38,7 @@  specified)
 
   $ HGEDITOR=cat hg tag "bleah"
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
   $ hg history
   changeset:   1:d4f0d2909abc
   tag:         tip
@@ -86,13 +88,21 @@  specified)
 
   $ hg tag -r 0 "bleah0"
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
   $ hg tag -l -r 1 "bleah1"
   $ hg tag gack gawk gorp
   hook: tag changes detected
+  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gack
+  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gawk
+  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gorp
   $ hg tag -f gack
   hook: tag changes detected
+  hook: -M 336fccc858a4eb69609a291105009e484a6b6b8d gack
+  hook: +M 799667b6f2d9b957f73fa644a918c2df22bab58f gack
   $ hg tag --remove gack gorp
   hook: tag changes detected
+  hook: -R 799667b6f2d9b957f73fa644a918c2df22bab58f gack
+  hook: -R 336fccc858a4eb69609a291105009e484a6b6b8d gorp
 
   $ hg tag "bleah "
   abort: tag 'bleah' already exists (use -f to force)
@@ -105,8 +115,10 @@  specified)
   [255]
   $ hg tag -r 0 "  bleahbleah  "
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
   $ hg tag -r 0 " bleah bleah "
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
 
   $ cat .hgtags
   acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
@@ -136,6 +148,7 @@  tagging on a non-head revision
   [255]
   $ hg tag -f "foobar"
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
   $ cat .hgtags
   acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
   $ cat .hg/localtags
@@ -194,18 +207,23 @@  cloning local tags
   
   $ hg clone -q -rbleah1 test test1
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
   $ hg -R test1 parents --style=compact
   1[tip]   d4f0d2909abc   1970-01-01 00:00 +0000   test
     Added tag bleah for changeset acb14030fe0a
   
   $ hg clone -q -r5 test#bleah1 test2
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
+  hook: +A 336fccc858a4eb69609a291105009e484a6b6b8d gawk
   $ hg -R test2 parents --style=compact
   5[tip]   b4bb47aaff09   1970-01-01 00:00 +0000   test
     Removed tag gack, gorp
   
   $ hg clone -q -U test#bleah1 test3
   hook: tag changes detected
+  hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
   $ hg -R test3 parents --style=compact
 
   $ cd test
@@ -234,6 +252,7 @@  doesn't end with EOL
   acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
   $ hg tag newline
   hook: tag changes detected
+  hook: +A a0eea09de1eeec777b46f2085260a373b2fbc293 newline
   $ cat .hgtags; echo
   acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
   a0eea09de1eeec777b46f2085260a373b2fbc293 newline
@@ -248,6 +267,7 @@  tag and branch using same name
   $ hg tag tag-and-branch-same-name
   warning: tag tag-and-branch-same-name conflicts with existing branch name
   hook: tag changes detected
+  hook: +A fc93d2ea1cd78e91216c6cfbbf26747c10ce11ae tag-and-branch-same-name
 
 test custom commit messages
 
@@ -333,6 +353,7 @@  then, test custom commit message itself
   HG: changed .hgtags
   ====
   hook: tag changes detected
+  hook: +A 75a534207be6b03576e0c7a4fa5708d045f1c876 custom-tag
   $ hg log -l1 --template "{desc}\n"
   custom tag message
   second line
@@ -342,6 +363,7 @@  local tag with .hgtags modified
 
   $ hg tag hgtags-modified
   hook: tag changes detected
+  hook: +A 0f26aaea6f74c3ed6c4aad8844403c9ba128d23a hgtags-modified
   $ hg rollback
   repository tip rolled back to revision 13 (undo commit)
   working directory now based on revision 13
@@ -362,10 +384,16 @@  tagging when at named-branch-head that's
   (branch merge, don't forget to commit)
   $ hg ci -m 'merge named branch'
   hook: tag changes detected
+  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
+  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
+  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
+  hook: -R acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
+  hook: -R 336fccc858a4eb69609a291105009e484a6b6b8d gawk
   $ hg up 13
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg tag new-topo-head
   hook: tag changes detected
+  hook: +A 0f26aaea6f74c3ed6c4aad8844403c9ba128d23a new-topo-head
 
 tagging on null rev
 
@@ -433,6 +461,7 @@  commit hook on tag used to be run withou
   > EOF
   $ hg -R repo-tag --config hooks.commit="sh ../issue3344.sh" tag tag
   hook: tag changes detected
+  hook: +A be090ea6625635128e90f7d89df8beeb2bcc1653 tag
   pushing to $TESTTMP/repo-tag-target (glob)
   searching for changes
   adding changesets
@@ -440,6 +469,7 @@  commit hook on tag used to be run withou
   adding file changes
   added 2 changesets with 2 changes to 2 files
   hook: tag changes detected
+  hook: +A be090ea6625635128e90f7d89df8beeb2bcc1653 tag
 
 automatically merge resolvable tag conflicts (i.e. tags that differ in rank)
 create two clones with some different tags as well as some common tags
@@ -452,6 +482,7 @@  check that we can merge tags that differ
   adding f0
   $ hg tag tbase
   hook: tag changes detected
+  hook: +A 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
   $ hg up -qr '.^'
   $ hg log -r 'wdir()' -T "{latesttagdistance}\n"
   1
@@ -468,15 +499,22 @@  check that we can merge tags that differ
   adding f1
   $ hg tag t1 t2 t3
   hook: tag changes detected
+  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
+  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
+  hook: +A 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
   $ hg tag --remove t2
   hook: tag changes detected
+  hook: -R 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
   $ hg tag t5
   hook: tag changes detected
+  hook: +A 875517b4806a848f942811a315a5bce30804ae85 t5
   $ echo c2 > f2
   $ hg ci -A -m2
   adding f2
   $ hg tag -f t3
   hook: tag changes detected
+  hook: -M 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
+  hook: +M 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
 
   $ cd ../repo-automatic-tag-merge
   $ echo c3 > f3
@@ -484,6 +522,9 @@  check that we can merge tags that differ
   adding f3
   $ hg tag -f t4 t5 t6
   hook: tag changes detected
+  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
+  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
+  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
 
   $ hg up -q '.^'
   $ hg log -r 'wdir()' -T "{changessincelatesttag} changes since {latesttag}\n"
@@ -497,6 +538,7 @@  check that we can merge tags that differ
 
   $ hg tag --remove t5
   hook: tag changes detected
+  hook: -R 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
   $ echo c4 > f4
   $ hg log -r '.' -T "{changessincelatesttag} changes since {latesttag}\n"
   2 changes since t4:t6
@@ -516,8 +558,11 @@  check that we can merge tags that differ
   4 changes since t4:t6
   $ hg tag t2
   hook: tag changes detected
+  hook: +A 929bca7b18d067cbf3844c3896319a940059d748 t2
   $ hg tag -f t6
   hook: tag changes detected
+  hook: -M 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
+  hook: +M 09af2ce14077a94effef208b49a718f4836d4338 t6
 
   $ cd ../repo-automatic-tag-merge-clone
   $ hg pull
@@ -528,6 +573,10 @@  check that we can merge tags that differ
   adding file changes
   added 6 changesets with 6 changes to 3 files (+1 heads)
   hook: tag changes detected
+  hook: +A 929bca7b18d067cbf3844c3896319a940059d748 t2
+  hook: +A 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
+  hook: -R 875517b4806a848f942811a315a5bce30804ae85 t5
+  hook: +A 09af2ce14077a94effef208b49a718f4836d4338 t6
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg merge --tool internal:tagmerge
   merging .hgtags
@@ -589,11 +638,16 @@  detect merge tag conflicts
   3 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg tag t7
   hook: tag changes detected
+  hook: +A b325cc5b642c5b465bdbe8c09627cb372de3d47d t7
   $ hg update -C -r 'first(sort(head()))'
   3 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ printf "%s %s\n" `hg log -r . --template "{node} t7"` >> .hgtags
   $ hg commit -m "manually add conflicting t7 tag"
   hook: tag changes detected
+  hook: -R 929bca7b18d067cbf3844c3896319a940059d748 t2
+  hook: +A 875517b4806a848f942811a315a5bce30804ae85 t5
+  hook: -M b325cc5b642c5b465bdbe8c09627cb372de3d47d t7
+  hook: +M ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
   $ hg merge --tool internal:tagmerge
   merging .hgtags
   automatic .hgtags merge failed
@@ -629,6 +683,8 @@  handle the loss of tags
   adding f5
   $ hg tag -f t7
   hook: tag changes detected
+  hook: -M ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
+  hook: +M fd3a9e394ce3afb354a496323bf68ac1755a30de t7
   $ hg update -r 'p1(t7)'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ printf '' > .hgtags