1
# Copyright (C) 2006 Canonical Ltd
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
17
# TODO: At some point, handle upgrades by just passing the whole request
18
# across to run on the server.
20
from urlparse import urlparse
22
from bzrlib import branch, errors, repository
23
from bzrlib.bzrdir import BzrDir, BzrDirFormat, RemoteBzrDirFormat
24
from bzrlib.branch import Branch, BranchFormat
25
from bzrlib.trace import mutter
26
from bzrlib.smart import client
28
# Note: RemoteBzrDirFormat is in bzrdir.py
30
class RemoteBzrDir(BzrDir):
31
"""Control directory on a remote server, accessed by HPSS."""
33
def __init__(self, transport):
34
BzrDir.__init__(self, transport, RemoteBzrDirFormat())
35
self.client = transport.get_smart_client()
36
# this object holds a delegated bzrdir that uses file-level operations
37
# to talk to the other side
38
# XXX: We should go into find_format, but not allow it to find
39
# RemoteBzrDirFormat and make sure it finds the real underlying format.
41
default_format = BzrDirFormat.get_default_format()
42
self._real_bzrdir = default_format.open(transport, _found=True)
43
path = urlparse(transport.base)[2]
44
#self._real_bzrdir._format.probe_transport(transport)
45
response = client.SmartClient(self.client).call('probe_dont_use', path)
46
if response == ('no',):
47
raise errors.NotBranchError(path=transport.base)
50
def create_repository(self, shared=False):
51
return RemoteRepository(
52
self, self._real_bzrdir.create_repository(shared=shared))
54
def create_branch(self):
55
real_branch = self._real_bzrdir.create_branch()
56
real_repository = real_branch.repository
57
remote_repository = RemoteRepository(self, real_repository)
58
return RemoteBranch(self, remote_repository, real_branch)
60
def create_workingtree(self, revision_id=None):
61
real_workingtree = self._real_bzrdir.create_workingtree(revision_id=revision_id)
62
return RemoteWorkingTree(self, real_workingtree)
64
def open_repository(self):
65
return RemoteRepository(self, self._real_bzrdir.open_repository())
67
def open_branch(self, _unsupported=False):
68
real_branch = self._real_bzrdir.open_branch(unsupported=_unsupported)
69
if real_branch.bzrdir is self._real_bzrdir:
70
# This branch accessed through the smart server, so wrap the
72
real_repository = real_branch.repository
73
remote_repository = RemoteRepository(self, real_repository)
74
return RemoteBranch(self, remote_repository, real_branch)
76
# We were redirected to somewhere else, so don't wrap.
79
def open_workingtree(self):
80
return RemoteWorkingTree(self, self._real_bzrdir.open_workingtree())
82
def get_branch_transport(self, branch_format):
83
return self._real_bzrdir.get_branch_transport(branch_format)
85
def get_repository_transport(self, repository_format):
86
return self._real_bzrdir.get_repository_transport(repository_format)
88
def get_workingtree_transport(self, workingtree_format):
89
return self._real_bzrdir.get_workingtree_transport(workingtree_format)
91
def can_convert_format(self):
92
"""Upgrading of remote bzrdirs is not supported yet."""
95
def needs_format_conversion(self, format=None):
96
"""Upgrading of remote bzrdirs is not supported yet."""
100
class RemoteRepositoryFormat(repository.RepositoryFormat):
101
"""Format for repositories accessed over rpc.
103
Instances of this repository are represented by RemoteRepository
107
_matchingbzrdir = RemoteBzrDirFormat
109
def initialize(self, a_bzrdir, shared=False):
110
assert isinstance(a_bzrdir, RemoteBzrDir)
111
return a_bzrdir.create_repository(shared=shared)
113
def open(self, a_bzrdir):
114
assert isinstance(a_bzrdir, RemoteBzrDir)
115
return a_bzrdir.open_repository()
117
def get_format_description(self):
118
return 'bzr remote repository'
120
def __eq__(self, other):
121
return self.__class__ == other.__class__
123
rich_root_data = False
126
class RemoteRepository(object):
127
"""Repository accessed over rpc.
129
For the moment everything is delegated to IO-like operations over
133
def __init__(self, remote_bzrdir, real_repository):
134
self.real_repository = real_repository
135
self.bzrdir = remote_bzrdir
136
self._format = RemoteRepositoryFormat()
138
def __getattr__(self, name):
139
# XXX: temporary way to lazily delegate everything to the real
141
return getattr(self.real_repository, name)
144
class RemoteBranchFormat(branch.BranchFormat):
146
def open(self, a_bzrdir):
147
assert isinstance(a_bzrdir, RemoteBzrDir)
148
return a_bzrdir.open_branch()
150
def initialize(self, a_bzrdir):
151
assert isinstance(a_bzrdir, RemoteBzrDir)
152
return a_bzrdir.create_branch()
155
class RemoteBranch(branch.Branch):
156
"""Branch stored on a server accessed by HPSS RPC.
158
At the moment most operations are mapped down to simple file operations.
161
def __init__(self, remote_bzrdir, remote_repository, real_branch):
162
self.bzrdir = remote_bzrdir
163
self.transport = remote_bzrdir.transport
164
self.repository = remote_repository
165
self._real_branch = real_branch
166
self._format = RemoteBranchFormat()
169
return self._real_branch.lock_read()
171
def lock_write(self):
172
return self._real_branch.lock_write()
175
return self._real_branch.unlock()
177
def break_lock(self):
178
return self._real_branch.break_lock()
180
def revision_history(self):
181
return self._real_branch.revision_history()
183
def set_revision_history(self, rev_history):
184
return self._real_branch.set_revision_history(rev_history)
186
def get_parent(self):
187
return self._real_branch.get_parent()
189
def set_parent(self, url):
190
return self._real_branch.set_parent(url)
193
class RemoteWorkingTree(object):
195
def __init__(self, remote_bzrdir, real_workingtree):
196
self.real_workingtree = real_workingtree
197
self.bzrdir = remote_bzrdir
199
def __getattr__(self, name):
200
# XXX: temporary way to lazily delegate everything to the real
202
return getattr(self.real_workingtree, name)