[PATCH 1 of 1] ( take 4 ) change tag computation to avoid surprises in case of multiple heads

Georg-W. Koltermann gwk.rko at googlemail.com
Sat Jan 13 14:11:09 CST 2007


# HG changeset patch
# User Georg.Koltermann at mscsoftware.com
# Date 1168718842 -3600
# Node ID 93ab992f68c4b0372801a2396de4276a13211542
# Parent  27230c29bfec36d5540fbe1c976810aefecfd1d2
FEATUREFIX: Change tag computation so that obsoleted tag lines (those lines in a tags file that are
superseded by subsequent lines of the same tag) are ignored.

Previously for any given tag the last entry in the tipmost tags file would win.  This caused
considerable surprises when a new tip was created off a historic version containing an
older .tags file.

With this change, lines that are superseded by newer entries in .tags files (called
obsoleted lines) are ignored in the process of tag computation. So creating a new
tip off a historic version will only result in exposing a new obsoleted tag entry which
is ignored, so having no effect on the final tag value.

(take 4 of the patch, supports un-obsoletion, + bugfix)

diff -r 27230c29bfec -r 93ab992f68c4 mercurial/localrepo.py
--- a/mercurial/localrepo.py	Sun Dec 17 05:00:22 2006 +0100
+++ b/mercurial/localrepo.py	Sat Jan 13 21:07:22 2007 +0100
@@ -259,27 +259,50 @@ class localrepository(repo.repository):
         '''return a mapping of tag to node'''
         if not self.tagscache:
             self.tagscache = {}
-
-            def parsetag(line, context):
-                if not line:
-                    return
-                s = l.split(" ", 1)
-                if len(s) != 2:
-                    self.ui.warn(_("%s: cannot parse entry\n") % context)
-                    return
-                node, key = s
-                key = util.tolocal(key.strip()) # stored in UTF-8
-                try:
-                    bin_n = bin(node)
-                except TypeError:
-                    self.ui.warn(_("%s: node '%s' is not well formed\n") %
-                                 (context, node))
-                    return
-                if bin_n not in self.changelog.nodemap:
-                    self.ui.warn(_("%s: tag '%s' refers to unknown node\n") %
-                                 (context, key))
-                    return
-                self.tagscache[key] = bin_n
+            obsoletetagvalues = {}
+
+            def readtags(lines, islocal, fn):
+                currenttags = {}
+                currentobsoletes = {}
+                
+                def parsetag(line, context):
+                    if not line:
+                        return
+                    s = l.split(" ", 1)
+                    if len(s) != 2:
+                        self.ui.warn(_("%s: cannot parse entry\n") % context)
+                        return
+                    node, key = s
+                    key = util.tolocal(key.strip()) # stored in UTF-8
+                    try:
+                        bin_n = bin(node)
+                    except TypeError:
+                        self.ui.warn(_("%s: node '%s' is not well formed\n") %
+                                     (context, node))
+                        return
+                    if bin_n not in self.changelog.nodemap:
+                        self.ui.warn(_("%s: tag '%s' refers to unknown node\n") %
+                                     (context, key))
+                        return
+                    if key in currenttags:
+                        previousvalue = (key, currenttags[key])
+                        del currenttags[key]
+                        currentobsoletes[previousvalue] = True
+                        obsoletetagvalues[previousvalue] = True
+                    newvalue = (key, bin_n)
+                    if newvalue in currentobsoletes:
+                        del currentobsoletes[newvalue]
+                        del obsoletetagvalues[newvalue]
+                    if not newvalue in obsoletetagvalues:
+                        currenttags[key] = bin_n
+                        
+                count = 0
+                for l in lines:
+                    count += 1
+                    if (islocal): l = util.fromlocal(l)
+                    parsetag(l, _("%s, line %d") % (fn, count))
+                self.tagscache.update(currenttags)
+                
 
             # read the tags file from each head, ending with the tip,
             # and add each tag found to the map, with "newer" ones
@@ -288,20 +311,13 @@ class localrepository(repo.repository):
             for rev, node, fnode in self._hgtagsnodes():
                 f = (f and f.filectx(fnode) or
                      self.filectx('.hgtags', fileid=fnode))
-                count = 0
-                for l in f.data().splitlines():
-                    count += 1
-                    parsetag(l, _("%s, line %d") % (str(f), count))
+                readtags(f.data().splitlines(), False, str(f))
 
             try:
                 f = self.opener("localtags")
-                count = 0
-                for l in f:
-                    # localtags are stored in the local character set
-                    # while the internal tag table is stored in UTF-8
-                    l = util.fromlocal(l)
-                    count += 1
-                    parsetag(l, _("localtags, line %d") % count)
+                # localtags are stored in the local character set
+                # while the internal tag table is stored in UTF-8
+                readtags(f, True, "localtags")
             except IOError:
                 pass
 




More information about the Mercurial-devel mailing list