[PATCH 2 of 2] convert: add shallow, single branch svn conversions via svn.startrev

Patrick Mezard pmezard at gmail.com
Sat Feb 23 09:50:39 CST 2008


# HG changeset patch
# User Patrick Mezard <pmezard at gmail.com>
# Date 1203781556 -3600
# Node ID 13e8d2d9a3278cbc655a5cb76e5b5a31cbe73251
# Parent  5f175562eb96d58e6e06d6327a91fe3a3b3d9a85
convert: add shallow, single branch svn conversions via svn.startrev

diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -105,6 +105,13 @@
     --config convert.svn.trunk=trunk          (directory name)
         specify the name of the trunk branch
 
+    Source history can be retrieved starting at a specific revision,
+    instead of being integrally converted. Only single branch
+    conversions are supported.
+
+    --config convert.svn.startrev=0           (svn revision number)
+        specify start Subversion revision.
+
     Mercurial Destination
     ---------------------
 
diff --git a/hgext/convert/subversion.py b/hgext/convert/subversion.py
--- a/hgext/convert/subversion.py
+++ b/hgext/convert/subversion.py
@@ -196,6 +196,15 @@
             except ValueError:
                 raise util.Abort('svn: revision %s is not an integer' % rev)
 
+        self.startrev = self.ui.config('convert', 'svn.startrev', default=0)
+        try:
+            self.startrev = int(self.startrev)
+            if self.startrev < 0:
+                self.startrev = 0
+        except ValueError:
+            raise util.Abort(_('svn: start revision %s is not an integer') 
+                             % self.startrev)
+
         try:
             self.get_blacklist()
         except IOError, e:
@@ -283,6 +292,15 @@
                              (branch, self.revnum(brevid)))
                 self.heads.append(brevid)
 
+        if self.startrev and self.heads:
+            if len(self.heads) > 1:
+                raise util.Abort(_('svn: start revision is not supported with '
+                                   'with more than one branch'))
+            revnum = self.revnum(self.heads[0])
+            if revnum < self.startrev:
+                raise util.Abort(_('svn: no revision found after start revision %d') 
+                                 % self.startrev)
+
         return self.heads
 
     def getfile(self, file, rev):
@@ -349,7 +367,7 @@
             
         start = self.revnum(self.head)
         try:
-            for entry in get_log(self.url, [self.tags], 0, start):
+            for entry in get_log(self.url, [self.tags], self.startrev, start):
                 orig_paths, revnum, author, date, message = entry
                 for path in orig_paths:
                     if not path.startswith(self.tags+'/'):
@@ -686,10 +704,11 @@
                     # ent.copyfrom_rev may not be the actual last revision
                     previd = self.latest(newpath, ent.copyfrom_rev)
                     if previd is not None:
-                        parents = [previd]
                         prevmodule, prevnum = self.revsplit(previd)[1:]
-                        self.ui.note('found parent of branch %s at %d: %s\n' %
-                                     (self.module, prevnum, prevmodule))
+                        if prevnum >= self.startrev:
+                            parents = [previd]
+                            self.ui.note('found parent of branch %s at %d: %s\n' %
+                                         (self.module, prevnum, prevmodule))
                 else:
                     self.ui.debug("No copyfrom path, don't know what to do.\n")
 
@@ -736,11 +755,14 @@
 
         try:
             firstcset = None
-            branched = False
+            lastonbranch = False
             stream = get_log(self.url, [self.module], from_revnum, to_revnum)
             try:
                 for entry in stream:
                     paths, revnum, author, date, message = entry
+                    if revnum < self.startrev:
+                        lastonbranch = True
+                        break
                     if self.is_blacklisted(revnum):
                         self.ui.note('skipping blacklisted revision %d\n' 
                                      % revnum)
@@ -748,16 +770,16 @@
                     if paths is None:
                         self.ui.debug('revision %d has no entries\n' % revnum)
                         continue
-                    cset, branched = parselogentry(paths, revnum, author, 
-                                                   date, message)
+                    cset, lastonbranch = parselogentry(paths, revnum, author, 
+                                                       date, message)
                     if cset:
                         firstcset = cset
-                    if branched:
+                    if lastonbranch:
                         break
             finally:
                 stream.close()
 
-            if not branched and firstcset and not firstcset.parents:
+            if not lastonbranch and firstcset and not firstcset.parents:
                 # The first revision of the sequence (the last fetched one)
                 # has invalid parents if not a branch root. Find the parent
                 # revision now, if any.
diff --git a/tests/test-convert-svn-startrev b/tests/test-convert-svn-startrev
new file mode 100755
--- /dev/null
+++ b/tests/test-convert-svn-startrev
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+"$TESTDIR/hghave" svn svn-bindings || exit 80
+
+fix_path()
+{
+    tr '\\' /
+}
+
+echo "[extensions]" >> $HGRCPATH
+echo "convert = " >> $HGRCPATH
+echo "hgext.graphlog =" >> $HGRCPATH
+
+svnadmin create svn-repo
+
+svnpath=`pwd | fix_path`
+# SVN wants all paths to start with a slash. Unfortunately,
+# Windows ones don't. Handle that.
+expr $svnpath : "\/" > /dev/null
+if [ $? -ne 0 ]; then
+    svnpath='/'$svnpath
+fi
+
+echo % initial svn import
+mkdir projA
+cd projA
+mkdir trunk
+mkdir branches
+mkdir tags
+cd ..
+
+svnurl=file://$svnpath/svn-repo/projA
+svn import -m "init projA" projA $svnurl | fix_path
+
+echo % update svn repository
+svn co $svnurl A | fix_path
+cd A
+echo a > trunk/a
+echo b > trunk/b
+svn add trunk/a trunk/b
+svn ci -m createab
+svn rm trunk/b
+svn ci -m removeb
+svn up
+echo a >> trunk/a
+svn ci -m changeaa
+
+echo % branch
+svn up
+svn copy trunk branches/branch1
+echo a >> branches/branch1/a
+svn ci -m "branch, changeaaa"
+
+echo a >> branches/branch1/a
+echo c > branches/branch1/c
+svn add branches/branch1/c
+svn ci -m "addc,changeaaaa"
+svn up
+cd ..
+
+convert()
+{
+    startrev=$1
+    repopath=A-r$startrev-hg
+    hg convert --config convert.svn.startrev=$startrev \
+        --config convert.svn.trunk=branches/branch1 \
+        --config convert.svn.branches="  " \
+        --config convert.svn.tags= \
+        --datesort $svnurl $repopath
+    hg -R $repopath glog --template '#rev# #desc|firstline# files: #files#\n'
+    echo
+}
+
+echo % convert before branching point
+convert 3
+echo % convert before branching point
+convert 4
+echo % convert at branching point
+convert 5
+echo % convert last revision only
+convert 6
diff --git a/tests/test-convert-svn-startrev.out b/tests/test-convert-svn-startrev.out
new file mode 100644
--- /dev/null
+++ b/tests/test-convert-svn-startrev.out
@@ -0,0 +1,92 @@
+% initial svn import
+Adding         projA/trunk
+Adding         projA/branches
+Adding         projA/tags
+
+Committed revision 1.
+% update svn repository
+A    A/trunk
+A    A/branches
+A    A/tags
+Checked out revision 1.
+A         trunk/a
+A         trunk/b
+Adding         trunk/a
+Adding         trunk/b
+Transmitting file data ..
+Committed revision 2.
+D         trunk/b
+Deleting       trunk/b
+
+Committed revision 3.
+At revision 3.
+Sending        trunk/a
+Transmitting file data .
+Committed revision 4.
+% branch
+At revision 4.
+A         branches/branch1
+Adding         branches/branch1
+Sending        branches/branch1/a
+Transmitting file data .
+Committed revision 5.
+A         branches/branch1/c
+Sending        branches/branch1/a
+Adding         branches/branch1/c
+Transmitting file data ..
+Committed revision 6.
+At revision 6.
+% convert before branching point
+initializing destination A-r3-hg repository
+scanning source...
+sorting...
+converting...
+3 removeb
+2 changeaa
+1 branch, changeaaa
+0 addc,changeaaaa
+o  3 addc,changeaaaa files: a c
+|
+o  2 branch, changeaaa files: a
+|
+o  1 changeaa files: a
+|
+o  0 removeb files: a
+
+
+% convert before branching point
+initializing destination A-r4-hg repository
+scanning source...
+sorting...
+converting...
+2 changeaa
+1 branch, changeaaa
+0 addc,changeaaaa
+o  2 addc,changeaaaa files: a c
+|
+o  1 branch, changeaaa files: a
+|
+o  0 changeaa files: a
+
+
+% convert at branching point
+initializing destination A-r5-hg repository
+scanning source...
+sorting...
+converting...
+1 branch, changeaaa
+0 addc,changeaaaa
+o  1 addc,changeaaaa files: a c
+|
+o  0 branch, changeaaa files: a
+
+
+% convert last revision only
+initializing destination A-r6-hg repository
+scanning source...
+sorting...
+converting...
+0 addc,changeaaaa
+o  0 addc,changeaaaa files: a c
+
+


More information about the Mercurial-devel mailing list