59acbb72dc1b6d96542ba84c4dbe7ab299cbde6b
[jelmer/subvertpy.git] / remote.py
1 # Copyright (C) 2006-2007 Jelmer Vernooij <jelmer@samba.org>
2
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 3 of the License, or
6 # (at your option) any later version.
7
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.
12
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
16 """Subversion BzrDir formats."""
17
18 import bzrlib
19 from bzrlib import urlutils
20 from bzrlib.bzrdir import BzrDirFormat, BzrDir, format_registry
21 from bzrlib.errors import (NotBranchError, NotLocalUrl, NoRepositoryPresent,
22                            NoWorkingTree, AlreadyBranchError)
23 from bzrlib.transport.local import LocalTransport
24
25 from core import SubversionException
26 import core 
27
28 from bzrlib.plugins.svn import core
29 from bzrlib.plugins.svn.errors import NoSvnRepositoryPresent
30 from bzrlib.plugins.svn.format import get_rich_root_format, SvnRemoteFormat
31 from bzrlib.plugins.svn.repository import SvnRepository
32 from bzrlib.plugins.svn.transport import bzr_to_svn_url, get_svn_ra_transport
33
34
35 class SvnRemoteAccess(BzrDir):
36     """BzrDir implementation for Subversion connections.
37     
38     This is used for all non-checkout connections 
39     to Subversion repositories.
40     """
41     def __init__(self, _transport, _format=None):
42         """See BzrDir.__init__()."""
43         _transport = get_svn_ra_transport(_transport)
44         if _format is None:
45             _format = SvnRemoteFormat()
46         self._format = _format
47         self.transport = None
48         self.root_transport = _transport
49
50         svn_url = bzr_to_svn_url(self.root_transport.base)
51         self.svn_root_url = _transport.get_svn_repos_root()
52         self.root_url = _transport.get_repos_root()
53
54         assert svn_url.startswith(self.svn_root_url)
55         self.branch_path = svn_url[len(self.svn_root_url):]
56
57     def clone(self, url, revision_id=None, force_new_repo=False):
58         """See BzrDir.clone().
59
60         Not supported on Subversion connections.
61         """
62         raise NotImplementedError(SvnRemoteAccess.clone)
63
64     def open_repository(self, _unsupported=False):
65         """Open the repository associated with this BzrDir.
66         
67         :return: instance of SvnRepository.
68         """
69         if self.branch_path == "":
70             return SvnRepository(self, self.root_transport)
71         raise NoSvnRepositoryPresent(self.root_transport.base)
72
73     def find_repository(self):
74         """Open the repository associated with this BzrDir.
75         
76         :return: instance of SvnRepository.
77         """
78         transport = self.root_transport
79         if self.root_url != transport.base:
80             transport = transport.clone_root()
81         return SvnRepository(self, transport, self.branch_path)
82
83     def cloning_metadir(self):
84         """Produce a metadir suitable for cloning with."""
85         return bzrlib.bzrdir.format_registry.make_bzrdir("rich-root-pack")
86
87     def open_workingtree(self, _unsupported=False,
88             recommend_upgrade=True):
89         """See BzrDir.open_workingtree().
90
91         Will always raise NotLocalUrl as this 
92         BzrDir can not be associated with working trees.
93         """
94         # Working trees never exist on remote Subversion repositories
95         raise NoWorkingTree(self.root_transport.base)
96
97     def create_workingtree(self, revision_id=None, hardlink=None):
98         """See BzrDir.create_workingtree().
99
100         Will always raise NotLocalUrl as this 
101         BzrDir can not be associated with working trees.
102         """
103         raise NotLocalUrl(self.root_transport.base)
104
105     def needs_format_conversion(self, format=None):
106         """See BzrDir.needs_format_conversion()."""
107         # if the format is not the same as the system default,
108         # an upgrade is needed.
109         if format is None:
110             format = BzrDirFormat.get_default_format()
111         return not isinstance(self._format, format.__class__)
112
113     def import_branch(self, source, stop_revision=None):
114         """Create a new branch in this repository, possibly 
115         with the specified history, optionally importing revisions.
116         
117         :param source: Source branch
118         :param stop_revision: Tip of new branch
119         :return: Branch object
120         """
121         from commit import push_new
122         if stop_revision is None:
123             stop_revision = source.last_revision()
124         target_branch_path = self.branch_path.strip("/")
125         repos = self.find_repository()
126         repos.lock_write()
127         try:
128             full_branch_url = urlutils.join(repos.transport.base, 
129                                             target_branch_path)
130             if repos.transport.check_path(target_branch_path,
131                 repos.get_latest_revnum()) != core.NODE_NONE:
132                 raise AlreadyBranchError(full_branch_url)
133             push_new(repos, target_branch_path, source, stop_revision)
134         finally:
135             repos.unlock()
136         branch = self.open_branch()
137         branch.lock_write()
138         try:
139             branch.pull(source, stop_revision=stop_revision)
140         finally:
141             branch.unlock()
142         return branch
143
144     def create_branch(self):
145         """See BzrDir.create_branch()."""
146         from branch import SvnBranch
147         repos = self.find_repository()
148
149         if self.branch_path != "":
150             # TODO: Set NULL_REVISION in SVN_PROP_BZR_BRANCHING_SCHEME
151             repos.transport.mkdir(self.branch_path.strip("/"))
152         elif repos.get_latest_revnum() > 0:
153             # Bail out if there are already revisions in this repository
154             raise AlreadyBranchError(self.root_transport.base)
155         branch = SvnBranch(self.root_transport.base, repos, self.branch_path)
156         branch.bzrdir = self
157         return branch
158
159     def open_branch(self, unsupported=True):
160         """See BzrDir.open_branch()."""
161         from branch import SvnBranch
162         repos = self.find_repository()
163         branch = SvnBranch(self.root_transport.base, repos, self.branch_path)
164         branch.bzrdir = self
165         return branch
166
167     def create_repository(self, shared=False, format=None):
168         """See BzrDir.create_repository."""
169         return self.open_repository()
170
171