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
Received on Sat Jul 20 08:16:57 2002