convert: fix history topology when using hg.tagsbranch
authorPatrick Mezard <pmezard@gmail.com>
Sun, 06 Sep 2009 15:29:14 +0200
changeset 9431 d1b135f2f415
parent 9429 d8143769e1d4
child 9432 fef209e65757
child 9433 f01a22096f1f
convert: fix history topology when using hg.tagsbranch When using hg.tagsbranch, all conversions fail at transcribing the source repo topology with conversion scenarios interleaving: - initial repo conversion, - then upstream tag - then later incremental conversion The problem is caused by the usage of the last source revid as source revid for the tagnode in the revision map. On a later incremental conversion, when resolving some child commit of the true last source revid, convert will parent the nodes to the tag node. If using tagsbranch you get a bad topology where all incremental commit nodes end up in the tag branch. Analysis and test by Edouard Gomez <ed.gomez@free.fr>
hgext/convert/common.py
hgext/convert/convcmd.py
hgext/convert/hg.py
tests/test-convert-clonebranches.out
tests/test-convert-tagsbranch-topology
tests/test-convert-tagsbranch-topology.out
--- a/hgext/convert/common.py	Sat Sep 05 18:56:51 2009 +0200
+++ b/hgext/convert/common.py	Sun Sep 06 15:29:14 2009 +0200
@@ -203,6 +203,8 @@
         """Put tags into sink.
 
         tags: {tagname: sink_rev_id, ...} where tagname is an UTF-8 string.
+        Return a pair (tag_revision, tag_parent_revision), or (None, None)
+        if nothing was changed.
         """
         raise NotImplementedError()
 
--- a/hgext/convert/convcmd.py	Sat Sep 05 18:56:51 2009 +0200
+++ b/hgext/convert/convcmd.py	Sun Sep 06 15:29:14 2009 +0200
@@ -336,11 +336,14 @@
                     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:
-                    self.map[c] = nrev
+                nrev, tagsparent = self.dest.puttags(ctags)
+                if nrev and tagsparent:
+                    # write another hash correspondence to override the previous
+                    # one so we don't end up with extra tag heads
+                    tagsparents = [e for e in self.map.iteritems()
+                                   if e[1] == tagsparent]
+                    if tagsparents:
+                        self.map[tagsparents[0][0]] = nrev
 
             self.writeauthormap()
         finally:
--- a/hgext/convert/hg.py	Sat Sep 05 18:56:51 2009 +0200
+++ b/hgext/convert/hg.py	Sun Sep 06 15:29:14 2009 +0200
@@ -189,7 +189,7 @@
 
         newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
         if newlines == oldlines:
-            return None
+            return None, None
         data = "".join(newlines)
         def getfilectx(repo, memctx, f):
             return context.memfilectx(f, data, False, False, None)
@@ -201,7 +201,7 @@
                              [".hgtags"], getfilectx, "convert-repo", date,
                              extra)
         self.repo.commitctx(ctx)
-        return hex(self.repo.changelog.tip())
+        return hex(self.repo.changelog.tip()), hex(tagparent)
 
     def setfilemapmode(self, active):
         self.filemapmode = active
--- a/tests/test-convert-clonebranches.out	Sat Sep 05 18:56:51 2009 +0200
+++ b/tests/test-convert-clonebranches.out	Sun Sep 06 15:29:14 2009 +0200
@@ -18,12 +18,12 @@
 % incremental conversion
 2 c1
 pulling from branch0 into branch1
-2 changesets found
+4 changesets found
 1 c2
 pulling from branch0 into branch2
-2 changesets found
+4 changesets found
 0 c3
 pulling from branch2 into branch3
-3 changesets found
+5 changesets found
 pulling from branch1 into branch3
 1 changesets found
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-tagsbranch-topology	Sun Sep 06 15:29:14 2009 +0200
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+"$TESTDIR/hghave" git || exit 80
+
+echo "[extensions]" >> $HGRCPATH
+echo "convert=" >> $HGRCPATH
+echo 'hgext.graphlog =' >> $HGRCPATH
+echo '[convert]' >> $HGRCPATH
+echo 'hg.usebranchnames = True' >> $HGRCPATH
+echo 'hg.tagsbranch = tags-update' >> $HGRCPATH
+
+GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
+GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
+GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
+GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
+GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
+GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
+
+count=10
+action()
+{
+    GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
+    GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+    git "$@" >/dev/null 2>/dev/null || echo "git command error"
+    count=`expr $count + 1`
+}
+
+glog()
+{
+    hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+}
+
+convertrepo()
+{
+    hg convert --datesort git-repo hg-repo
+}
+
+# Build a GIT repo with at least 1 tag
+mkdir git-repo
+cd git-repo
+git init >/dev/null 2>&1
+echo a > a
+git add a
+action commit -m "rev1"
+action tag -m "tag1" tag1
+cd ..
+
+# Do a first conversion
+convertrepo
+
+# Simulate upstream  updates after first conversion
+cd git-repo
+echo b > a
+git add a
+action commit -m "rev2"
+action tag -m "tag2" tag2
+cd ..
+
+# Perform an incremental conversion
+convertrepo
+
+# Print the log
+cd hg-repo
+glog
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-tagsbranch-topology.out	Sun Sep 06 15:29:14 2009 +0200
@@ -0,0 +1,19 @@
+initializing destination hg-repo repository
+scanning source...
+sorting...
+converting...
+0 rev1
+updating tags
+scanning source...
+sorting...
+converting...
+0 rev2
+updating tags
+o  3 "update tags" files: .hgtags
+|
+| o  2 "rev2" files: a
+| |
+o |  1 "update tags" files: .hgtags
+ /
+o  0 "rev1" files: a
+