[PATCH] Make convert-repo put tags on the branches where they apply

Brendan Cully brendan at kublai.com
Mon Feb 26 22:28:19 UTC 2007


The attached version removes the sys.path detritus, and corrects a bug
where the tags would slide forward to include the commit that created
the tag.
-------------- next part --------------
# HG changeset patch
# User Brendan Cully <brendan at kublai.com>
# Date 1172528761 28800
# Node ID b686d261e3ccc036f037b1deba7f07abf2593e2c
# Parent  eb0967c6e77b66a1096584c882725cb779caf90f
Make convert-repo put tags on the branches where they apply

diff -r eb0967c6e77b -r b686d261e3cc contrib/convert-repo
--- a/contrib/convert-repo	Mon Feb 26 21:57:33 2007 +0100
+++ b/contrib/convert-repo	Mon Feb 26 14:26:01 2007 -0800
@@ -32,6 +32,7 @@ class NoRepo(Exception): pass
 
 class commit:
     def __init__(self, **parts):
+        self.branch = None
         for x in "author date desc parents".split():
             if not x in parts:
                 abort("commit missing field %s\n" % x)
@@ -417,10 +418,8 @@ class convert_mercurial:
 
         text = commit.desc
         extra = {}
-        try:
+        if commit.branch is not None:
             extra["branch"] = commit.branch
-        except AttributeError:
-            pass
 
         while parents:
             p1 = p2
@@ -432,10 +431,11 @@ class convert_mercurial:
 
         return p2
 
-    def puttags(self, tags):
-        try:
-            old = self.repo.wfile(".hgtags").read()
-            oldlines = old.splitlines(1)
+    def puttags(self, tags, rev, branch):
+        rev = hg.bin(rev)
+        try:
+            old = self.repo.filectx(".hgtags", rev)
+            oldlines = old.data().splitlines(1)
             oldlines.sort()
         except:
             oldlines = []
@@ -455,8 +455,11 @@ class convert_mercurial:
             f.close()
             if not oldlines: self.repo.add([".hgtags"])
             date = "%s 0" % int(time.mktime(time.gmtime()))
+            extra = {}
+            if branch:
+                extra['branch'] = branch
             self.repo.rawcommit([".hgtags"], "update tags", "convert-repo",
-                                date, self.repo.changelog.tip(), hg.nullid)
+                                date, rev, hg.nullid, extra=extra)
             return hg.hex(self.repo.changelog.tip())
 
 converters = [convert_cvs, convert_git, convert_mercurial]
@@ -481,6 +484,8 @@ class convert:
         self.commitcache = {}
 
         self.map = {}
+        # to avoid applying tags to synthesized tag nodes 
+        self.tagmap = {}
         try:
             for l in file(self.mapfile):
                 sv, dv = l[:-1].split()
@@ -560,6 +565,29 @@ class convert:
 
         return s
 
+    def ancestors(self, rev):
+        visit = [rev]
+        seen = {rev: 1}
+        while visit:
+            n = visit.pop(0)
+            for p in self.commitcache[n].parents:
+                if p not in seen:
+                    visit.append(p)
+                    seen[p] = 1
+        return seen.keys()
+            
+    def branchtags(self, tags, rev):
+        'Find tags for already-committed nodes on the same branch as rev'
+        ctags = {}
+        parents = self.ancestors(rev)
+        for name, tagrev in tags.iteritems():
+            if tagrev in self.map and tagrev in parents:
+                if tagrev in self.tagmap:
+                    ctags[name] = self.tagmap[tagrev]
+                else:
+                    ctags[name] = self.map[tagrev]
+        return ctags
+
     def copy(self, rev):
         c = self.commitcache[rev]
         files = self.source.getchanges(rev)
@@ -588,6 +616,7 @@ class convert:
         c = None
 
         status("converting...\n")
+        tags = self.source.gettags()
         for c in t:
             num -= 1
             desc = self.commitcache[c].desc
@@ -595,20 +624,15 @@ class convert:
                 desc = desc.splitlines()[0]
             status("%d %s\n" % (num, desc))
             self.copy(c)
-
-        tags = self.source.gettags()
-        ctags = {}
-        for k in tags:
-            v = tags[k]
-            if v in self.map:
-                ctags[k] = self.map[v]
-
-        if c and ctags:
-            nrev = self.dest.puttags(ctags)
-            # write another hash correspondence to override the previous
-            # one so we don't end up with extra tag heads
-            if nrev:
-                file(self.mapfile, "a").write("%s %s\n" % (c, nrev))
+            if c in tags.values():
+                tbranch = self.commitcache[c].branch
+                nrev = self.dest.puttags(self.branchtags(tags, c), self.map[c], tbranch)
+                # write another hash correspondence to override the previous
+                # one so we don't end up with extra tag heads
+                if nrev:
+                    self.tagmap[c] = self.map[c]
+                    self.map[c] = nrev
+                    file(self.mapfile, "a").write("%s %s\n" % (c, nrev))
 
 def command(src, dest=None, mapfile=None, **opts):
     srcc = converter(src)


More information about the Mercurial-devel mailing list