31
repository as _mod_repository,
33
31
revision as _mod_revision,
37
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
34
from bzrlib.branch import BranchReferenceFormat
38
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
39
36
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
40
37
from bzrlib.errors import (
246
242
self._ensure_real()
247
243
self._real_bzrdir.destroy_repository()
249
def create_branch(self, name=None):
245
def create_branch(self):
250
246
# as per meta1 formats - just delegate to the format object which may
251
247
# be parameterised.
252
real_branch = self._format.get_branch_format().initialize(self,
248
real_branch = self._format.get_branch_format().initialize(self)
254
249
if not isinstance(real_branch, RemoteBranch):
255
result = RemoteBranch(self, self.find_repository(), real_branch,
250
result = RemoteBranch(self, self.find_repository(), real_branch)
258
252
result = real_branch
259
253
# BzrDir.clone_on_transport() uses the result of create_branch but does
265
259
self._next_open_branch_result = result
268
def destroy_branch(self, name=None):
262
def destroy_branch(self):
269
263
"""See BzrDir.destroy_branch"""
270
264
self._ensure_real()
271
self._real_bzrdir.destroy_branch(name=name)
265
self._real_bzrdir.destroy_branch()
272
266
self._next_open_branch_result = None
274
268
def create_workingtree(self, revision_id=None, from_branch=None):
275
269
raise errors.NotLocalUrl(self.transport.base)
277
def find_branch_format(self, name=None):
271
def find_branch_format(self):
278
272
"""Find the branch 'format' for this bzrdir.
280
274
This might be a synthetic object for e.g. RemoteBranch and SVN.
282
b = self.open_branch(name=name)
276
b = self.open_branch()
285
def get_branch_reference(self, name=None):
279
def get_branch_reference(self):
286
280
"""See BzrDir.get_branch_reference()."""
288
# XXX JRV20100304: Support opening colocated branches
289
raise errors.NoColocatedBranchSupport(self)
290
281
response = self._get_branch_reference()
291
282
if response[0] == 'ref':
292
283
return response[1]
323
314
raise errors.UnexpectedSmartServerResponse(response)
326
def _get_tree_branch(self, name=None):
317
def _get_tree_branch(self):
327
318
"""See BzrDir._get_tree_branch()."""
328
return None, self.open_branch(name=name)
319
return None, self.open_branch()
330
def open_branch(self, name=None, unsupported=False,
331
ignore_fallbacks=False):
321
def open_branch(self, _unsupported=False, ignore_fallbacks=False):
333
323
raise NotImplementedError('unsupported flag support not implemented yet.')
334
324
if self._next_open_branch_result is not None:
335
325
# See create_branch for details.
340
330
if response[0] == 'ref':
341
331
# a branch reference, use the existing BranchReference logic.
342
332
format = BranchReferenceFormat()
343
return format.open(self, name=name, _found=True,
344
location=response[1], ignore_fallbacks=ignore_fallbacks)
333
return format.open(self, _found=True, location=response[1],
334
ignore_fallbacks=ignore_fallbacks)
345
335
branch_format_name = response[1]
346
336
if not branch_format_name:
347
337
branch_format_name = None
348
338
format = RemoteBranchFormat(network_name=branch_format_name)
349
339
return RemoteBranch(self, self.find_repository(), format=format,
350
setup_stacking=not ignore_fallbacks, name=name)
340
setup_stacking=not ignore_fallbacks)
352
342
def _open_repo_v1(self, path):
353
343
verb = 'BzrDir.find_repository'
430
420
"""Return the path to be used for this bzrdir in a remote call."""
431
421
return client.remote_path_from_transport(self.root_transport)
433
def get_branch_transport(self, branch_format, name=None):
423
def get_branch_transport(self, branch_format):
434
424
self._ensure_real()
435
return self._real_bzrdir.get_branch_transport(branch_format, name=name)
425
return self._real_bzrdir.get_branch_transport(branch_format)
437
427
def get_repository_transport(self, repository_format):
438
428
self._ensure_real()
698
687
# Additional places to query for data.
699
688
self._fallback_repositories = []
702
def user_transport(self):
703
return self.bzrdir.user_transport
706
def control_transport(self):
707
# XXX: Normally you shouldn't directly get at the remote repository
708
# transport, but I'm not sure it's worth making this method
709
# optional -- mbp 2010-04-21
710
return self.bzrdir.get_repository_transport(None)
712
690
def __str__(self):
713
691
return "%s(%s)" % (self.__class__.__name__, self.base)
900
878
def _has_same_fallbacks(self, other_repo):
901
879
"""Returns true if the repositories have the same fallbacks."""
902
880
# XXX: copied from Repository; it should be unified into a base class
903
# <https://bugs.launchpad.net/bzr/+bug/401622>
881
# <https://bugs.edge.launchpad.net/bzr/+bug/401622>
904
882
my_fb = self._fallback_repositories
905
883
other_fb = other_repo._fallback_repositories
906
884
if len(my_fb) != len(other_fb):
922
900
parents_provider = self._make_parents_provider(other_repository)
923
901
return graph.Graph(parents_provider)
926
def get_known_graph_ancestry(self, revision_ids):
927
"""Return the known graph for a set of revision ids and their ancestors.
929
st = static_tuple.StaticTuple
930
revision_keys = [st(r_id).intern() for r_id in revision_ids]
931
known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
932
return graph.GraphThunkIdsToKeys(known_graph)
934
903
def gather_stats(self, revid=None, committers=None):
935
904
"""See Repository.gather_stats()."""
936
905
path = self.bzrdir._path_for_remote_call(self._client)
1250
1214
# state, so always add a lock here. If a caller passes us a locked
1251
1215
# repository, they are responsible for unlocking it later.
1252
1216
repository.lock_read()
1253
self._check_fallback_repository(repository)
1254
1217
self._fallback_repositories.append(repository)
1255
1218
# If self._real_repository was parameterised already (e.g. because a
1256
1219
# _real_branch had its get_stacked_on_url method called), then the
1257
1220
# repository to be added may already be in the _real_repositories list.
1258
1221
if self._real_repository is not None:
1259
fallback_locations = [repo.user_url for repo in
1222
fallback_locations = [repo.bzrdir.root_transport.base for repo in
1260
1223
self._real_repository._fallback_repositories]
1261
if repository.user_url not in fallback_locations:
1224
if repository.bzrdir.root_transport.base not in fallback_locations:
1262
1225
self._real_repository.add_fallback_repository(repository)
1264
def _check_fallback_repository(self, repository):
1265
"""Check that this repository can fallback to repository safely.
1267
Raise an error if not.
1269
:param repository: A repository to fallback to.
1271
return _mod_repository.InterRepository._assert_same_model(
1274
1227
def add_inventory(self, revid, inv, parents):
1275
1228
self._ensure_real()
1276
1229
return self._real_repository.add_inventory(revid, inv, parents)
1278
1231
def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1279
parents, basis_inv=None, propagate_caches=False):
1280
1233
self._ensure_real()
1281
1234
return self._real_repository.add_inventory_by_delta(basis_revision_id,
1282
delta, new_revision_id, parents, basis_inv=basis_inv,
1283
propagate_caches=propagate_caches)
1235
delta, new_revision_id, parents)
1285
1237
def add_revision(self, rev_id, rev, inv=None, config=None):
1286
1238
self._ensure_real()
1316
1268
return self._real_repository.make_working_trees()
1318
1270
def refresh_data(self):
1319
"""Re-read any data needed to synchronise with disk.
1271
"""Re-read any data needed to to synchronise with disk.
1321
1273
This method is intended to be called after another repository instance
1322
1274
(such as one used by a smart server) has inserted data into the
1323
repository. On all repositories this will work outside of write groups.
1324
Some repository formats (pack and newer for bzrlib native formats)
1325
support refresh_data inside write groups. If called inside a write
1326
group on a repository that does not support refreshing in a write group
1327
IsInWriteGroupError will be raised.
1275
repository. It may not be called during a write group, but may be
1276
called at any other time.
1278
if self.is_in_write_group():
1279
raise errors.InternalBzrError(
1280
"May not refresh_data while in a write group.")
1329
1281
if self._real_repository is not None:
1330
1282
self._real_repository.refresh_data()
1549
1501
self._ensure_real()
1550
1502
return self._real_repository._get_inventory_xml(revision_id)
1504
def _deserialise_inventory(self, revision_id, xml):
1506
return self._real_repository._deserialise_inventory(revision_id, xml)
1552
1508
def reconcile(self, other=None, thorough=False):
1553
1509
self._ensure_real()
1554
1510
return self._real_repository.reconcile(other=other, thorough=thorough)
1629
1585
return self._real_repository.inventories
1631
1587
@needs_write_lock
1632
def pack(self, hint=None, clean_obsolete_packs=False):
1588
def pack(self, hint=None):
1633
1589
"""Compress the data within the repository.
1635
1591
This is not currently implemented within the smart server.
1637
1593
self._ensure_real()
1638
return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
1594
return self._real_repository.pack(hint=hint)
1641
1597
def revisions(self):
1981
1937
if response_tuple[0] != 'ok':
1982
1938
raise errors.UnexpectedSmartServerResponse(response_tuple)
1983
1939
byte_stream = response_handler.read_streamed_body()
1984
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1985
self._record_counter)
1940
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1986
1941
if src_format.network_name() != repo._format.network_name():
1987
1942
raise AssertionError(
1988
1943
"Mismatched RemoteRepository and stream src %r, %r" % (
2070
2025
def network_name(self):
2071
2026
return self._network_name
2073
def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2074
return a_bzrdir.open_branch(name=name,
2075
ignore_fallbacks=ignore_fallbacks)
2028
def open(self, a_bzrdir, ignore_fallbacks=False):
2029
return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2077
def _vfs_initialize(self, a_bzrdir, name):
2031
def _vfs_initialize(self, a_bzrdir):
2078
2032
# Initialisation when using a local bzrdir object, or a non-vfs init
2079
2033
# method is not available on the server.
2080
2034
# self._custom_format is always set - the start of initialize ensures
2082
2036
if isinstance(a_bzrdir, RemoteBzrDir):
2083
2037
a_bzrdir._ensure_real()
2084
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2038
result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2087
2040
# We assume the bzrdir is parameterised; it may not be.
2088
result = self._custom_format.initialize(a_bzrdir, name)
2041
result = self._custom_format.initialize(a_bzrdir)
2089
2042
if (isinstance(a_bzrdir, RemoteBzrDir) and
2090
2043
not isinstance(result, RemoteBranch)):
2091
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2044
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2095
def initialize(self, a_bzrdir, name=None):
2047
def initialize(self, a_bzrdir):
2096
2048
# 1) get the network name to use.
2097
2049
if self._custom_format:
2098
2050
network_name = self._custom_format.network_name()
2104
2056
network_name = reference_format.network_name()
2105
2057
# Being asked to create on a non RemoteBzrDir:
2106
2058
if not isinstance(a_bzrdir, RemoteBzrDir):
2107
return self._vfs_initialize(a_bzrdir, name=name)
2059
return self._vfs_initialize(a_bzrdir)
2108
2060
medium = a_bzrdir._client._medium
2109
2061
if medium._is_remote_before((1, 13)):
2110
return self._vfs_initialize(a_bzrdir, name=name)
2062
return self._vfs_initialize(a_bzrdir)
2111
2063
# Creating on a remote bzr dir.
2112
2064
# 2) try direct creation via RPC
2113
2065
path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2114
if name is not None:
2115
# XXX JRV20100304: Support creating colocated branches
2116
raise errors.NoColocatedBranchSupport(self)
2117
2066
verb = 'BzrDir.create_branch'
2119
2068
response = a_bzrdir._call(verb, path, network_name)
2120
2069
except errors.UnknownSmartMethod:
2121
2070
# Fallback - use vfs methods
2122
2071
medium._remember_remote_is_before((1, 13))
2123
return self._vfs_initialize(a_bzrdir, name=name)
2072
return self._vfs_initialize(a_bzrdir)
2124
2073
if response[0] != 'ok':
2125
2074
raise errors.UnexpectedSmartServerResponse(response)
2126
2075
# Turn the response into a RemoteRepository object.
2134
2083
a_bzrdir._client)
2135
2084
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2136
2085
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2137
format=format, setup_stacking=False, name=name)
2086
format=format, setup_stacking=False)
2138
2087
# XXX: We know this is a new branch, so it must have revno 0, revid
2139
2088
# NULL_REVISION. Creating the branch locked would make this be unable
2140
2089
# to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2169
2118
def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2170
_client=None, format=None, setup_stacking=True, name=None):
2119
_client=None, format=None, setup_stacking=True):
2171
2120
"""Create a RemoteBranch instance.
2173
2122
:param real_branch: An optional local implementation of the branch
2277
2223
'to use vfs implementation')
2278
2224
self.bzrdir._ensure_real()
2279
2225
self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2280
ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
2226
ignore_fallbacks=self._real_ignore_fallbacks)
2281
2227
if self.repository._real_repository is None:
2282
2228
# Give the remote repository the matching real repo.
2283
2229
real_repo = self._real_branch.repository
2411
2353
self._real_branch.lock_read()
2413
2355
self._lock_count += 1
2414
return lock.LogicalLockResult(self.unlock)
2416
2357
def _remote_lock_write(self, token):
2417
2358
if token is None:
2418
2359
branch_token = repo_token = ''
2420
2361
branch_token = token
2421
repo_token = self.repository.lock_write().repository_token
2362
repo_token = self.repository.lock_write()
2422
2363
self.repository.unlock()
2423
2364
err_context = {'token': token}
2425
response = self._call(
2426
'Branch.lock_write', self._remote_path(), branch_token,
2427
repo_token or '', **err_context)
2428
except errors.LockContention, e:
2429
# The LockContention from the server doesn't have any
2430
# information about the lock_url. We re-raise LockContention
2431
# with valid lock_url.
2432
raise errors.LockContention('(remote lock)',
2433
self.repository.base.split('.bzr/')[0])
2365
response = self._call(
2366
'Branch.lock_write', self._remote_path(), branch_token,
2367
repo_token or '', **err_context)
2434
2368
if response[0] != 'ok':
2435
2369
raise errors.UnexpectedSmartServerResponse(response)
2436
2370
ok, branch_token, repo_token = response
2468
2402
self._lock_count += 1
2469
2403
# Re-lock the repository too.
2470
2404
self.repository.lock_write(self._repo_lock_token)
2471
return BranchWriteLockResult(self.unlock, self._lock_token or None)
2405
return self._lock_token or None
2473
2407
def _unlock(self, branch_token, repo_token):
2474
2408
err_context = {'token': str((branch_token, repo_token))}
2797
2731
medium = self._branch._client._medium
2798
2732
if medium._is_remote_before((1, 14)):
2799
2733
return self._vfs_set_option(value, name, section)
2800
if isinstance(value, dict):
2801
if medium._is_remote_before((2, 2)):
2802
return self._vfs_set_option(value, name, section)
2803
return self._set_config_option_dict(value, name, section)
2805
return self._set_config_option(value, name, section)
2807
def _set_config_option(self, value, name, section):
2809
2735
path = self._branch._remote_path()
2810
2736
response = self._branch._client.call('Branch.set_config_option',
2811
2737
path, self._branch._lock_token, self._branch._repo_lock_token,
2812
2738
value.encode('utf8'), name, section or '')
2813
2739
except errors.UnknownSmartMethod:
2814
medium = self._branch._client._medium
2815
2740
medium._remember_remote_is_before((1, 14))
2816
2741
return self._vfs_set_option(value, name, section)
2817
2742
if response != ():
2818
2743
raise errors.UnexpectedSmartServerResponse(response)
2820
def _serialize_option_dict(self, option_dict):
2822
for key, value in option_dict.items():
2823
if isinstance(key, unicode):
2824
key = key.encode('utf8')
2825
if isinstance(value, unicode):
2826
value = value.encode('utf8')
2827
utf8_dict[key] = value
2828
return bencode.bencode(utf8_dict)
2830
def _set_config_option_dict(self, value, name, section):
2832
path = self._branch._remote_path()
2833
serialised_dict = self._serialize_option_dict(value)
2834
response = self._branch._client.call(
2835
'Branch.set_config_option_dict',
2836
path, self._branch._lock_token, self._branch._repo_lock_token,
2837
serialised_dict, name, section or '')
2838
except errors.UnknownSmartMethod:
2839
medium = self._branch._client._medium
2840
medium._remember_remote_is_before((2, 2))
2841
return self._vfs_set_option(value, name, section)
2843
raise errors.UnexpectedSmartServerResponse(response)
2845
2745
def _real_object(self):
2846
2746
self._branch._ensure_real()
2847
2747
return self._branch._real_branch