track-tags: write all tag changes to a file
The tag changes information we compute is now written to disk. This gives
hooks full access to that data.
The format picked for that file uses 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 examples:
* 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.
--- a/mercurial/localrepo.py Tue Mar 28 10:14:55 2017 +0200
+++ b/mercurial/localrepo.py Tue Mar 28 10:15:02 2017 +0200
@@ -1015,6 +1015,25 @@
# 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. Changes 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 @@
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
--- a/mercurial/tags.py Tue Mar 28 10:14:55 2017 +0200
+++ b/mercurial/tags.py Tue Mar 28 10:15:02 2017 +0200
@@ -129,6 +129,44 @@
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
--- a/tests/test-tag.t Tue Mar 28 10:14:55 2017 +0200
+++ b/tests/test-tag.t Tue Mar 28 10:15:02 2017 +0200
@@ -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 @@
$ HGEDITOR=cat hg tag "bleah"
hook: tag changes detected
+ hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
$ hg history
changeset: 1:d4f0d2909abc
tag: tip
@@ -86,13 +88,21 @@
$ 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 @@
[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 @@
[255]
$ hg tag -f "foobar"
hook: tag changes detected
+ hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
$ cat .hgtags
acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
$ cat .hg/localtags
@@ -194,18 +207,23 @@
$ 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 @@
acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
$ hg tag newline
hook: tag changes detected
+ hook: +A a0eea09de1eeec777b46f2085260a373b2fbc293 newline
$ cat .hgtags; echo
acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
a0eea09de1eeec777b46f2085260a373b2fbc293 newline
@@ -248,6 +267,7 @@
$ 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 @@
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 @@
$ 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 @@
(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 @@
> 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 @@
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 @@
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 @@
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 @@
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 @@
$ 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 @@
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 @@
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 @@
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 @@
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