92
# Note: RemoteBzrDirFormat is in bzrdir.py
94
class RemoteBzrDir(BzrDir, _RpcHelper):
89
# Note that RemoteBzrDirProber lives in bzrlib.bzrdir so bzrlib.remote
90
# does not have to be imported unless a remote format is involved.
92
class RemoteBzrDirFormat(_mod_bzrdir.BzrDirMetaFormat1):
93
"""Format representing bzrdirs accessed via a smart server"""
95
supports_workingtrees = False
98
super(RemoteBzrDirFormat, self).__init__()
99
# XXX: It's a bit ugly that the network name is here, because we'd
100
# like to believe that format objects are stateless or at least
101
# immutable, However, we do at least avoid mutating the name after
102
# it's returned. See <https://bugs.launchpad.net/bzr/+bug/504102>
103
self._network_name = None
106
return "%s(_network_name=%r)" % (self.__class__.__name__,
109
def get_format_description(self):
110
if self._network_name:
111
real_format = controldir.network_format_registry.get(self._network_name)
112
return 'Remote: ' + real_format.get_format_description()
113
return 'bzr remote bzrdir'
115
def get_format_string(self):
116
raise NotImplementedError(self.get_format_string)
118
def network_name(self):
119
if self._network_name:
120
return self._network_name
122
raise AssertionError("No network name set.")
124
def initialize_on_transport(self, transport):
126
# hand off the request to the smart server
127
client_medium = transport.get_smart_medium()
128
except errors.NoSmartMedium:
129
# TODO: lookup the local format from a server hint.
130
local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
131
return local_dir_format.initialize_on_transport(transport)
132
client = _SmartClient(client_medium)
133
path = client.remote_path_from_transport(transport)
135
response = client.call('BzrDirFormat.initialize', path)
136
except errors.ErrorFromSmartServer, err:
137
_translate_error(err, path=path)
138
if response[0] != 'ok':
139
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
140
format = RemoteBzrDirFormat()
141
self._supply_sub_formats_to(format)
142
return RemoteBzrDir(transport, format)
144
def parse_NoneTrueFalse(self, arg):
151
raise AssertionError("invalid arg %r" % arg)
153
def _serialize_NoneTrueFalse(self, arg):
160
def _serialize_NoneString(self, arg):
163
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
164
create_prefix=False, force_new_repo=False, stacked_on=None,
165
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
168
# hand off the request to the smart server
169
client_medium = transport.get_smart_medium()
170
except errors.NoSmartMedium:
173
# Decline to open it if the server doesn't support our required
174
# version (3) so that the VFS-based transport will do it.
175
if client_medium.should_probe():
177
server_version = client_medium.protocol_version()
178
if server_version != '2':
182
except errors.SmartProtocolError:
183
# Apparently there's no usable smart server there, even though
184
# the medium supports the smart protocol.
189
client = _SmartClient(client_medium)
190
path = client.remote_path_from_transport(transport)
191
if client_medium._is_remote_before((1, 16)):
194
# TODO: lookup the local format from a server hint.
195
local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
196
self._supply_sub_formats_to(local_dir_format)
197
return local_dir_format.initialize_on_transport_ex(transport,
198
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
199
force_new_repo=force_new_repo, stacked_on=stacked_on,
200
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
201
make_working_trees=make_working_trees, shared_repo=shared_repo,
203
return self._initialize_on_transport_ex_rpc(client, path, transport,
204
use_existing_dir, create_prefix, force_new_repo, stacked_on,
205
stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
207
def _initialize_on_transport_ex_rpc(self, client, path, transport,
208
use_existing_dir, create_prefix, force_new_repo, stacked_on,
209
stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
211
args.append(self._serialize_NoneTrueFalse(use_existing_dir))
212
args.append(self._serialize_NoneTrueFalse(create_prefix))
213
args.append(self._serialize_NoneTrueFalse(force_new_repo))
214
args.append(self._serialize_NoneString(stacked_on))
215
# stack_on_pwd is often/usually our transport
218
stack_on_pwd = transport.relpath(stack_on_pwd)
221
except errors.PathNotChild:
223
args.append(self._serialize_NoneString(stack_on_pwd))
224
args.append(self._serialize_NoneString(repo_format_name))
225
args.append(self._serialize_NoneTrueFalse(make_working_trees))
226
args.append(self._serialize_NoneTrueFalse(shared_repo))
227
request_network_name = self._network_name or \
228
_mod_bzrdir.BzrDirFormat.get_default_format().network_name()
230
response = client.call('BzrDirFormat.initialize_ex_1.16',
231
request_network_name, path, *args)
232
except errors.UnknownSmartMethod:
233
client._medium._remember_remote_is_before((1,16))
234
local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
235
self._supply_sub_formats_to(local_dir_format)
236
return local_dir_format.initialize_on_transport_ex(transport,
237
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
238
force_new_repo=force_new_repo, stacked_on=stacked_on,
239
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
240
make_working_trees=make_working_trees, shared_repo=shared_repo,
242
except errors.ErrorFromSmartServer, err:
243
_translate_error(err, path=path)
244
repo_path = response[0]
245
bzrdir_name = response[6]
246
require_stacking = response[7]
247
require_stacking = self.parse_NoneTrueFalse(require_stacking)
248
format = RemoteBzrDirFormat()
249
format._network_name = bzrdir_name
250
self._supply_sub_formats_to(format)
251
bzrdir = RemoteBzrDir(transport, format, _client=client)
253
repo_format = response_tuple_to_repo_format(response[1:])
257
repo_bzrdir_format = RemoteBzrDirFormat()
258
repo_bzrdir_format._network_name = response[5]
259
repo_bzr = RemoteBzrDir(transport.clone(repo_path),
263
final_stack = response[8] or None
264
final_stack_pwd = response[9] or None
266
final_stack_pwd = urlutils.join(
267
transport.base, final_stack_pwd)
268
remote_repo = RemoteRepository(repo_bzr, repo_format)
269
if len(response) > 10:
270
# Updated server verb that locks remotely.
271
repo_lock_token = response[10] or None
272
remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
274
remote_repo.dont_leave_lock_in_place()
276
remote_repo.lock_write()
277
policy = UseExistingRepository(remote_repo, final_stack,
278
final_stack_pwd, require_stacking)
279
policy.acquire_repository()
283
bzrdir._format.set_branch_format(self.get_branch_format())
285
# The repo has already been created, but we need to make sure that
286
# we'll make a stackable branch.
287
bzrdir._format.require_stacking(_skip_repo=True)
288
return remote_repo, bzrdir, require_stacking, policy
290
def _open(self, transport):
291
return RemoteBzrDir(transport, self)
293
def __eq__(self, other):
294
if not isinstance(other, RemoteBzrDirFormat):
296
return self.get_format_description() == other.get_format_description()
298
def __return_repository_format(self):
299
# Always return a RemoteRepositoryFormat object, but if a specific bzr
300
# repository format has been asked for, tell the RemoteRepositoryFormat
301
# that it should use that for init() etc.
302
result = RemoteRepositoryFormat()
303
custom_format = getattr(self, '_repository_format', None)
305
if isinstance(custom_format, RemoteRepositoryFormat):
308
# We will use the custom format to create repositories over the
309
# wire; expose its details like rich_root_data for code to
311
result._custom_format = custom_format
314
def get_branch_format(self):
315
result = _mod_bzrdir.BzrDirMetaFormat1.get_branch_format(self)
316
if not isinstance(result, RemoteBranchFormat):
317
new_result = RemoteBranchFormat()
318
new_result._custom_format = result
320
self.set_branch_format(new_result)
324
repository_format = property(__return_repository_format,
325
_mod_bzrdir.BzrDirMetaFormat1._set_repository_format) #.im_func)
328
class RemoteBzrDir(_mod_bzrdir.BzrDir, _RpcHelper):
95
329
"""Control directory on a remote server, accessed via bzr:// or similar."""
97
331
def __init__(self, transport, format, _client=None, _force_probe=False):