1 # Copyright (C) 2005-2007 by Jelmer Vernooij
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 from bzrlib.plugin import load_plugins
23 from bzrlib.bzrdir import BzrDir, BzrDirFormat
24 from bzrlib.branch import Branch
25 from bzrlib.errors import BzrError, NotBranchError, NoSuchFile, NoRepositoryPresent
26 import bzrlib.osutils as osutils
27 from bzrlib.progress import DummyProgress
28 from bzrlib.repository import Repository
29 from bzrlib.trace import info, mutter
30 from bzrlib.transport import get_transport
31 import bzrlib.urlutils as urlutils
32 from bzrlib.ui import ui_factory
34 from format import SvnRemoteAccess, SvnFormat
35 from repository import SvnRepository
36 from transport import SvnRaTransport
40 def transport_makedirs(transport, location_url):
41 needed = [(transport, transport.relpath(location_url))]
44 transport, relpath = needed[-1]
45 transport.mkdir(relpath)
50 needed.append((transport, urlutils.dirname(relpath)))
53 class NotDumpFile(BzrError):
54 _fmt = """%(dumpfile)s is not a dump file."""
55 def __init__(self, dumpfile):
56 self.dumpfile = dumpfile
59 def load_dumpfile(dumpfile, outputdir):
61 from svn.core import SubversionException
62 from cStringIO import StringIO
63 repos = svn.repos.svn_repos_create(outputdir, '', '', None, None)
66 svn.repos.load_fs2(repos, file, StringIO(),
67 svn.repos.load_uuid_default, '', 0, 0, None)
68 except SubversionException, (svn.core.SVN_ERR_STREAM_MALFORMED_DATA, _):
69 raise NotDumpFile(dumpfile)
73 def convert_repository(url, output_url, scheme, create_shared_repo=True,
74 working_trees=False, all=False):
75 assert not all or create_shared_repo
78 if os.path.isfile(url):
79 tmp_repos = tempfile.mkdtemp(prefix='bzr-svn-dump-')
80 mutter('loading dumpfile %r to %r' % (url, tmp_repos))
81 load_dumpfile(url, tmp_repos)
87 to_transport = get_transport(output_url)
89 if dirs.has_key(path):
91 nt = to_transport.clone(path)
93 dirs[path] = BzrDir.open_from_transport(nt)
94 except NotBranchError:
95 transport_makedirs(to_transport, urlutils.join(to_transport.base, path))
96 dirs[path] = BzrDirFormat.get_default_format().initialize_on_transport(nt)
100 source_repos = SvnRepository.open(url)
101 source_repos.set_branching_scheme(scheme)
103 if create_shared_repo:
105 target_repos = get_dir("").open_repository()
106 assert scheme.is_branch("") or scheme.is_tag("") or target_repos.is_shared()
107 except NoRepositoryPresent:
108 target_repos = get_dir("").create_repository(shared=True)
109 target_repos.set_make_working_trees(working_trees)
111 source_repos.copy_content_into(target_repos)
113 pb = ui_factory.nested_progress_bar()
115 branches = source_repos.find_branches(pb=pb)
116 existing_branches = filter(lambda (bp, revnum, exists): exists,
121 pb = ui_factory.nested_progress_bar()
125 for (branch, revnum, exists) in existing_branches:
126 if source_repos.transport.check_path(branch, revnum) == svn.core.svn_node_file:
128 pb.update("%s:%d" % (branch, revnum), i, len(existing_branches))
129 revid = source_repos.generate_revision_id(revnum, branch)
131 target_dir = get_dir(branch)
132 if not create_shared_repo:
134 target_dir.open_repository()
135 except NoRepositoryPresent:
136 target_dir.create_repository()
138 target_branch = target_dir.open_branch()
139 except NotBranchError:
140 target_branch = target_dir.create_branch()
141 if not revid in target_branch.revision_history():
142 source_branch = Branch.open(urlutils.join(url, branch))
143 # Check if target_branch contains a subset of
144 # source_branch. If that is not the case,
145 # assume that source_branch has been replaced
146 # and remove target_branch
147 if not target_branch.last_revision() in \
148 source_branch.revision_history():
149 target_branch.set_revision_history([])
151 target_branch.pull(source_branch)
152 if working_trees and not target_dir.has_workingtree():
153 target_dir.create_workingtree()
159 osutils.rmtree(tmp_repos)