Make the tags algorithm smarter
authorMatt Mackall <mpm@selenic.com>
Wed, 14 Mar 2007 18:47:29 -0500
changeset 4211 e29f2db5ab18
parent 4210 caff92047e87
child 4212 6c0be67c2b27
Make the tags algorithm smarter
mercurial/localrepo.py
tests/test-tags
tests/test-tags.out
--- a/mercurial/localrepo.py	Wed Mar 14 16:40:47 2007 -0500
+++ b/mercurial/localrepo.py	Wed Mar 14 18:47:29 2007 -0500
@@ -260,10 +260,12 @@
         if self.tagscache:
             return self.tagscache
 
-        self.tagscache = {}
+        globaltags = {}
+        globalover = {}
 
         def readtags(lines, fn):
             filetags = {}
+            fileover = {}
             count = 0
 
             def warn(msg):
@@ -287,11 +289,30 @@
                 if bin_n not in self.changelog.nodemap:
                     warn(_("tag '%s' refers to unknown node") % key)
                     continue
-                self.tagscache[key] = bin_n
+
+                h = {}
+                if key in filetags:
+                    n, h = filetags[key]
+                    h[n] = True
+                filetags[key] = (bin_n, h)
 
-        # read the tags file from each head, ending with the tip,
-        # and add each tag found to the map, with "newer" ones
-        # taking precedence
+            for k,nh in filetags.items():
+                if k not in globaltags:
+                    globaltags[k] = nh
+                    continue
+                # we prefer the global tag if:
+                #  it supercedes us OR
+                #  mutual supercedes and it has a higher rank
+                # otherwise we win because we're tip-most
+                an, ah = nh
+                bn, bh = globaltags[k]
+                if bn != an and an in bh and \
+                   (bn not in ah or len(bh) > len(ah)):
+                    an = bn
+                ah.update(bh)
+                globaltags[k] = an, ah
+
+        # read the tags file from each head, ending with the tip
         f = None
         for rev, node, fnode in self._hgtagsnodes():
             f = (f and f.filectx(fnode) or
@@ -306,6 +327,10 @@
         except IOError:
             pass
 
+        self.tagscache = {}
+        for k,nh in globaltags.items():
+            n = nh[0]
+            self.tagscache[k] = n
         self.tagscache['tip'] = self.changelog.tip()
 
         return self.tagscache
--- a/tests/test-tags	Wed Mar 14 16:40:47 2007 -0500
+++ b/tests/test-tags	Wed Mar 14 18:47:29 2007 -0500
@@ -63,7 +63,7 @@
 hg tags
 hg tip
 
-# tags from later heads override previous ones
+# test tag precedence rules
 cd ..
 hg init t2
 cd t2
--- a/tests/test-tags.out	Wed Mar 14 16:40:47 2007 -0500
+++ b/tests/test-tags.out	Wed Mar 14 18:47:29 2007 -0500
@@ -41,4 +41,4 @@
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 tip                                4:36195b728445
-bar                                0:b409d9da318e
+bar                                1:b204a97e6e8d