You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Eric Gillespie <ep...@pretzelnet.org> on 2002/07/20 06:16:23 UTC

[PATCH] cvs2svn into subdirectory of existing repository

I have added two new options to cvs2svn:

  -c       create the repo before acting on it.
  -b       base directory in svn repo where files are added.

-c tells cvs2svn to open the repository rather than trying to create
it, and -b allows you to specify a subdirectory in the repository
where everything should go.

This is useful if, like me, you have kept new projects in svn and
old ones in cvs.  I plan to use this to import the cvs repository
to /cvs and then svn mv everything to their final desitinations.

I have tested this with a decent-sized repository, which added over
4000 revisions to my svn repository when converted.

On a related note, what is the plan for supporting tags and branches?
I see the cvs2svn-data.tags file is created but not yet used.  I
can devote some time to this feature; that's why i ask.  If there
is no plan, i'll see what i can come up with.

Index: ./cvs2svn.py
===================================================================
--- ./cvs2svn.py
+++ ./cvs2svn.py	Fri Jul 19 22:37:02 2002
@@ -340,16 +340,18 @@
     for f, r in self.changes:
       # compute a repository path. ensure we have a leading "/" and drop
       # the ,v from the file name
-      repos_path = '/' + relative_name(ctx.cvsroot, f[:-2])
-      #print 'DEBUG:', repos_path
+      cvs_path = '/' + relative_name(ctx.cvsroot, f[:-2])
+      svn_path = ctx.base_dir + '/' + relative_name(ctx.cvsroot, f[:-2])
+      #print 'DEBUG:', cvs_path
+      cvs_dirname = os.path.dirname(cvs_path)
+      svn_dirname = os.path.dirname(svn_path)
 
-      print '    changing %s : %s' % (r, repos_path)
+      print '    changing %s : %s' % (r, cvs_path)
 
       ### hmm. need to clarify OS path separators vs FS path separators
-      dirname = os.path.dirname(repos_path)
-      if dirname != '/':
+      if cvs_dirname != '/':
         # get the components of the path (skipping the leading '/')
-        parts = string.split(dirname[1:], os.sep)
+        parts = string.split(svn_dirname[1:], os.sep)
         for i in range(1, len(parts) + 1):
           # reassemble the pieces, adding a leading slash
           parent_dir = '/' + string.join(parts[:i], '/')
@@ -357,20 +359,20 @@
             print '    making dir:', parent_dir
             fs.make_dir(root, parent_dir, f_pool)
 
-      if fs.check_path(root, repos_path, f_pool) == svn_node_none:
+      if fs.check_path(root, svn_path, f_pool) == svn_node_none:
         created_file = 1
-        fs.make_file(root, repos_path, f_pool)
+        fs.make_file(root, svn_path, f_pool)
       else:
         created_file = 0
 
-      handler, baton = fs.apply_textdelta(root, repos_path, f_pool)
+      handler, baton = fs.apply_textdelta(root, svn_path, f_pool)
 
       # figure out the real file path for "co"
       try:
         statcache.stat(f)
       except os.error:
-        dirname, fname = os.path.split(f)
-        f = os.path.join(dirname, 'Attic', fname)
+        cvs_dirname, fname = os.path.split(f)
+        f = os.path.join(cvs_dirname, 'Attic', fname)
         statcache.stat(f)
 
       pipe = os.popen('co -q -p%s \'%s\'' % (r, f), 'r', 102400)
@@ -390,11 +392,11 @@
         # single commit, then get the contents of the previous
         # revision from co, or else the delta won't be correct because
         # the contents in the repo won't have changed yet.
-        if repos_path == lastcommit[0]:
+        if cvs_path == lastcommit[0]:
           infile2 = os.popen("co -q -p%s \'%s\'" % (lastcommit[1], f), "r", 102400)
           stream1 = util.svn_stream_from_stdio(infile2, f_pool)
         else:
-          stream1 = fs.file_contents(root, repos_path, f_pool)
+          stream1 = fs.file_contents(root, svn_path, f_pool)
 
         txstream = _delta.svn_txdelta(stream1, stream2, f_pool)
         _delta.svn_txdelta_send_txstream(txstream, handler, baton, f_pool)
@@ -410,21 +412,22 @@
       util.svn_pool_clear(f_pool)
 
       # remember what we just did, for the next iteration
-      lastcommit = (repos_path, r)
+      lastcommit = (cvs_path, r)
 
     for f, r in self.deletes:
       # compute a repository path. ensure we have a leading "/" and drop
       # the ,v from the file name
-      repos_path = '/' + relative_name(ctx.cvsroot, f[:-2])
+      cvs_path = '/' + relative_name(ctx.cvsroot, f[:-2])
+      svn_path = ctx.base_dir + '/' + relative_name(ctx.cvsroot, f[:-2])
 
-      print '    deleting %s : %s' % (r, repos_path)
+      print '    deleting %s : %s' % (r, cvs_path)
 
       # If the file was initially added on a branch, the first mainline
       # revision will be marked dead, and thus, attempts to delete it will
       # fail, since it doesn't really exist.
       if r != '1.1':
         ### need to discriminate between OS paths and FS paths
-        fs.delete(root, repos_path, f_pool)
+        fs.delete(root, svn_path, f_pool)
 
       # wipe the pool, in case the delete loads it up
       util.svn_pool_clear(f_pool)
@@ -549,7 +552,10 @@
 def pass4(ctx):
   # create the target repository
   if not ctx.dry_run:
-    t_repos = _repos.svn_repos_create(ctx.target, ctx.pool)
+    if ctx.create_repo:
+      t_repos = _repos.svn_repos_create(ctx.target, ctx.pool)
+    else:
+      t_repos = _repos.svn_repos_open(ctx.target, ctx.pool)
     t_fs = _repos.svn_repos_fs(t_repos)
   else:
     t_fs = t_repos = None
@@ -631,6 +637,8 @@
 def usage():
   print 'USAGE: %s [-n] [-v] [-s svn-repos-path] [-p pass] cvs-repos-path' \
         % os.path.basename(sys.argv[0])
+  print '  -c       create the repo before acting on it.'
+  print '  -b       base directory in svn repo where files are added.'
   print '  -n       dry run. parse CVS repos, but do not construct SVN repos.'
   print '  -v       verbose.'
   print '  -s PATH  path for new SVN repos.'
@@ -639,7 +647,7 @@
 
 def main():
   try:
-    opts, args = getopt.getopt(sys.argv[1:], 'p:s:vn')
+    opts, args = getopt.getopt(sys.argv[1:], 'p:s:vnb:c')
   except getopt.GetoptError:
     usage()
   if len(args) != 1:
@@ -649,6 +657,8 @@
   ctx = _ctx()
   ctx.cvsroot = args[0]
   ctx.target = SVNROOT
+  ctx.base_dir = '/'
+  ctx.create_repo = 0
   ctx.log_fname_base = DATAFILE
   ctx.verbose = 0
   ctx.dry_run = 0
@@ -662,6 +672,10 @@
         print 'ERROR: illegal value (%d) for starting pass. ' \
               'must be 1 through %d.' % (start_pass, len(_passes))
         sys.exit(1)
+    elif opt == '-c':
+      ctx.create_repo = 1
+    elif opt == '-b':
+      ctx.base_dir = value
     elif opt == '-v':
       ctx.verbose = 1
     elif opt == '-n':

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org