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

Georg-W. Koltermann gwk.rko at googlemail.com
Sat Jan 13 13:27:59 CST 2007


# HG changeset patch
# User Georg.Koltermann at mscsoftware.com
# Date 1168716337 -3600
# Node ID 3adb94754d118f58c2ce9a629aae69c811ceb6e9
# 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 3 of the patch, supports un-obsoletion)

diff -r 27230c29bfec -r 3adb94754d11 mercurial/localrepo.py
--- a/mercurial/localrepo.py	Sun Dec 17 05:00:22 2006 +0100
+++ b/mercurial/localrepo.py	Sat Jan 13 20:25:37 2007 +0100
@@ -259,27 +259,49 @@ 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])
+                        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 +310,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
 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3441 bytes
Desc: not available
Url : http://www.selenic.com/pipermail/mercurial-devel/attachments/20070113/380b812b/smime.bin


More information about the Mercurial-devel mailing list