diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1028,7 +1028,8 @@ class localrepository(object): newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads) # notes: we compare lists here. # As we do it only once buiding set would not be cheaper - if oldfnodes != newfnodes: + changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes) + if changes: tr2.hookargs['tag_moved'] = '1' def validate(tr2): """will run pre-closing hooks""" diff --git a/mercurial/tags.py b/mercurial/tags.py --- a/mercurial/tags.py +++ b/mercurial/tags.py @@ -90,6 +90,45 @@ def fnoderevs(ui, repo, revs): fnodes = _filterfnodes(fnodes, nodes) return fnodes +def _nulltonone(value): + """convert nullid to None + + For tag value, nullid means "deleted". This small utility function helps + translating that to None.""" + if value == nullid: + return None + return value + +def difftags(ui, repo, oldfnodes, newfnodes): + """list differences between tags expressed in two set of file-nodes + + The list contains entries in the form: (tagname, oldvalue, new value). + None is used to expressed missing value: + ('foo', None, 'abcd') is a new tag, + ('bar', 'ef01', None) is a deletion, + ('baz', 'abcd', 'ef01') is a tag movement. + """ + if oldfnodes == newfnodes: + return [] + oldtags = _tagsfromfnodes(ui, repo, oldfnodes) + newtags = _tagsfromfnodes(ui, repo, newfnodes) + + # list of (tag, old, new): None means missing + entries = [] + for tag, (new, __) in newtags.items(): + new = _nulltonone(new) + old, __ = oldtags.pop(tag, (None, None)) + old = _nulltonone(old) + if old != new: + entries.append((tag, old, new)) + # handle deleted tags + for tag, (old, __) in oldtags.items(): + old = _nulltonone(old) + if old is not None: + entries.append((tag, old, None)) + entries.sort() + return entries + 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 @@ -230,7 +230,6 @@ doesn't end with EOL > f = file('.hgtags', 'w'); f.write(last); f.close() > EOF $ hg ci -m'broken manual edit of .hgtags' - hook: tag changes detected $ cat .hgtags; echo acb14030fe0a21b60322c440ad2d20cf7685a376 foobar $ hg tag newline @@ -635,7 +634,6 @@ handle the loss of tags $ printf '' > .hgtags $ hg commit -m 'delete all tags' created new head - hook: tag changes detected $ hg log -r 'max(t7::)' changeset: 17:ffe462b50880 user: test