30
repository as _mod_repository,
32
31
revision as _mod_revision,
36
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
34
from bzrlib.branch import BranchReferenceFormat
37
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
36
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
39
37
from bzrlib.errors import (
43
41
from bzrlib.lockable_files import LockableFiles
44
42
from bzrlib.smart import client, vfs, repository as smart_repo
45
43
from bzrlib.revision import ensure_null, NULL_REVISION
46
from bzrlib.repository import RepositoryWriteLockResult
47
44
from bzrlib.trace import mutter, note, warning
246
243
self._real_bzrdir.destroy_repository()
248
245
def create_branch(self, name=None):
247
raise errors.NoColocatedBranchSupport(self)
249
248
# as per meta1 formats - just delegate to the format object which may
250
249
# be parameterised.
251
real_branch = self._format.get_branch_format().initialize(self,
250
real_branch = self._format.get_branch_format().initialize(self)
253
251
if not isinstance(real_branch, RemoteBranch):
254
result = RemoteBranch(self, self.find_repository(), real_branch,
252
result = RemoteBranch(self, self.find_repository(), real_branch)
257
254
result = real_branch
258
255
# BzrDir.clone_on_transport() uses the result of create_branch but does
273
270
def create_workingtree(self, revision_id=None, from_branch=None):
274
271
raise errors.NotLocalUrl(self.transport.base)
276
def find_branch_format(self, name=None):
273
def find_branch_format(self):
277
274
"""Find the branch 'format' for this bzrdir.
279
276
This might be a synthetic object for e.g. RemoteBranch and SVN.
281
b = self.open_branch(name=name)
278
b = self.open_branch()
284
def get_branch_reference(self, name=None):
281
def get_branch_reference(self):
285
282
"""See BzrDir.get_branch_reference()."""
287
# XXX JRV20100304: Support opening colocated branches
288
raise errors.NoColocatedBranchSupport(self)
289
283
response = self._get_branch_reference()
290
284
if response[0] == 'ref':
291
285
return response[1]
322
316
raise errors.UnexpectedSmartServerResponse(response)
325
def _get_tree_branch(self, name=None):
319
def _get_tree_branch(self):
326
320
"""See BzrDir._get_tree_branch()."""
327
return None, self.open_branch(name=name)
321
return None, self.open_branch()
329
323
def open_branch(self, name=None, unsupported=False,
330
324
ignore_fallbacks=False):
332
326
raise NotImplementedError('unsupported flag support not implemented yet.')
328
raise errors.NoColocatedBranchSupport(self)
333
329
if self._next_open_branch_result is not None:
334
330
# See create_branch for details.
335
331
result = self._next_open_branch_result
339
335
if response[0] == 'ref':
340
336
# a branch reference, use the existing BranchReference logic.
341
337
format = BranchReferenceFormat()
342
return format.open(self, name=name, _found=True,
343
location=response[1], ignore_fallbacks=ignore_fallbacks)
338
return format.open(self, _found=True, location=response[1],
339
ignore_fallbacks=ignore_fallbacks)
344
340
branch_format_name = response[1]
345
341
if not branch_format_name:
346
342
branch_format_name = None
347
343
format = RemoteBranchFormat(network_name=branch_format_name)
348
344
return RemoteBranch(self, self.find_repository(), format=format,
349
setup_stacking=not ignore_fallbacks, name=name)
345
setup_stacking=not ignore_fallbacks)
351
347
def _open_repo_v1(self, path):
352
348
verb = 'BzrDir.find_repository'
429
425
"""Return the path to be used for this bzrdir in a remote call."""
430
426
return client.remote_path_from_transport(self.root_transport)
432
def get_branch_transport(self, branch_format, name=None):
428
def get_branch_transport(self, branch_format):
433
429
self._ensure_real()
434
return self._real_bzrdir.get_branch_transport(branch_format, name=name)
430
return self._real_bzrdir.get_branch_transport(branch_format)
436
432
def get_repository_transport(self, repository_format):
437
433
self._ensure_real()
647
643
return self._custom_format._serializer
650
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
651
bzrdir.ControlComponent):
646
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):
652
647
"""Repository accessed over rpc.
654
649
For the moment most operations are performed using local transport-backed
697
692
# Additional places to query for data.
698
693
self._fallback_repositories = []
701
def user_transport(self):
702
return self.bzrdir.user_transport
705
def control_transport(self):
706
# XXX: Normally you shouldn't directly get at the remote repository
707
# transport, but I'm not sure it's worth making this method
708
# optional -- mbp 2010-04-21
709
return self.bzrdir.get_repository_transport(None)
711
695
def __str__(self):
712
696
return "%s(%s)" % (self.__class__.__name__, self.base)
921
905
parents_provider = self._make_parents_provider(other_repository)
922
906
return graph.Graph(parents_provider)
925
def get_known_graph_ancestry(self, revision_ids):
926
"""Return the known graph for a set of revision ids and their ancestors.
928
st = static_tuple.StaticTuple
929
revision_keys = [st(r_id).intern() for r_id in revision_ids]
930
known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
931
return graph.GraphThunkIdsToKeys(known_graph)
933
908
def gather_stats(self, revid=None, committers=None):
934
909
"""See Repository.gather_stats()."""
935
910
path = self.bzrdir._path_for_remote_call(self._client)
1063
1033
raise errors.ReadOnlyError(self)
1065
1035
self._lock_count += 1
1066
return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
1036
return self._lock_token or None
1068
1038
def leave_lock_in_place(self):
1069
1039
if not self._lock_token:
1249
1219
# state, so always add a lock here. If a caller passes us a locked
1250
1220
# repository, they are responsible for unlocking it later.
1251
1221
repository.lock_read()
1252
self._check_fallback_repository(repository)
1253
1222
self._fallback_repositories.append(repository)
1254
1223
# If self._real_repository was parameterised already (e.g. because a
1255
1224
# _real_branch had its get_stacked_on_url method called), then the
1256
1225
# repository to be added may already be in the _real_repositories list.
1257
1226
if self._real_repository is not None:
1258
fallback_locations = [repo.user_url for repo in
1227
fallback_locations = [repo.bzrdir.root_transport.base for repo in
1259
1228
self._real_repository._fallback_repositories]
1260
if repository.user_url not in fallback_locations:
1229
if repository.bzrdir.root_transport.base not in fallback_locations:
1261
1230
self._real_repository.add_fallback_repository(repository)
1263
def _check_fallback_repository(self, repository):
1264
"""Check that this repository can fallback to repository safely.
1266
Raise an error if not.
1268
:param repository: A repository to fallback to.
1270
return _mod_repository.InterRepository._assert_same_model(
1273
1232
def add_inventory(self, revid, inv, parents):
1274
1233
self._ensure_real()
1275
1234
return self._real_repository.add_inventory(revid, inv, parents)
1315
1274
return self._real_repository.make_working_trees()
1317
1276
def refresh_data(self):
1318
"""Re-read any data needed to synchronise with disk.
1277
"""Re-read any data needed to to synchronise with disk.
1320
1279
This method is intended to be called after another repository instance
1321
1280
(such as one used by a smart server) has inserted data into the
1322
repository. On all repositories this will work outside of write groups.
1323
Some repository formats (pack and newer for bzrlib native formats)
1324
support refresh_data inside write groups. If called inside a write
1325
group on a repository that does not support refreshing in a write group
1326
IsInWriteGroupError will be raised.
1281
repository. It may not be called during a write group, but may be
1282
called at any other time.
1284
if self.is_in_write_group():
1285
raise errors.InternalBzrError(
1286
"May not refresh_data while in a write group.")
1328
1287
if self._real_repository is not None:
1329
1288
self._real_repository.refresh_data()
1628
1587
return self._real_repository.inventories
1630
1589
@needs_write_lock
1631
def pack(self, hint=None, clean_obsolete_packs=False):
1590
def pack(self, hint=None):
1632
1591
"""Compress the data within the repository.
1634
1593
This is not currently implemented within the smart server.
1636
1595
self._ensure_real()
1637
return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
1596
return self._real_repository.pack(hint=hint)
1640
1599
def revisions(self):
2068
2027
def network_name(self):
2069
2028
return self._network_name
2071
def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2072
return a_bzrdir.open_branch(name=name,
2073
ignore_fallbacks=ignore_fallbacks)
2030
def open(self, a_bzrdir, ignore_fallbacks=False):
2031
return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2075
def _vfs_initialize(self, a_bzrdir, name):
2033
def _vfs_initialize(self, a_bzrdir):
2076
2034
# Initialisation when using a local bzrdir object, or a non-vfs init
2077
2035
# method is not available on the server.
2078
2036
# self._custom_format is always set - the start of initialize ensures
2080
2038
if isinstance(a_bzrdir, RemoteBzrDir):
2081
2039
a_bzrdir._ensure_real()
2082
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2040
result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2085
2042
# We assume the bzrdir is parameterised; it may not be.
2086
result = self._custom_format.initialize(a_bzrdir, name)
2043
result = self._custom_format.initialize(a_bzrdir)
2087
2044
if (isinstance(a_bzrdir, RemoteBzrDir) and
2088
2045
not isinstance(result, RemoteBranch)):
2089
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2046
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2093
def initialize(self, a_bzrdir, name=None):
2049
def initialize(self, a_bzrdir):
2094
2050
# 1) get the network name to use.
2095
2051
if self._custom_format:
2096
2052
network_name = self._custom_format.network_name()
2102
2058
network_name = reference_format.network_name()
2103
2059
# Being asked to create on a non RemoteBzrDir:
2104
2060
if not isinstance(a_bzrdir, RemoteBzrDir):
2105
return self._vfs_initialize(a_bzrdir, name=name)
2061
return self._vfs_initialize(a_bzrdir)
2106
2062
medium = a_bzrdir._client._medium
2107
2063
if medium._is_remote_before((1, 13)):
2108
return self._vfs_initialize(a_bzrdir, name=name)
2064
return self._vfs_initialize(a_bzrdir)
2109
2065
# Creating on a remote bzr dir.
2110
2066
# 2) try direct creation via RPC
2111
2067
path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2112
if name is not None:
2113
# XXX JRV20100304: Support creating colocated branches
2114
raise errors.NoColocatedBranchSupport(self)
2115
2068
verb = 'BzrDir.create_branch'
2117
2070
response = a_bzrdir._call(verb, path, network_name)
2118
2071
except errors.UnknownSmartMethod:
2119
2072
# Fallback - use vfs methods
2120
2073
medium._remember_remote_is_before((1, 13))
2121
return self._vfs_initialize(a_bzrdir, name=name)
2074
return self._vfs_initialize(a_bzrdir)
2122
2075
if response[0] != 'ok':
2123
2076
raise errors.UnexpectedSmartServerResponse(response)
2124
2077
# Turn the response into a RemoteRepository object.
2132
2085
a_bzrdir._client)
2133
2086
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2134
2087
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2135
format=format, setup_stacking=False, name=name)
2088
format=format, setup_stacking=False)
2136
2089
# XXX: We know this is a new branch, so it must have revno 0, revid
2137
2090
# NULL_REVISION. Creating the branch locked would make this be unable
2138
2091
# to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2167
2120
def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2168
_client=None, format=None, setup_stacking=True, name=None):
2121
_client=None, format=None, setup_stacking=True):
2169
2122
"""Create a RemoteBranch instance.
2171
2124
:param real_branch: An optional local implementation of the branch
2177
2130
:param setup_stacking: If True make an RPC call to determine the
2178
2131
stacked (or not) status of the branch. If False assume the branch
2179
2132
is not stacked.
2180
:param name: Colocated branch name
2182
2134
# We intentionally don't call the parent class's __init__, because it
2183
2135
# will try to assign to self.tags, which is a property in this subclass.
2202
2154
self._real_branch = None
2203
2155
# Fill out expected attributes of branch for bzrlib API users.
2204
2156
self._clear_cached_state()
2205
# TODO: deprecate self.base in favor of user_url
2206
self.base = self.bzrdir.user_url
2157
self.base = self.bzrdir.root_transport.base
2208
2158
self._control_files = None
2209
2159
self._lock_mode = None
2210
2160
self._lock_token = None
2275
2225
'to use vfs implementation')
2276
2226
self.bzrdir._ensure_real()
2277
2227
self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2278
ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
2228
ignore_fallbacks=self._real_ignore_fallbacks)
2279
2229
if self.repository._real_repository is None:
2280
2230
# Give the remote repository the matching real repo.
2281
2231
real_repo = self._real_branch.repository
2409
2355
self._real_branch.lock_read()
2411
2357
self._lock_count += 1
2412
return lock.LogicalLockResult(self.unlock)
2414
2359
def _remote_lock_write(self, token):
2415
2360
if token is None:
2416
2361
branch_token = repo_token = ''
2418
2363
branch_token = token
2419
repo_token = self.repository.lock_write().repository_token
2364
repo_token = self.repository.lock_write()
2420
2365
self.repository.unlock()
2421
2366
err_context = {'token': token}
2422
2367
response = self._call(
2459
2404
self._lock_count += 1
2460
2405
# Re-lock the repository too.
2461
2406
self.repository.lock_write(self._repo_lock_token)
2462
return BranchWriteLockResult(self.unlock, self._lock_token or None)
2407
return self._lock_token or None
2464
2409
def _unlock(self, branch_token, repo_token):
2465
2410
err_context = {'token': str((branch_token, repo_token))}