convert: tell the source repository when a rev has been converted
authorBryan O'Sullivan <bos@serpentine.com>
Mon, 26 Nov 2007 17:23:20 -0800
changeset 5554 2147a734dcf9
parent 5553 ee80591f5636
child 5555 86405ff6d74b
convert: tell the source repository when a rev has been converted This lets us roundtrip changes between svn and hg.
hgext/convert/__init__.py
hgext/convert/common.py
hgext/convert/hg.py
hgext/convert/subversion.py
tests/test-convert-hg-svn
tests/test-convert-hg-svn.out
--- a/hgext/convert/__init__.py	Mon Nov 26 14:01:31 2007 -0800
+++ b/hgext/convert/__init__.py	Mon Nov 26 17:23:20 2007 -0800
@@ -227,6 +227,7 @@
                         self.dest.copyfile(copyf, f)
 
         newnode = self.dest.putcommit(filenames, parents, commit)
+        self.source.converted(rev, newnode)
         self.map[rev] = newnode
 
     def convert(self):
--- a/hgext/convert/common.py	Mon Nov 26 14:01:31 2007 -0800
+++ b/hgext/convert/common.py	Mon Nov 26 17:23:20 2007 -0800
@@ -115,6 +115,11 @@
         """
         raise NotImplementedError()
 
+    def converted(self, rev, sinkrev):
+        '''Notify the source that a revision has been converted.'''
+        pass
+
+
 class converter_sink(object):
     """Conversion sink (target) interface"""
 
--- a/hgext/convert/hg.py	Mon Nov 26 14:01:31 2007 -0800
+++ b/hgext/convert/hg.py	Mon Nov 26 17:23:20 2007 -0800
@@ -24,8 +24,6 @@
         if os.path.isdir(path) and len(os.listdir(path)) > 0:
             try:
                 self.repo = hg.repository(self.ui, path)
-                ui.status(_('destination %s is a Mercurial repository\n') %
-                          path)
             except hg.RepoError, err:
                 ui.print_exc()
                 raise NoRepo(err.args[0])
@@ -195,6 +193,7 @@
         self.lastrev = None
         self.lastctx = None
         self._changescache = None
+        self.convertfp = None
 
     def changectx(self, rev):
         if self.lastrev != rev:
@@ -258,3 +257,9 @@
 
         return changes[0] + changes[1] + changes[2]
 
+    def converted(self, rev, destrev):
+        if self.convertfp is None:
+            self.convertfp = open(os.path.join(self.path, '.hg', 'shamap'),
+                                  'a')
+        self.convertfp.write('%s %s\n' % (destrev, rev))
+        self.convertfp.flush()
--- a/hgext/convert/subversion.py	Mon Nov 26 14:01:31 2007 -0800
+++ b/hgext/convert/subversion.py	Mon Nov 26 17:23:20 2007 -0800
@@ -154,6 +154,12 @@
         self.head = self.revid(self.last_changed)
         self._changescache = None
 
+        if os.path.exists(os.path.join(url, '.svn/entries')):
+            self.wc = url
+        else:
+            self.wc = None
+        self.convertfp = None
+
     def setrevmap(self, revmap):
         lastrevs = {}
         for revid in revmap.iterkeys():
@@ -298,6 +304,15 @@
             self.ui.note('no tags found at revision %d\n' % start)
         return tags
 
+    def converted(self, rev, destrev):
+        if not self.wc:
+            return
+        if self.convertfp is None:
+            self.convertfp = open(os.path.join(self.wc, '.svn', 'hg-shamap'),
+                                  'a')
+        self.convertfp.write('%s %d\n' % (destrev, self.revnum(rev)))
+        self.convertfp.flush()
+
     # -- helper functions --
 
     def revid(self, revnum, module=None):
@@ -749,6 +764,9 @@
             fp.close()
             util.set_exec(hook, True)
 
+        xport = transport.SvnRaTransport(url=geturl(path))
+        self.uuid = svn.ra.get_uuid(xport.ra)
+
     def wjoin(self, *names):
         return os.path.join(self.wc, *names)
 
@@ -837,10 +855,13 @@
     def addchild(self, parent, child):
         self.childmap[parent] = child
 
+    def revid(self, rev):
+        return u"svn:%s@%s" % (self.uuid, rev)
+        
     def putcommit(self, files, parents, commit):
         for parent in parents:
             try:
-                return self.childmap[parent]
+                return self.revid(self.childmap[parent])
             except KeyError:
                 pass
         entries = set(self.delete)
@@ -873,7 +894,7 @@
                          revprop=True, revision=rev)
             for parent in parents:
                 self.addchild(parent, rev)
-            return rev
+            return self.revid(rev)
         finally:
             os.unlink(messagefile)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-hg-svn	Mon Nov 26 17:23:20 2007 -0800
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+"$TESTDIR/hghave" svn svn-bindings || exit 80
+
+fix_path()
+{
+    tr '\\' /
+}
+
+echo "[extensions]" >> $HGRCPATH
+echo "convert = " >> $HGRCPATH
+
+svnpath=`pwd`/svn-repo
+svnadmin create $svnpath
+
+cat > $svnpath/hooks/pre-revprop-change <<'EOF'
+#!/bin/sh
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
+if [ "$ACTION" = "A" -a "$PROPNAME" = "hg:convert-branch" ]; then exit 0; fi
+if [ "$ACTION" = "A" -a "$PROPNAME" = "hg:convert-rev" ]; then exit 0; fi
+
+echo "Changing prohibited revision property" >&2
+exit 1
+EOF
+chmod +x $svnpath/hooks/pre-revprop-change
+
+svnurl=file://$svnpath
+svn co $svnurl $svnpath-wc
+
+cd $svnpath-wc
+echo a > a
+svn add a
+svn ci -m'added a' a
+
+cd ..
+
+echo % initial roundtrip
+hg convert -s svn -d hg $svnpath-wc $svnpath-hg | grep -v initializing
+hg convert -s hg -d svn $svnpath-hg $svnpath-wc
+
+echo % second roundtrip should do nothing
+hg convert -s svn -d hg $svnpath-wc $svnpath-hg
+hg convert -s hg -d svn $svnpath-hg $svnpath-wc
+
+echo % new hg rev
+
+hg clone $svnpath-hg $svnpath-work
+echo b > $svnpath-work/b
+hg --cwd $svnpath-work add b
+hg --cwd $svnpath-work ci -mb
+
+echo % echo hg to svn
+hg --cwd $svnpath-hg pull -q $svnpath-work
+hg convert -s hg -d svn $svnpath-hg $svnpath-wc
+
+echo % svn back to hg should do nothing
+hg convert -s svn -d hg $svnpath-wc $svnpath-hg
+echo % hg back to svn should do nothing
+hg convert -s hg -d svn $svnpath-hg $svnpath-wc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-hg-svn.out	Mon Nov 26 17:23:20 2007 -0800
@@ -0,0 +1,35 @@
+Checked out revision 0.
+A         a
+Adding         a
+Transmitting file data .
+Committed revision 1.
+% initial roundtrip
+scanning source...
+sorting...
+converting...
+0 added a
+scanning source...
+sorting...
+converting...
+% second roundtrip should do nothing
+scanning source...
+sorting...
+converting...
+scanning source...
+sorting...
+converting...
+% new hg rev
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% echo hg to svn
+scanning source...
+sorting...
+converting...
+0 b
+% svn back to hg should do nothing
+scanning source...
+sorting...
+converting...
+% hg back to svn should do nothing
+scanning source...
+sorting...
+converting...