Patchwork [3,of,4,NEW-CONCEPT] track-tags: compute the actual differences between tags pre/post transaction

login
register
mail settings
Submitter Pierre-Yves David
Date March 30, 2017, 3:03 p.m.
Message ID <2dcaa99d616056116626.1490886221@nodosa.octopoid.net>
Download mbox | patch
Permalink /patch/19847/
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 1490688895 -7200
#      Tue Mar 28 10:14:55 2017 +0200
# Node ID 2dcaa99d6160561166269f192a89b25f84fd4667
# Parent  25952f350daaae03506991d566c8de170b5db094
# 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 2dcaa99d6160
track-tags: compute the actual differences between tags pre/post transaction

We now compute the proper actuall differences between tags before and after the
transaction. This catch a couple of false positives in the tests.

The compute the full difference since we are about to make this data available
to hooks in the next changeset.

Patch

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