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 (
274
270
def create_workingtree(self, revision_id=None, from_branch=None):
275
271
raise errors.NotLocalUrl(self.transport.base)
277
def find_branch_format(self, name=None):
273
def find_branch_format(self):
278
274
"""Find the branch 'format' for this bzrdir.
280
276
This might be a synthetic object for e.g. RemoteBranch and SVN.
282
b = self.open_branch(name=name)
278
b = self.open_branch()
285
def get_branch_reference(self, name=None):
281
def get_branch_reference(self):
286
282
"""See BzrDir.get_branch_reference()."""
288
# XXX JRV20100304: Support opening colocated branches
289
raise errors.NoColocatedBranchSupport(self)
290
283
response = self._get_branch_reference()
291
284
if response[0] == 'ref':
292
285
return response[1]
323
316
raise errors.UnexpectedSmartServerResponse(response)
326
def _get_tree_branch(self, name=None):
319
def _get_tree_branch(self):
327
320
"""See BzrDir._get_tree_branch()."""
328
return None, self.open_branch(name=name)
321
return None, self.open_branch()
330
323
def open_branch(self, name=None, unsupported=False,
331
324
ignore_fallbacks=False):
698
690
# Additional places to query for data.
699
691
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
693
def __str__(self):
713
694
return "%s(%s)" % (self.__class__.__name__, self.base)
900
881
def _has_same_fallbacks(self, other_repo):
901
882
"""Returns true if the repositories have the same fallbacks."""
902
883
# XXX: copied from Repository; it should be unified into a base class
903
# <https://bugs.launchpad.net/bzr/+bug/401622>
884
# <https://bugs.edge.launchpad.net/bzr/+bug/401622>
904
885
my_fb = self._fallback_repositories
905
886
other_fb = other_repo._fallback_repositories
906
887
if len(my_fb) != len(other_fb):
922
903
parents_provider = self._make_parents_provider(other_repository)
923
904
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
906
def gather_stats(self, revid=None, committers=None):
935
907
"""See Repository.gather_stats()."""
936
908
path = self.bzrdir._path_for_remote_call(self._client)
1250
1217
# state, so always add a lock here. If a caller passes us a locked
1251
1218
# repository, they are responsible for unlocking it later.
1252
1219
repository.lock_read()
1253
self._check_fallback_repository(repository)
1254
1220
self._fallback_repositories.append(repository)
1255
1221
# If self._real_repository was parameterised already (e.g. because a
1256
1222
# _real_branch had its get_stacked_on_url method called), then the
1257
1223
# repository to be added may already be in the _real_repositories list.
1258
1224
if self._real_repository is not None:
1259
fallback_locations = [repo.user_url for repo in
1225
fallback_locations = [repo.bzrdir.root_transport.base for repo in
1260
1226
self._real_repository._fallback_repositories]
1261
if repository.user_url not in fallback_locations:
1227
if repository.bzrdir.root_transport.base not in fallback_locations:
1262
1228
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
1230
def add_inventory(self, revid, inv, parents):
1275
1231
self._ensure_real()
1276
1232
return self._real_repository.add_inventory(revid, inv, parents)
1316
1272
return self._real_repository.make_working_trees()
1318
1274
def refresh_data(self):
1319
"""Re-read any data needed to synchronise with disk.
1275
"""Re-read any data needed to to synchronise with disk.
1321
1277
This method is intended to be called after another repository instance
1322
1278
(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.
1279
repository. It may not be called during a write group, but may be
1280
called at any other time.
1282
if self.is_in_write_group():
1283
raise errors.InternalBzrError(
1284
"May not refresh_data while in a write group.")
1329
1285
if self._real_repository is not None:
1330
1286
self._real_repository.refresh_data()
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" % (
2411
2361
self._real_branch.lock_read()
2413
2363
self._lock_count += 1
2414
return lock.LogicalLockResult(self.unlock)
2416
2365
def _remote_lock_write(self, token):
2417
2366
if token is None:
2418
2367
branch_token = repo_token = ''
2420
2369
branch_token = token
2421
repo_token = self.repository.lock_write().repository_token
2370
repo_token = self.repository.lock_write()
2422
2371
self.repository.unlock()
2423
2372
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])
2373
response = self._call(
2374
'Branch.lock_write', self._remote_path(), branch_token,
2375
repo_token or '', **err_context)
2434
2376
if response[0] != 'ok':
2435
2377
raise errors.UnexpectedSmartServerResponse(response)
2436
2378
ok, branch_token, repo_token = response
2468
2410
self._lock_count += 1
2469
2411
# Re-lock the repository too.
2470
2412
self.repository.lock_write(self._repo_lock_token)
2471
return BranchWriteLockResult(self.unlock, self._lock_token or None)
2413
return self._lock_token or None
2473
2415
def _unlock(self, branch_token, repo_token):
2474
2416
err_context = {'token': str((branch_token, repo_token))}
2797
2739
medium = self._branch._client._medium
2798
2740
if medium._is_remote_before((1, 14)):
2799
2741
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
2743
path = self._branch._remote_path()
2810
2744
response = self._branch._client.call('Branch.set_config_option',
2811
2745
path, self._branch._lock_token, self._branch._repo_lock_token,
2812
2746
value.encode('utf8'), name, section or '')
2813
2747
except errors.UnknownSmartMethod:
2814
medium = self._branch._client._medium
2815
2748
medium._remember_remote_is_before((1, 14))
2816
2749
return self._vfs_set_option(value, name, section)
2817
2750
if response != ():
2818
2751
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
2753
def _real_object(self):
2846
2754
self._branch._ensure_real()
2847
2755
return self._branch._real_branch