32
33
revision as _mod_revision,
36
from bzrlib.branch import BranchReferenceFormat
38
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
37
39
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
40
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
39
41
from bzrlib.errors import (
244
247
self._ensure_real()
245
248
self._real_bzrdir.destroy_repository()
247
def create_branch(self, name=None):
250
def create_branch(self, name=None, repository=None):
248
251
# as per meta1 formats - just delegate to the format object which may
249
252
# be parameterised.
250
253
real_branch = self._format.get_branch_format().initialize(self,
254
name=name, repository=repository)
252
255
if not isinstance(real_branch, RemoteBranch):
253
result = RemoteBranch(self, self.find_repository(), real_branch,
256
if not isinstance(repository, RemoteRepository):
257
raise AssertionError(
258
'need a RemoteRepository to use with RemoteBranch, got %r'
260
result = RemoteBranch(self, repository, real_branch, name=name)
256
262
result = real_branch
257
263
# BzrDir.clone_on_transport() uses the result of create_branch but does
269
275
self._real_bzrdir.destroy_branch(name=name)
270
276
self._next_open_branch_result = None
272
def create_workingtree(self, revision_id=None, from_branch=None):
278
def create_workingtree(self, revision_id=None, from_branch=None,
279
accelerator_tree=None, hardlink=False):
273
280
raise errors.NotLocalUrl(self.transport.base)
275
def find_branch_format(self):
282
def find_branch_format(self, name=None):
276
283
"""Find the branch 'format' for this bzrdir.
278
285
This might be a synthetic object for e.g. RemoteBranch and SVN.
280
b = self.open_branch()
287
b = self.open_branch(name=name)
283
def get_branch_reference(self):
290
def get_branch_reference(self, name=None):
284
291
"""See BzrDir.get_branch_reference()."""
293
# XXX JRV20100304: Support opening colocated branches
294
raise errors.NoColocatedBranchSupport(self)
285
295
response = self._get_branch_reference()
286
296
if response[0] == 'ref':
287
297
return response[1]
318
328
raise errors.UnexpectedSmartServerResponse(response)
321
def _get_tree_branch(self):
331
def _get_tree_branch(self, name=None):
322
332
"""See BzrDir._get_tree_branch()."""
323
return None, self.open_branch()
333
return None, self.open_branch(name=name)
325
335
def open_branch(self, name=None, unsupported=False,
326
336
ignore_fallbacks=False):
441
451
"""Upgrading of remote bzrdirs is not supported yet."""
444
def needs_format_conversion(self, format=None):
454
def needs_format_conversion(self, format):
445
455
"""Upgrading of remote bzrdirs is not supported yet."""
447
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
448
% 'needs_format_conversion(format=None)')
451
458
def clone(self, url, revision_id=None, force_new_repo=False,
529
537
self._custom_format.supports_tree_reference
530
538
return self._supports_tree_reference
540
def is_deprecated(self):
541
if self._is_deprecated is None:
543
self._is_deprecated = self._custom_format.is_deprecated()
544
return self._is_deprecated
532
546
def _vfs_initialize(self, a_bzrdir, shared):
533
547
"""Helper for common code in initialize."""
534
548
if self._custom_format:
895
909
def _has_same_fallbacks(self, other_repo):
896
910
"""Returns true if the repositories have the same fallbacks."""
897
911
# XXX: copied from Repository; it should be unified into a base class
898
# <https://bugs.edge.launchpad.net/bzr/+bug/401622>
912
# <https://bugs.launchpad.net/bzr/+bug/401622>
899
913
my_fb = self._fallback_repositories
900
914
other_fb = other_repo._fallback_repositories
901
915
if len(my_fb) != len(other_fb):
991
1005
def is_write_locked(self):
992
1006
return self._lock_mode == 'w'
994
def _warn_if_deprecated(self, branch=None):
995
# If we have a real repository, the check will be done there, if we
996
# don't the check will be done remotely.
999
1008
def lock_read(self):
1009
"""Lock the repository for read operations.
1011
:return: A bzrlib.lock.LogicalLockResult.
1000
1013
# wrong eventually - want a local lock cache context
1001
1014
if not self._lock_mode:
1002
1015
self._note_lock('r')
1306
1320
return self._real_repository.make_working_trees()
1308
1322
def refresh_data(self):
1309
"""Re-read any data needed to to synchronise with disk.
1323
"""Re-read any data needed to synchronise with disk.
1311
1325
This method is intended to be called after another repository instance
1312
1326
(such as one used by a smart server) has inserted data into the
1313
repository. It may not be called during a write group, but may be
1314
called at any other time.
1327
repository. On all repositories this will work outside of write groups.
1328
Some repository formats (pack and newer for bzrlib native formats)
1329
support refresh_data inside write groups. If called inside a write
1330
group on a repository that does not support refreshing in a write group
1331
IsInWriteGroupError will be raised.
1316
if self.is_in_write_group():
1317
raise errors.InternalBzrError(
1318
"May not refresh_data while in a write group.")
1319
1333
if self._real_repository is not None:
1320
1334
self._real_repository.refresh_data()
1335
1349
@needs_read_lock
1336
def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1350
def search_missing_revision_ids(self, other,
1351
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1352
find_ghosts=True, revision_ids=None, if_present_ids=None):
1337
1353
"""Return the revision ids that other has that this does not.
1339
1355
These are returned in topological order.
1341
1357
revision_id: only return revision ids included by revision_id.
1343
return repository.InterRepository.get(
1344
other, self).search_missing_revision_ids(revision_id, find_ghosts)
1359
if symbol_versioning.deprecated_passed(revision_id):
1360
symbol_versioning.warn(
1361
'search_missing_revision_ids(revision_id=...) was '
1362
'deprecated in 2.4. Use revision_ids=[...] instead.',
1363
DeprecationWarning, stacklevel=2)
1364
if revision_ids is not None:
1365
raise AssertionError(
1366
'revision_ids is mutually exclusive with revision_id')
1367
if revision_id is not None:
1368
revision_ids = [revision_id]
1369
inter_repo = repository.InterRepository.get(other, self)
1370
return inter_repo.search_missing_revision_ids(
1371
find_ghosts=find_ghosts, revision_ids=revision_ids,
1372
if_present_ids=if_present_ids)
1346
def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
1374
def fetch(self, source, revision_id=None, find_ghosts=False,
1347
1375
fetch_spec=None):
1348
1376
# No base implementation to use as RemoteRepository is not a subclass
1349
1377
# of Repository; so this is a copy of Repository.fetch().
1367
1395
# the InterRepository base class, which raises an
1368
1396
# IncompatibleRepositories when asked to fetch.
1369
1397
inter = repository.InterRepository.get(source, self)
1370
return inter.fetch(revision_id=revision_id, pb=pb,
1398
return inter.fetch(revision_id=revision_id,
1371
1399
find_ghosts=find_ghosts, fetch_spec=fetch_spec)
1373
1401
def create_bundle(self, target, base, fileobj, format=None):
1748
1776
return '\n'.join((start_keys, stop_keys, count))
1750
1778
def _serialise_search_result(self, search_result):
1751
if isinstance(search_result, graph.PendingAncestryResult):
1752
parts = ['ancestry-of']
1753
parts.extend(search_result.heads)
1755
recipe = search_result.get_recipe()
1756
parts = [recipe[0], self._serialise_search_recipe(recipe)]
1779
parts = search_result.get_network_struct()
1757
1780
return '\n'.join(parts)
1759
1782
def autopack(self):
1962
1986
verb, args, search_bytes)
1963
1987
except errors.UnknownSmartMethod:
1964
1988
medium._remember_remote_is_before(version)
1989
except errors.UnknownErrorFromSmartServer, e:
1990
if isinstance(search, graph.EverythingResult):
1991
error_verb = e.error_from_smart_server.error_verb
1992
if error_verb == 'BadSearch':
1993
# Pre-2.4 servers don't support this sort of search.
1994
# XXX: perhaps falling back to VFS on BadSearch is a
1995
# good idea in general? It might provide a little bit
1996
# of protection against client-side bugs.
1997
medium._remember_remote_is_before((2, 4))
1966
2001
response_tuple, response_handler = response
1967
2002
found_verb = True
1971
2006
if response_tuple[0] != 'ok':
1972
2007
raise errors.UnexpectedSmartServerResponse(response_tuple)
1973
2008
byte_stream = response_handler.read_streamed_body()
1974
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
2009
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
2010
self._record_counter)
1975
2011
if src_format.network_name() != repo._format.network_name():
1976
2012
raise AssertionError(
1977
2013
"Mismatched RemoteRepository and stream src %r, %r" % (
2115
2151
# Turn the response into a RemoteRepository object.
2116
2152
format = RemoteBranchFormat(network_name=response[1])
2117
2153
repo_format = response_tuple_to_repo_format(response[3:])
2118
if response[2] == '':
2119
repo_bzrdir = a_bzrdir
2154
repo_path = response[2]
2155
if repository is not None:
2156
remote_repo_url = urlutils.join(medium.base, repo_path)
2157
url_diff = urlutils.relative_url(repository.user_url,
2160
raise AssertionError(
2161
'repository.user_url %r does not match URL from server '
2162
'response (%r + %r)'
2163
% (repository.user_url, medium.base, repo_path))
2164
remote_repo = repository
2121
repo_bzrdir = RemoteBzrDir(
2122
a_bzrdir.root_transport.clone(response[2]), a_bzrdir._format,
2124
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2167
repo_bzrdir = a_bzrdir
2169
repo_bzrdir = RemoteBzrDir(
2170
a_bzrdir.root_transport.clone(repo_path), a_bzrdir._format,
2172
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2125
2173
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2126
2174
format=format, setup_stacking=False, name=name)
2127
2175
# XXX: We know this is a new branch, so it must have revno 0, revid
2357
2405
self._ensure_real()
2358
2406
return self._real_branch._get_tags_bytes()
2360
2409
def _get_tags_bytes(self):
2410
if self._tags_bytes is None:
2411
self._tags_bytes = self._get_tags_bytes_via_hpss()
2412
return self._tags_bytes
2414
def _get_tags_bytes_via_hpss(self):
2361
2415
medium = self._client._medium
2362
2416
if medium._is_remote_before((1, 13)):
2363
2417
return self._vfs_get_tags_bytes()
2396
2456
self._real_branch.lock_read()
2398
2458
self._lock_count += 1
2459
return lock.LogicalLockResult(self.unlock)
2400
2461
def _remote_lock_write(self, token):
2401
2462
if token is None:
2402
2463
branch_token = repo_token = ''
2404
2465
branch_token = token
2405
repo_token = self.repository.lock_write()
2466
repo_token = self.repository.lock_write().repository_token
2406
2467
self.repository.unlock()
2407
2468
err_context = {'token': token}
2408
response = self._call(
2409
'Branch.lock_write', self._remote_path(), branch_token,
2410
repo_token or '', **err_context)
2470
response = self._call(
2471
'Branch.lock_write', self._remote_path(), branch_token,
2472
repo_token or '', **err_context)
2473
except errors.LockContention, e:
2474
# The LockContention from the server doesn't have any
2475
# information about the lock_url. We re-raise LockContention
2476
# with valid lock_url.
2477
raise errors.LockContention('(remote lock)',
2478
self.repository.base.split('.bzr/')[0])
2411
2479
if response[0] != 'ok':
2412
2480
raise errors.UnexpectedSmartServerResponse(response)
2413
2481
ok, branch_token, repo_token = response
2445
2513
self._lock_count += 1
2446
2514
# Re-lock the repository too.
2447
2515
self.repository.lock_write(self._repo_lock_token)
2448
return self._lock_token or None
2516
return BranchWriteLockResult(self.unlock, self._lock_token or None)
2450
2518
def _unlock(self, branch_token, repo_token):
2451
2519
err_context = {'token': str((branch_token, repo_token))}
2774
2842
medium = self._branch._client._medium
2775
2843
if medium._is_remote_before((1, 14)):
2776
2844
return self._vfs_set_option(value, name, section)
2845
if isinstance(value, dict):
2846
if medium._is_remote_before((2, 2)):
2847
return self._vfs_set_option(value, name, section)
2848
return self._set_config_option_dict(value, name, section)
2850
return self._set_config_option(value, name, section)
2852
def _set_config_option(self, value, name, section):
2778
2854
path = self._branch._remote_path()
2779
2855
response = self._branch._client.call('Branch.set_config_option',
2780
2856
path, self._branch._lock_token, self._branch._repo_lock_token,
2781
2857
value.encode('utf8'), name, section or '')
2782
2858
except errors.UnknownSmartMethod:
2859
medium = self._branch._client._medium
2783
2860
medium._remember_remote_is_before((1, 14))
2784
2861
return self._vfs_set_option(value, name, section)
2785
2862
if response != ():
2786
2863
raise errors.UnexpectedSmartServerResponse(response)
2865
def _serialize_option_dict(self, option_dict):
2867
for key, value in option_dict.items():
2868
if isinstance(key, unicode):
2869
key = key.encode('utf8')
2870
if isinstance(value, unicode):
2871
value = value.encode('utf8')
2872
utf8_dict[key] = value
2873
return bencode.bencode(utf8_dict)
2875
def _set_config_option_dict(self, value, name, section):
2877
path = self._branch._remote_path()
2878
serialised_dict = self._serialize_option_dict(value)
2879
response = self._branch._client.call(
2880
'Branch.set_config_option_dict',
2881
path, self._branch._lock_token, self._branch._repo_lock_token,
2882
serialised_dict, name, section or '')
2883
except errors.UnknownSmartMethod:
2884
medium = self._branch._client._medium
2885
medium._remember_remote_is_before((2, 2))
2886
return self._vfs_set_option(value, name, section)
2888
raise errors.UnexpectedSmartServerResponse(response)
2788
2890
def _real_object(self):
2789
2891
self._branch._ensure_real()
2790
2892
return self._branch._real_branch