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