61
62
except errors.ErrorFromSmartServer, err:
62
63
self._translate_error(err, **err_context)
65
def _call_with_body_bytes(self, method, args, body_bytes, **err_context):
67
return self._client.call_with_body_bytes(method, args, body_bytes)
68
except errors.ErrorFromSmartServer, err:
69
self._translate_error(err, **err_context)
64
71
def _call_with_body_bytes_expecting_body(self, method, args, body_bytes,
104
112
self._client = client._SmartClient(medium)
106
114
self._client = _client
121
return '%s(%r)' % (self.__class__.__name__, self._client)
123
def _probe_bzrdir(self):
124
medium = self._client._medium
109
125
path = self._path_for_remote_call(self._client)
126
if medium._is_remote_before((2, 1)):
130
self._rpc_open_2_1(path)
132
except errors.UnknownSmartMethod:
133
medium._remember_remote_is_before((2, 1))
136
def _rpc_open_2_1(self, path):
137
response = self._call('BzrDir.open_2.1', path)
138
if response == ('no',):
139
raise errors.NotBranchError(path=self.root_transport.base)
140
elif response[0] == 'yes':
141
if response[1] == 'yes':
142
self._has_working_tree = True
143
elif response[1] == 'no':
144
self._has_working_tree = False
146
raise errors.UnexpectedSmartServerResponse(response)
148
raise errors.UnexpectedSmartServerResponse(response)
150
def _rpc_open(self, path):
110
151
response = self._call('BzrDir.open', path)
111
152
if response not in [('yes',), ('no',)]:
112
153
raise errors.UnexpectedSmartServerResponse(response)
113
154
if response == ('no',):
114
raise errors.NotBranchError(path=transport.base)
155
raise errors.NotBranchError(path=self.root_transport.base)
116
157
def _ensure_real(self):
117
158
"""Ensure that there is a _real_bzrdir set.
200
245
self._ensure_real()
201
246
self._real_bzrdir.destroy_repository()
203
def create_branch(self):
248
def create_branch(self, name=None):
204
249
# as per meta1 formats - just delegate to the format object which may
205
250
# be parameterised.
206
real_branch = self._format.get_branch_format().initialize(self)
251
real_branch = self._format.get_branch_format().initialize(self,
207
253
if not isinstance(real_branch, RemoteBranch):
208
result = RemoteBranch(self, self.find_repository(), real_branch)
254
result = RemoteBranch(self, self.find_repository(), real_branch,
210
257
result = real_branch
211
258
# BzrDir.clone_on_transport() uses the result of create_branch but does
217
264
self._next_open_branch_result = result
220
def destroy_branch(self):
267
def destroy_branch(self, name=None):
221
268
"""See BzrDir.destroy_branch"""
222
269
self._ensure_real()
223
self._real_bzrdir.destroy_branch()
270
self._real_bzrdir.destroy_branch(name=name)
224
271
self._next_open_branch_result = None
226
273
def create_workingtree(self, revision_id=None, from_branch=None):
227
274
raise errors.NotLocalUrl(self.transport.base)
229
def find_branch_format(self):
276
def find_branch_format(self, name=None):
230
277
"""Find the branch 'format' for this bzrdir.
232
279
This might be a synthetic object for e.g. RemoteBranch and SVN.
234
b = self.open_branch()
281
b = self.open_branch(name=name)
237
def get_branch_reference(self):
284
def get_branch_reference(self, name=None):
238
285
"""See BzrDir.get_branch_reference()."""
287
# XXX JRV20100304: Support opening colocated branches
288
raise errors.NoColocatedBranchSupport(self)
239
289
response = self._get_branch_reference()
240
290
if response[0] == 'ref':
241
291
return response[1]
245
295
def _get_branch_reference(self):
246
296
path = self._path_for_remote_call(self._client)
247
297
medium = self._client._medium
248
if not medium._is_remote_before((1, 13)):
299
('BzrDir.open_branchV3', (2, 1)),
300
('BzrDir.open_branchV2', (1, 13)),
301
('BzrDir.open_branch', None),
303
for verb, required_version in candidate_calls:
304
if required_version and medium._is_remote_before(required_version):
250
response = self._call('BzrDir.open_branchV2', path)
251
if response[0] not in ('ref', 'branch'):
252
raise errors.UnexpectedSmartServerResponse(response)
307
response = self._call(verb, path)
254
308
except errors.UnknownSmartMethod:
255
medium._remember_remote_is_before((1, 13))
256
response = self._call('BzrDir.open_branch', path)
257
if response[0] != 'ok':
309
if required_version is None:
311
medium._remember_remote_is_before(required_version)
314
if verb == 'BzrDir.open_branch':
315
if response[0] != 'ok':
316
raise errors.UnexpectedSmartServerResponse(response)
317
if response[1] != '':
318
return ('ref', response[1])
320
return ('branch', '')
321
if response[0] not in ('ref', 'branch'):
258
322
raise errors.UnexpectedSmartServerResponse(response)
259
if response[1] != '':
260
return ('ref', response[1])
262
return ('branch', '')
264
def _get_tree_branch(self):
325
def _get_tree_branch(self, name=None):
265
326
"""See BzrDir._get_tree_branch()."""
266
return None, self.open_branch()
327
return None, self.open_branch(name=name)
268
def open_branch(self, _unsupported=False, ignore_fallbacks=False):
329
def open_branch(self, name=None, unsupported=False,
330
ignore_fallbacks=False):
270
332
raise NotImplementedError('unsupported flag support not implemented yet.')
271
333
if self._next_open_branch_result is not None:
272
334
# See create_branch for details.
277
339
if response[0] == 'ref':
278
340
# a branch reference, use the existing BranchReference logic.
279
341
format = BranchReferenceFormat()
280
return format.open(self, _found=True, location=response[1],
281
ignore_fallbacks=ignore_fallbacks)
342
return format.open(self, name=name, _found=True,
343
location=response[1], ignore_fallbacks=ignore_fallbacks)
282
344
branch_format_name = response[1]
283
345
if not branch_format_name:
284
346
branch_format_name = None
285
347
format = RemoteBranchFormat(network_name=branch_format_name)
286
348
return RemoteBranch(self, self.find_repository(), format=format,
287
setup_stacking=not ignore_fallbacks)
349
setup_stacking=not ignore_fallbacks, name=name)
289
351
def _open_repo_v1(self, path):
290
352
verb = 'BzrDir.find_repository'
545
624
return self._custom_format._fetch_reconcile
547
626
def get_format_description(self):
548
return 'bzr remote repository'
628
return 'Remote: ' + self._custom_format.get_format_description()
550
630
def __eq__(self, other):
551
631
return self.__class__ is other.__class__
553
def check_conversion_target(self, target_format):
554
if self.rich_root_data and not target_format.rich_root_data:
555
raise errors.BadConversionTarget(
556
'Does not support rich root data.', target_format)
557
if (self.supports_tree_reference and
558
not getattr(target_format, 'supports_tree_reference', False)):
559
raise errors.BadConversionTarget(
560
'Does not support nested trees', target_format)
562
633
def network_name(self):
563
634
if self._network_name:
564
635
return self._network_name
808
896
result.add(_mod_revision.NULL_REVISION)
899
def _has_same_fallbacks(self, other_repo):
900
"""Returns true if the repositories have the same fallbacks."""
901
# XXX: copied from Repository; it should be unified into a base class
902
# <https://bugs.launchpad.net/bzr/+bug/401622>
903
my_fb = self._fallback_repositories
904
other_fb = other_repo._fallback_repositories
905
if len(my_fb) != len(other_fb):
907
for f, g in zip(my_fb, other_fb):
908
if not f.has_same_location(g):
811
912
def has_same_location(self, other):
913
# TODO: Move to RepositoryBase and unify with the regular Repository
914
# one; unfortunately the tests rely on slightly different behaviour at
915
# present -- mbp 20090710
812
916
return (self.__class__ is other.__class__ and
813
917
self.bzrdir.transport.base == other.bzrdir.transport.base)
817
921
parents_provider = self._make_parents_provider(other_repository)
818
922
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)
820
933
def gather_stats(self, revid=None, committers=None):
821
934
"""See Repository.gather_stats()."""
822
935
path = self.bzrdir._path_for_remote_call(self._client)
1123
1249
# state, so always add a lock here. If a caller passes us a locked
1124
1250
# repository, they are responsible for unlocking it later.
1125
1251
repository.lock_read()
1252
self._check_fallback_repository(repository)
1126
1253
self._fallback_repositories.append(repository)
1127
1254
# If self._real_repository was parameterised already (e.g. because a
1128
1255
# _real_branch had its get_stacked_on_url method called), then the
1129
1256
# repository to be added may already be in the _real_repositories list.
1130
1257
if self._real_repository is not None:
1131
fallback_locations = [repo.bzrdir.root_transport.base for repo in
1258
fallback_locations = [repo.user_url for repo in
1132
1259
self._real_repository._fallback_repositories]
1133
if repository.bzrdir.root_transport.base not in fallback_locations:
1260
if repository.user_url not in fallback_locations:
1134
1261
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(
1136
1273
def add_inventory(self, revid, inv, parents):
1137
1274
self._ensure_real()
1138
1275
return self._real_repository.add_inventory(revid, inv, parents)
1140
1277
def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1278
parents, basis_inv=None, propagate_caches=False):
1142
1279
self._ensure_real()
1143
1280
return self._real_repository.add_inventory_by_delta(basis_revision_id,
1144
delta, new_revision_id, parents)
1281
delta, new_revision_id, parents, basis_inv=basis_inv,
1282
propagate_caches=propagate_caches)
1146
1284
def add_revision(self, rev_id, rev, inv=None, config=None):
1147
1285
self._ensure_real()
1177
1315
return self._real_repository.make_working_trees()
1179
1317
def refresh_data(self):
1180
"""Re-read any data needed to to synchronise with disk.
1318
"""Re-read any data needed to synchronise with disk.
1182
1320
This method is intended to be called after another repository instance
1183
1321
(such as one used by a smart server) has inserted data into the
1184
repository. It may not be called during a write group, but may be
1185
called at any other time.
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.
1187
if self.is_in_write_group():
1188
raise errors.InternalBzrError(
1189
"May not refresh_data while in a write group.")
1190
1328
if self._real_repository is not None:
1191
1329
self._real_repository.refresh_data()
1653
1791
def insert_stream(self, stream, src_format, resume_tokens):
1654
1792
target = self.target_repo
1655
1793
target._unstacked_provider.missing_keys.clear()
1794
candidate_calls = [('Repository.insert_stream_1.19', (1, 19))]
1656
1795
if target._lock_token:
1657
verb = 'Repository.insert_stream_locked'
1658
extra_args = (target._lock_token or '',)
1659
required_version = (1, 14)
1796
candidate_calls.append(('Repository.insert_stream_locked', (1, 14)))
1797
lock_args = (target._lock_token or '',)
1661
verb = 'Repository.insert_stream'
1663
required_version = (1, 13)
1799
candidate_calls.append(('Repository.insert_stream', (1, 13)))
1664
1801
client = target._client
1665
1802
medium = client._medium
1666
if medium._is_remote_before(required_version):
1667
# No possible way this can work.
1668
return self._insert_real(stream, src_format, resume_tokens)
1669
1803
path = target.bzrdir._path_for_remote_call(client)
1670
if not resume_tokens:
1671
# XXX: Ugly but important for correctness, *will* be fixed during
1672
# 1.13 cycle. Pushing a stream that is interrupted results in a
1673
# fallback to the _real_repositories sink *with a partial stream*.
1674
# Thats bad because we insert less data than bzr expected. To avoid
1675
# this we do a trial push to make sure the verb is accessible, and
1676
# do not fallback when actually pushing the stream. A cleanup patch
1677
# is going to look at rewinding/restarting the stream/partial
1804
# Probe for the verb to use with an empty stream before sending the
1805
# real stream to it. We do this both to avoid the risk of sending a
1806
# large request that is then rejected, and because we don't want to
1807
# implement a way to buffer, rewind, or restart the stream.
1809
for verb, required_version in candidate_calls:
1810
if medium._is_remote_before(required_version):
1813
# We've already done the probing (and set _is_remote_before) on
1814
# a previous insert.
1679
1817
byte_stream = smart_repo._stream_to_byte_stream([], src_format)
1681
1819
response = client.call_with_body_stream(
1682
(verb, path, '') + extra_args, byte_stream)
1820
(verb, path, '') + lock_args, byte_stream)
1683
1821
except errors.UnknownSmartMethod:
1684
1822
medium._remember_remote_is_before(required_version)
1685
return self._insert_real(stream, src_format, resume_tokens)
1828
return self._insert_real(stream, src_format, resume_tokens)
1829
self._last_inv_record = None
1830
self._last_substream = None
1831
if required_version < (1, 19):
1832
# Remote side doesn't support inventory deltas. Wrap the stream to
1833
# make sure we don't send any. If the stream contains inventory
1834
# deltas we'll interrupt the smart insert_stream request and
1836
stream = self._stop_stream_if_inventory_delta(stream)
1686
1837
byte_stream = smart_repo._stream_to_byte_stream(
1687
1838
stream, src_format)
1688
1839
resume_tokens = ' '.join(resume_tokens)
1689
1840
response = client.call_with_body_stream(
1690
(verb, path, resume_tokens) + extra_args, byte_stream)
1841
(verb, path, resume_tokens) + lock_args, byte_stream)
1691
1842
if response[0][0] not in ('ok', 'missing-basis'):
1692
1843
raise errors.UnexpectedSmartServerResponse(response)
1844
if self._last_substream is not None:
1845
# The stream included an inventory-delta record, but the remote
1846
# side isn't new enough to support them. So we need to send the
1847
# rest of the stream via VFS.
1848
self.target_repo.refresh_data()
1849
return self._resume_stream_with_vfs(response, src_format)
1693
1850
if response[0][0] == 'missing-basis':
1694
1851
tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1695
1852
resume_tokens = tokens
1698
1855
self.target_repo.refresh_data()
1699
1856
return [], set()
1858
def _resume_stream_with_vfs(self, response, src_format):
1859
"""Resume sending a stream via VFS, first resending the record and
1860
substream that couldn't be sent via an insert_stream verb.
1862
if response[0][0] == 'missing-basis':
1863
tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1864
# Ignore missing_keys, we haven't finished inserting yet
1867
def resume_substream():
1868
# Yield the substream that was interrupted.
1869
for record in self._last_substream:
1871
self._last_substream = None
1872
def resume_stream():
1873
# Finish sending the interrupted substream
1874
yield ('inventory-deltas', resume_substream())
1875
# Then simply continue sending the rest of the stream.
1876
for substream_kind, substream in self._last_stream:
1877
yield substream_kind, substream
1878
return self._insert_real(resume_stream(), src_format, tokens)
1880
def _stop_stream_if_inventory_delta(self, stream):
1881
"""Normally this just lets the original stream pass-through unchanged.
1883
However if any 'inventory-deltas' substream occurs it will stop
1884
streaming, and store the interrupted substream and stream in
1885
self._last_substream and self._last_stream so that the stream can be
1886
resumed by _resume_stream_with_vfs.
1889
stream_iter = iter(stream)
1890
for substream_kind, substream in stream_iter:
1891
if substream_kind == 'inventory-deltas':
1892
self._last_substream = substream
1893
self._last_stream = stream_iter
1896
yield substream_kind, substream
1702
1899
class RemoteStreamSource(repository.StreamSource):
1703
1900
"""Stream data from a remote server."""
1706
1903
if (self.from_repository._fallback_repositories and
1707
1904
self.to_format._fetch_order == 'topological'):
1708
1905
return self._real_stream(self.from_repository, search)
1709
return self.missing_parents_chain(search, [self.from_repository] +
1710
self.from_repository._fallback_repositories)
1908
repos = [self.from_repository]
1914
repos.extend(repo._fallback_repositories)
1915
sources.append(repo)
1916
return self.missing_parents_chain(search, sources)
1918
def get_stream_for_missing_keys(self, missing_keys):
1919
self.from_repository._ensure_real()
1920
real_repo = self.from_repository._real_repository
1921
real_source = real_repo._get_source(self.to_format)
1922
return real_source.get_stream_for_missing_keys(missing_keys)
1712
1924
def _real_stream(self, repo, search):
1713
1925
"""Get a stream for search from repo.
1743
1956
return self._real_stream(repo, search)
1744
1957
client = repo._client
1745
1958
medium = client._medium
1746
if medium._is_remote_before((1, 13)):
1747
# streaming was added in 1.13
1748
return self._real_stream(repo, search)
1749
1959
path = repo.bzrdir._path_for_remote_call(client)
1751
search_bytes = repo._serialise_search_result(search)
1752
response = repo._call_with_body_bytes_expecting_body(
1753
'Repository.get_stream',
1754
(path, self.to_format.network_name()), search_bytes)
1755
response_tuple, response_handler = response
1756
except errors.UnknownSmartMethod:
1757
medium._remember_remote_is_before((1,13))
1960
search_bytes = repo._serialise_search_result(search)
1961
args = (path, self.to_format.network_name())
1963
('Repository.get_stream_1.19', (1, 19)),
1964
('Repository.get_stream', (1, 13))]
1966
for verb, version in candidate_verbs:
1967
if medium._is_remote_before(version):
1970
response = repo._call_with_body_bytes_expecting_body(
1971
verb, args, search_bytes)
1972
except errors.UnknownSmartMethod:
1973
medium._remember_remote_is_before(version)
1975
response_tuple, response_handler = response
1758
1979
return self._real_stream(repo, search)
1759
1980
if response_tuple[0] != 'ok':
1760
1981
raise errors.UnexpectedSmartServerResponse(response_tuple)
1761
1982
byte_stream = response_handler.read_streamed_body()
1762
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1983
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1984
self._record_counter)
1763
1985
if src_format.network_name() != repo._format.network_name():
1764
1986
raise AssertionError(
1765
1987
"Mismatched RemoteRepository and stream src %r, %r" % (
1840
2063
self._network_name)
1842
2065
def get_format_description(self):
1843
return 'Remote BZR Branch'
2067
return 'Remote: ' + self._custom_format.get_format_description()
1845
2069
def network_name(self):
1846
2070
return self._network_name
1848
def open(self, a_bzrdir, ignore_fallbacks=False):
1849
return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2072
def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2073
return a_bzrdir.open_branch(name=name,
2074
ignore_fallbacks=ignore_fallbacks)
1851
def _vfs_initialize(self, a_bzrdir):
2076
def _vfs_initialize(self, a_bzrdir, name):
1852
2077
# Initialisation when using a local bzrdir object, or a non-vfs init
1853
2078
# method is not available on the server.
1854
2079
# self._custom_format is always set - the start of initialize ensures
1856
2081
if isinstance(a_bzrdir, RemoteBzrDir):
1857
2082
a_bzrdir._ensure_real()
1858
result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2083
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
1860
2086
# We assume the bzrdir is parameterised; it may not be.
1861
result = self._custom_format.initialize(a_bzrdir)
2087
result = self._custom_format.initialize(a_bzrdir, name)
1862
2088
if (isinstance(a_bzrdir, RemoteBzrDir) and
1863
2089
not isinstance(result, RemoteBranch)):
1864
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2090
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
1867
def initialize(self, a_bzrdir):
2094
def initialize(self, a_bzrdir, name=None):
1868
2095
# 1) get the network name to use.
1869
2096
if self._custom_format:
1870
2097
network_name = self._custom_format.network_name()
1876
2103
network_name = reference_format.network_name()
1877
2104
# Being asked to create on a non RemoteBzrDir:
1878
2105
if not isinstance(a_bzrdir, RemoteBzrDir):
1879
return self._vfs_initialize(a_bzrdir)
2106
return self._vfs_initialize(a_bzrdir, name=name)
1880
2107
medium = a_bzrdir._client._medium
1881
2108
if medium._is_remote_before((1, 13)):
1882
return self._vfs_initialize(a_bzrdir)
2109
return self._vfs_initialize(a_bzrdir, name=name)
1883
2110
# Creating on a remote bzr dir.
1884
2111
# 2) try direct creation via RPC
1885
2112
path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2113
if name is not None:
2114
# XXX JRV20100304: Support creating colocated branches
2115
raise errors.NoColocatedBranchSupport(self)
1886
2116
verb = 'BzrDir.create_branch'
1888
2118
response = a_bzrdir._call(verb, path, network_name)
1889
2119
except errors.UnknownSmartMethod:
1890
2120
# Fallback - use vfs methods
1891
2121
medium._remember_remote_is_before((1, 13))
1892
return self._vfs_initialize(a_bzrdir)
2122
return self._vfs_initialize(a_bzrdir, name=name)
1893
2123
if response[0] != 'ok':
1894
2124
raise errors.UnexpectedSmartServerResponse(response)
1895
2125
# Turn the response into a RemoteRepository object.
1929
2159
return self._custom_format.supports_set_append_revisions_only()
1932
class RemoteBranch(branch.Branch, _RpcHelper):
2162
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
1933
2163
"""Branch stored on a server accessed by HPSS RPC.
1935
2165
At the moment most operations are mapped down to simple file operations.
1938
2168
def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
1939
_client=None, format=None, setup_stacking=True):
2169
_client=None, format=None, setup_stacking=True, name=None):
1940
2170
"""Create a RemoteBranch instance.
1942
2172
:param real_branch: An optional local implementation of the branch
2141
2378
return self._vfs_get_tags_bytes()
2142
2379
return response[0]
2381
def _vfs_set_tags_bytes(self, bytes):
2383
return self._real_branch._set_tags_bytes(bytes)
2385
def _set_tags_bytes(self, bytes):
2386
medium = self._client._medium
2387
if medium._is_remote_before((1, 18)):
2388
self._vfs_set_tags_bytes(bytes)
2392
self._remote_path(), self._lock_token, self._repo_lock_token)
2393
response = self._call_with_body_bytes(
2394
'Branch.set_tags_bytes', args, bytes)
2395
except errors.UnknownSmartMethod:
2396
medium._remember_remote_is_before((1, 18))
2397
self._vfs_set_tags_bytes(bytes)
2144
2399
def lock_read(self):
2400
"""Lock the branch for read operations.
2402
:return: A bzrlib.lock.LogicalLockResult.
2145
2404
self.repository.lock_read()
2146
2405
if not self._lock_mode:
2406
self._note_lock('r')
2147
2407
self._lock_mode = 'r'
2148
2408
self._lock_count = 1
2149
2409
if self._real_branch is not None:
2150
2410
self._real_branch.lock_read()
2152
2412
self._lock_count += 1
2413
return lock.LogicalLockResult(self.unlock)
2154
2415
def _remote_lock_write(self, token):
2155
2416
if token is None:
2156
2417
branch_token = repo_token = ''
2158
2419
branch_token = token
2159
repo_token = self.repository.lock_write()
2420
repo_token = self.repository.lock_write().repository_token
2160
2421
self.repository.unlock()
2161
2422
err_context = {'token': token}
2162
response = self._call(
2163
'Branch.lock_write', self._remote_path(), branch_token,
2164
repo_token or '', **err_context)
2424
response = self._call(
2425
'Branch.lock_write', self._remote_path(), branch_token,
2426
repo_token or '', **err_context)
2427
except errors.LockContention, e:
2428
# The LockContention from the server doesn't have any
2429
# information about the lock_url. We re-raise LockContention
2430
# with valid lock_url.
2431
raise errors.LockContention('(remote lock)',
2432
self.repository.base.split('.bzr/')[0])
2165
2433
if response[0] != 'ok':
2166
2434
raise errors.UnexpectedSmartServerResponse(response)
2167
2435
ok, branch_token, repo_token = response
2529
2796
medium = self._branch._client._medium
2530
2797
if medium._is_remote_before((1, 14)):
2531
2798
return self._vfs_set_option(value, name, section)
2799
if isinstance(value, dict):
2800
if medium._is_remote_before((2, 2)):
2801
return self._vfs_set_option(value, name, section)
2802
return self._set_config_option_dict(value, name, section)
2804
return self._set_config_option(value, name, section)
2806
def _set_config_option(self, value, name, section):
2533
2808
path = self._branch._remote_path()
2534
2809
response = self._branch._client.call('Branch.set_config_option',
2535
2810
path, self._branch._lock_token, self._branch._repo_lock_token,
2536
2811
value.encode('utf8'), name, section or '')
2537
2812
except errors.UnknownSmartMethod:
2813
medium = self._branch._client._medium
2538
2814
medium._remember_remote_is_before((1, 14))
2539
2815
return self._vfs_set_option(value, name, section)
2540
2816
if response != ():
2541
2817
raise errors.UnexpectedSmartServerResponse(response)
2819
def _serialize_option_dict(self, option_dict):
2821
for key, value in option_dict.items():
2822
if isinstance(key, unicode):
2823
key = key.encode('utf8')
2824
if isinstance(value, unicode):
2825
value = value.encode('utf8')
2826
utf8_dict[key] = value
2827
return bencode.bencode(utf8_dict)
2829
def _set_config_option_dict(self, value, name, section):
2831
path = self._branch._remote_path()
2832
serialised_dict = self._serialize_option_dict(value)
2833
response = self._branch._client.call(
2834
'Branch.set_config_option_dict',
2835
path, self._branch._lock_token, self._branch._repo_lock_token,
2836
serialised_dict, name, section or '')
2837
except errors.UnknownSmartMethod:
2838
medium = self._branch._client._medium
2839
medium._remember_remote_is_before((2, 2))
2840
return self._vfs_set_option(value, name, section)
2842
raise errors.UnexpectedSmartServerResponse(response)
2543
2844
def _real_object(self):
2544
2845
self._branch._ensure_real()
2545
2846
return self._branch._real_branch
2628
2929
'Missing key %r in context %r', key_err.args[0], context)
2631
if err.error_verb == 'NoSuchRevision':
2932
if err.error_verb == 'IncompatibleRepositories':
2933
raise errors.IncompatibleRepositories(err.error_args[0],
2934
err.error_args[1], err.error_args[2])
2935
elif err.error_verb == 'NoSuchRevision':
2632
2936
raise NoSuchRevision(find('branch'), err.error_args[0])
2633
2937
elif err.error_verb == 'nosuchrevision':
2634
2938
raise NoSuchRevision(find('repository'), err.error_args[0])
2635
elif err.error_tuple == ('nobranch',):
2636
raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2939
elif err.error_verb == 'nobranch':
2940
if len(err.error_args) >= 1:
2941
extra = err.error_args[0]
2944
raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2637
2946
elif err.error_verb == 'norepository':
2638
2947
raise errors.NoRepositoryPresent(find('bzrdir'))
2639
2948
elif err.error_verb == 'LockContention':