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):
895
905
def _has_same_fallbacks(self, other_repo):
896
906
"""Returns true if the repositories have the same fallbacks."""
897
907
# XXX: copied from Repository; it should be unified into a base class
898
# <https://bugs.edge.launchpad.net/bzr/+bug/401622>
908
# <https://bugs.launchpad.net/bzr/+bug/401622>
899
909
my_fb = self._fallback_repositories
900
910
other_fb = other_repo._fallback_repositories
901
911
if len(my_fb) != len(other_fb):
1306
1321
return self._real_repository.make_working_trees()
1308
1323
def refresh_data(self):
1309
"""Re-read any data needed to to synchronise with disk.
1324
"""Re-read any data needed to synchronise with disk.
1311
1326
This method is intended to be called after another repository instance
1312
1327
(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.
1328
repository. On all repositories this will work outside of write groups.
1329
Some repository formats (pack and newer for bzrlib native formats)
1330
support refresh_data inside write groups. If called inside a write
1331
group on a repository that does not support refreshing in a write group
1332
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
1334
if self._real_repository is not None:
1320
1335
self._real_repository.refresh_data()
1335
1350
@needs_read_lock
1336
def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1351
def search_missing_revision_ids(self, other,
1352
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1353
find_ghosts=True, revision_ids=None, if_present_ids=None):
1337
1354
"""Return the revision ids that other has that this does not.
1339
1356
These are returned in topological order.
1341
1358
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)
1360
if symbol_versioning.deprecated_passed(revision_id):
1361
symbol_versioning.warn(
1362
'search_missing_revision_ids(revision_id=...) was '
1363
'deprecated in 2.4. Use revision_ids=[...] instead.',
1364
DeprecationWarning, stacklevel=2)
1365
if revision_ids is not None:
1366
raise AssertionError(
1367
'revision_ids is mutually exclusive with revision_id')
1368
if revision_id is not None:
1369
revision_ids = [revision_id]
1370
inter_repo = repository.InterRepository.get(other, self)
1371
return inter_repo.search_missing_revision_ids(
1372
find_ghosts=find_ghosts, revision_ids=revision_ids,
1373
if_present_ids=if_present_ids)
1346
1375
def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
1347
1376
fetch_spec=None):
1748
1777
return '\n'.join((start_keys, stop_keys, count))
1750
1779
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)]
1780
parts = search_result.get_network_struct()
1757
1781
return '\n'.join(parts)
1759
1783
def autopack(self):
1962
1987
verb, args, search_bytes)
1963
1988
except errors.UnknownSmartMethod:
1964
1989
medium._remember_remote_is_before(version)
1990
except errors.UnknownErrorFromSmartServer, e:
1991
if isinstance(search, graph.EverythingResult):
1992
error_verb = e.error_from_smart_server.error_verb
1993
if error_verb == 'BadSearch':
1994
# Pre-2.4 servers don't support this sort of search.
1995
# XXX: perhaps falling back to VFS on BadSearch is a
1996
# good idea in general? It might provide a little bit
1997
# of protection against client-side bugs.
1998
medium._remember_remote_is_before((2, 4))
1966
2002
response_tuple, response_handler = response
1967
2003
found_verb = True
1971
2007
if response_tuple[0] != 'ok':
1972
2008
raise errors.UnexpectedSmartServerResponse(response_tuple)
1973
2009
byte_stream = response_handler.read_streamed_body()
1974
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
2010
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
2011
self._record_counter)
1975
2012
if src_format.network_name() != repo._format.network_name():
1976
2013
raise AssertionError(
1977
2014
"Mismatched RemoteRepository and stream src %r, %r" % (
2115
2152
# Turn the response into a RemoteRepository object.
2116
2153
format = RemoteBranchFormat(network_name=response[1])
2117
2154
repo_format = response_tuple_to_repo_format(response[3:])
2118
if response[2] == '':
2119
repo_bzrdir = a_bzrdir
2155
repo_path = response[2]
2156
if repository is not None:
2157
remote_repo_url = urlutils.join(medium.base, repo_path)
2158
url_diff = urlutils.relative_url(repository.user_url,
2161
raise AssertionError(
2162
'repository.user_url %r does not match URL from server '
2163
'response (%r + %r)'
2164
% (repository.user_url, medium.base, repo_path))
2165
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)
2168
repo_bzrdir = a_bzrdir
2170
repo_bzrdir = RemoteBzrDir(
2171
a_bzrdir.root_transport.clone(repo_path), a_bzrdir._format,
2173
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2125
2174
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2126
2175
format=format, setup_stacking=False, name=name)
2127
2176
# XXX: We know this is a new branch, so it must have revno 0, revid
2357
2406
self._ensure_real()
2358
2407
return self._real_branch._get_tags_bytes()
2360
2410
def _get_tags_bytes(self):
2411
if self._tags_bytes is None:
2412
self._tags_bytes = self._get_tags_bytes_via_hpss()
2413
return self._tags_bytes
2415
def _get_tags_bytes_via_hpss(self):
2361
2416
medium = self._client._medium
2362
2417
if medium._is_remote_before((1, 13)):
2363
2418
return self._vfs_get_tags_bytes()
2396
2457
self._real_branch.lock_read()
2398
2459
self._lock_count += 1
2460
return lock.LogicalLockResult(self.unlock)
2400
2462
def _remote_lock_write(self, token):
2401
2463
if token is None:
2402
2464
branch_token = repo_token = ''
2404
2466
branch_token = token
2405
repo_token = self.repository.lock_write()
2467
repo_token = self.repository.lock_write().repository_token
2406
2468
self.repository.unlock()
2407
2469
err_context = {'token': token}
2408
response = self._call(
2409
'Branch.lock_write', self._remote_path(), branch_token,
2410
repo_token or '', **err_context)
2471
response = self._call(
2472
'Branch.lock_write', self._remote_path(), branch_token,
2473
repo_token or '', **err_context)
2474
except errors.LockContention, e:
2475
# The LockContention from the server doesn't have any
2476
# information about the lock_url. We re-raise LockContention
2477
# with valid lock_url.
2478
raise errors.LockContention('(remote lock)',
2479
self.repository.base.split('.bzr/')[0])
2411
2480
if response[0] != 'ok':
2412
2481
raise errors.UnexpectedSmartServerResponse(response)
2413
2482
ok, branch_token, repo_token = response
2445
2514
self._lock_count += 1
2446
2515
# Re-lock the repository too.
2447
2516
self.repository.lock_write(self._repo_lock_token)
2448
return self._lock_token or None
2517
return BranchWriteLockResult(self.unlock, self._lock_token or None)
2450
2519
def _unlock(self, branch_token, repo_token):
2451
2520
err_context = {'token': str((branch_token, repo_token))}
2774
2843
medium = self._branch._client._medium
2775
2844
if medium._is_remote_before((1, 14)):
2776
2845
return self._vfs_set_option(value, name, section)
2846
if isinstance(value, dict):
2847
if medium._is_remote_before((2, 2)):
2848
return self._vfs_set_option(value, name, section)
2849
return self._set_config_option_dict(value, name, section)
2851
return self._set_config_option(value, name, section)
2853
def _set_config_option(self, value, name, section):
2778
2855
path = self._branch._remote_path()
2779
2856
response = self._branch._client.call('Branch.set_config_option',
2780
2857
path, self._branch._lock_token, self._branch._repo_lock_token,
2781
2858
value.encode('utf8'), name, section or '')
2782
2859
except errors.UnknownSmartMethod:
2860
medium = self._branch._client._medium
2783
2861
medium._remember_remote_is_before((1, 14))
2784
2862
return self._vfs_set_option(value, name, section)
2785
2863
if response != ():
2786
2864
raise errors.UnexpectedSmartServerResponse(response)
2866
def _serialize_option_dict(self, option_dict):
2868
for key, value in option_dict.items():
2869
if isinstance(key, unicode):
2870
key = key.encode('utf8')
2871
if isinstance(value, unicode):
2872
value = value.encode('utf8')
2873
utf8_dict[key] = value
2874
return bencode.bencode(utf8_dict)
2876
def _set_config_option_dict(self, value, name, section):
2878
path = self._branch._remote_path()
2879
serialised_dict = self._serialize_option_dict(value)
2880
response = self._branch._client.call(
2881
'Branch.set_config_option_dict',
2882
path, self._branch._lock_token, self._branch._repo_lock_token,
2883
serialised_dict, name, section or '')
2884
except errors.UnknownSmartMethod:
2885
medium = self._branch._client._medium
2886
medium._remember_remote_is_before((2, 2))
2887
return self._vfs_set_option(value, name, section)
2889
raise errors.UnexpectedSmartServerResponse(response)
2788
2891
def _real_object(self):
2789
2892
self._branch._ensure_real()
2790
2893
return self._branch._real_branch