63
61
except errors.ErrorFromSmartServer, err:
64
62
self._translate_error(err, **err_context)
66
def _call_with_body_bytes(self, method, args, body_bytes, **err_context):
68
return self._client.call_with_body_bytes(method, args, body_bytes)
69
except errors.ErrorFromSmartServer, err:
70
self._translate_error(err, **err_context)
72
64
def _call_with_body_bytes_expecting_body(self, method, args, body_bytes,
113
104
self._client = client._SmartClient(medium)
115
106
self._client = _client
122
return '%s(%r)' % (self.__class__.__name__, self._client)
124
def _probe_bzrdir(self):
125
medium = self._client._medium
126
109
path = self._path_for_remote_call(self._client)
127
if medium._is_remote_before((2, 1)):
131
self._rpc_open_2_1(path)
133
except errors.UnknownSmartMethod:
134
medium._remember_remote_is_before((2, 1))
137
def _rpc_open_2_1(self, path):
138
response = self._call('BzrDir.open_2.1', path)
139
if response == ('no',):
140
raise errors.NotBranchError(path=self.root_transport.base)
141
elif response[0] == 'yes':
142
if response[1] == 'yes':
143
self._has_working_tree = True
144
elif response[1] == 'no':
145
self._has_working_tree = False
147
raise errors.UnexpectedSmartServerResponse(response)
149
raise errors.UnexpectedSmartServerResponse(response)
151
def _rpc_open(self, path):
152
110
response = self._call('BzrDir.open', path)
153
111
if response not in [('yes',), ('no',)]:
154
112
raise errors.UnexpectedSmartServerResponse(response)
155
113
if response == ('no',):
156
raise errors.NotBranchError(path=self.root_transport.base)
114
raise errors.NotBranchError(path=transport.base)
158
116
def _ensure_real(self):
159
117
"""Ensure that there is a _real_bzrdir set.
246
200
self._ensure_real()
247
201
self._real_bzrdir.destroy_repository()
249
def create_branch(self, name=None):
203
def create_branch(self):
250
204
# as per meta1 formats - just delegate to the format object which may
251
205
# be parameterised.
252
real_branch = self._format.get_branch_format().initialize(self,
206
real_branch = self._format.get_branch_format().initialize(self)
254
207
if not isinstance(real_branch, RemoteBranch):
255
result = RemoteBranch(self, self.find_repository(), real_branch,
208
result = RemoteBranch(self, self.find_repository(), real_branch)
258
210
result = real_branch
259
211
# BzrDir.clone_on_transport() uses the result of create_branch but does
265
217
self._next_open_branch_result = result
268
def destroy_branch(self, name=None):
220
def destroy_branch(self):
269
221
"""See BzrDir.destroy_branch"""
270
222
self._ensure_real()
271
self._real_bzrdir.destroy_branch(name=name)
223
self._real_bzrdir.destroy_branch()
272
224
self._next_open_branch_result = None
274
def create_workingtree(self, revision_id=None, from_branch=None,
275
accelerator_tree=None, hardlink=False):
226
def create_workingtree(self, revision_id=None, from_branch=None):
276
227
raise errors.NotLocalUrl(self.transport.base)
278
def find_branch_format(self, name=None):
229
def find_branch_format(self):
279
230
"""Find the branch 'format' for this bzrdir.
281
232
This might be a synthetic object for e.g. RemoteBranch and SVN.
283
b = self.open_branch(name=name)
234
b = self.open_branch()
286
def get_branch_reference(self, name=None):
237
def get_branch_reference(self):
287
238
"""See BzrDir.get_branch_reference()."""
289
# XXX JRV20100304: Support opening colocated branches
290
raise errors.NoColocatedBranchSupport(self)
291
239
response = self._get_branch_reference()
292
240
if response[0] == 'ref':
293
241
return response[1]
297
245
def _get_branch_reference(self):
298
246
path = self._path_for_remote_call(self._client)
299
247
medium = self._client._medium
301
('BzrDir.open_branchV3', (2, 1)),
302
('BzrDir.open_branchV2', (1, 13)),
303
('BzrDir.open_branch', None),
305
for verb, required_version in candidate_calls:
306
if required_version and medium._is_remote_before(required_version):
248
if not medium._is_remote_before((1, 13)):
309
response = self._call(verb, path)
250
response = self._call('BzrDir.open_branchV2', path)
251
if response[0] not in ('ref', 'branch'):
252
raise errors.UnexpectedSmartServerResponse(response)
310
254
except errors.UnknownSmartMethod:
311
if required_version is None:
313
medium._remember_remote_is_before(required_version)
316
if verb == 'BzrDir.open_branch':
317
if response[0] != 'ok':
318
raise errors.UnexpectedSmartServerResponse(response)
319
if response[1] != '':
320
return ('ref', response[1])
322
return ('branch', '')
323
if response[0] not in ('ref', 'branch'):
255
medium._remember_remote_is_before((1, 13))
256
response = self._call('BzrDir.open_branch', path)
257
if response[0] != 'ok':
324
258
raise errors.UnexpectedSmartServerResponse(response)
259
if response[1] != '':
260
return ('ref', response[1])
262
return ('branch', '')
327
def _get_tree_branch(self, name=None):
264
def _get_tree_branch(self):
328
265
"""See BzrDir._get_tree_branch()."""
329
return None, self.open_branch(name=name)
266
return None, self.open_branch()
331
def open_branch(self, name=None, unsupported=False,
332
ignore_fallbacks=False):
268
def open_branch(self, _unsupported=False, ignore_fallbacks=False):
334
270
raise NotImplementedError('unsupported flag support not implemented yet.')
335
271
if self._next_open_branch_result is not None:
336
272
# See create_branch for details.
341
277
if response[0] == 'ref':
342
278
# a branch reference, use the existing BranchReference logic.
343
279
format = BranchReferenceFormat()
344
return format.open(self, name=name, _found=True,
345
location=response[1], ignore_fallbacks=ignore_fallbacks)
280
return format.open(self, _found=True, location=response[1],
281
ignore_fallbacks=ignore_fallbacks)
346
282
branch_format_name = response[1]
347
283
if not branch_format_name:
348
284
branch_format_name = None
349
285
format = RemoteBranchFormat(network_name=branch_format_name)
350
286
return RemoteBranch(self, self.find_repository(), format=format,
351
setup_stacking=not ignore_fallbacks, name=name)
287
setup_stacking=not ignore_fallbacks)
353
289
def _open_repo_v1(self, path):
354
290
verb = 'BzrDir.find_repository'
626
545
return self._custom_format._fetch_reconcile
628
547
def get_format_description(self):
630
return 'Remote: ' + self._custom_format.get_format_description()
548
return 'bzr remote repository'
632
550
def __eq__(self, other):
633
551
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)
635
562
def network_name(self):
636
563
if self._network_name:
637
564
return self._network_name
898
813
result.add(_mod_revision.NULL_REVISION)
901
def _has_same_fallbacks(self, other_repo):
902
"""Returns true if the repositories have the same fallbacks."""
903
# XXX: copied from Repository; it should be unified into a base class
904
# <https://bugs.launchpad.net/bzr/+bug/401622>
905
my_fb = self._fallback_repositories
906
other_fb = other_repo._fallback_repositories
907
if len(my_fb) != len(other_fb):
909
for f, g in zip(my_fb, other_fb):
910
if not f.has_same_location(g):
914
816
def has_same_location(self, other):
915
# TODO: Move to RepositoryBase and unify with the regular Repository
916
# one; unfortunately the tests rely on slightly different behaviour at
917
# present -- mbp 20090710
918
817
return (self.__class__ is other.__class__ and
919
818
self.bzrdir.transport.base == other.bzrdir.transport.base)
923
822
parents_provider = self._make_parents_provider(other_repository)
924
823
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)
935
825
def gather_stats(self, revid=None, committers=None):
936
826
"""See Repository.gather_stats()."""
937
827
path = self.bzrdir._path_for_remote_call(self._client)
1251
1128
# state, so always add a lock here. If a caller passes us a locked
1252
1129
# repository, they are responsible for unlocking it later.
1253
1130
repository.lock_read()
1254
self._check_fallback_repository(repository)
1255
1131
self._fallback_repositories.append(repository)
1256
1132
# If self._real_repository was parameterised already (e.g. because a
1257
1133
# _real_branch had its get_stacked_on_url method called), then the
1258
1134
# repository to be added may already be in the _real_repositories list.
1259
1135
if self._real_repository is not None:
1260
fallback_locations = [repo.user_url for repo in
1136
fallback_locations = [repo.bzrdir.root_transport.base for repo in
1261
1137
self._real_repository._fallback_repositories]
1262
if repository.user_url not in fallback_locations:
1138
if repository.bzrdir.root_transport.base not in fallback_locations:
1263
1139
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(
1275
1141
def add_inventory(self, revid, inv, parents):
1276
1142
self._ensure_real()
1277
1143
return self._real_repository.add_inventory(revid, inv, parents)
1279
1145
def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1280
parents, basis_inv=None, propagate_caches=False):
1281
1147
self._ensure_real()
1282
1148
return self._real_repository.add_inventory_by_delta(basis_revision_id,
1283
delta, new_revision_id, parents, basis_inv=basis_inv,
1284
propagate_caches=propagate_caches)
1149
delta, new_revision_id, parents)
1286
1151
def add_revision(self, rev_id, rev, inv=None, config=None):
1287
1152
self._ensure_real()
1317
1182
return self._real_repository.make_working_trees()
1319
1184
def refresh_data(self):
1320
"""Re-read any data needed to synchronise with disk.
1185
"""Re-read any data needed to to synchronise with disk.
1322
1187
This method is intended to be called after another repository instance
1323
1188
(such as one used by a smart server) has inserted data into the
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.
1189
repository. It may not be called during a write group, but may be
1190
called at any other time.
1192
if self.is_in_write_group():
1193
raise errors.InternalBzrError(
1194
"May not refresh_data while in a write group.")
1330
1195
if self._real_repository is not None:
1331
1196
self._real_repository.refresh_data()
1793
1658
def insert_stream(self, stream, src_format, resume_tokens):
1794
1659
target = self.target_repo
1795
1660
target._unstacked_provider.missing_keys.clear()
1796
candidate_calls = [('Repository.insert_stream_1.19', (1, 19))]
1797
1661
if target._lock_token:
1798
candidate_calls.append(('Repository.insert_stream_locked', (1, 14)))
1799
lock_args = (target._lock_token or '',)
1662
verb = 'Repository.insert_stream_locked'
1663
extra_args = (target._lock_token or '',)
1664
required_version = (1, 14)
1801
candidate_calls.append(('Repository.insert_stream', (1, 13)))
1666
verb = 'Repository.insert_stream'
1668
required_version = (1, 13)
1803
1669
client = target._client
1804
1670
medium = client._medium
1671
if medium._is_remote_before(required_version):
1672
# No possible way this can work.
1673
return self._insert_real(stream, src_format, resume_tokens)
1805
1674
path = target.bzrdir._path_for_remote_call(client)
1806
# Probe for the verb to use with an empty stream before sending the
1807
# real stream to it. We do this both to avoid the risk of sending a
1808
# large request that is then rejected, and because we don't want to
1809
# implement a way to buffer, rewind, or restart the stream.
1811
for verb, required_version in candidate_calls:
1812
if medium._is_remote_before(required_version):
1815
# We've already done the probing (and set _is_remote_before) on
1816
# a previous insert.
1675
if not resume_tokens:
1676
# XXX: Ugly but important for correctness, *will* be fixed during
1677
# 1.13 cycle. Pushing a stream that is interrupted results in a
1678
# fallback to the _real_repositories sink *with a partial stream*.
1679
# Thats bad because we insert less data than bzr expected. To avoid
1680
# this we do a trial push to make sure the verb is accessible, and
1681
# do not fallback when actually pushing the stream. A cleanup patch
1682
# is going to look at rewinding/restarting the stream/partial
1819
1684
byte_stream = smart_repo._stream_to_byte_stream([], src_format)
1821
1686
response = client.call_with_body_stream(
1822
(verb, path, '') + lock_args, byte_stream)
1687
(verb, path, '') + extra_args, byte_stream)
1823
1688
except errors.UnknownSmartMethod:
1824
1689
medium._remember_remote_is_before(required_version)
1830
return self._insert_real(stream, src_format, resume_tokens)
1831
self._last_inv_record = None
1832
self._last_substream = None
1833
if required_version < (1, 19):
1834
# Remote side doesn't support inventory deltas. Wrap the stream to
1835
# make sure we don't send any. If the stream contains inventory
1836
# deltas we'll interrupt the smart insert_stream request and
1838
stream = self._stop_stream_if_inventory_delta(stream)
1690
return self._insert_real(stream, src_format, resume_tokens)
1839
1691
byte_stream = smart_repo._stream_to_byte_stream(
1840
1692
stream, src_format)
1841
1693
resume_tokens = ' '.join(resume_tokens)
1842
1694
response = client.call_with_body_stream(
1843
(verb, path, resume_tokens) + lock_args, byte_stream)
1695
(verb, path, resume_tokens) + extra_args, byte_stream)
1844
1696
if response[0][0] not in ('ok', 'missing-basis'):
1845
1697
raise errors.UnexpectedSmartServerResponse(response)
1846
if self._last_substream is not None:
1847
# The stream included an inventory-delta record, but the remote
1848
# side isn't new enough to support them. So we need to send the
1849
# rest of the stream via VFS.
1850
self.target_repo.refresh_data()
1851
return self._resume_stream_with_vfs(response, src_format)
1852
1698
if response[0][0] == 'missing-basis':
1853
1699
tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1854
1700
resume_tokens = tokens
1857
1703
self.target_repo.refresh_data()
1858
1704
return [], set()
1860
def _resume_stream_with_vfs(self, response, src_format):
1861
"""Resume sending a stream via VFS, first resending the record and
1862
substream that couldn't be sent via an insert_stream verb.
1864
if response[0][0] == 'missing-basis':
1865
tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1866
# Ignore missing_keys, we haven't finished inserting yet
1869
def resume_substream():
1870
# Yield the substream that was interrupted.
1871
for record in self._last_substream:
1873
self._last_substream = None
1874
def resume_stream():
1875
# Finish sending the interrupted substream
1876
yield ('inventory-deltas', resume_substream())
1877
# Then simply continue sending the rest of the stream.
1878
for substream_kind, substream in self._last_stream:
1879
yield substream_kind, substream
1880
return self._insert_real(resume_stream(), src_format, tokens)
1882
def _stop_stream_if_inventory_delta(self, stream):
1883
"""Normally this just lets the original stream pass-through unchanged.
1885
However if any 'inventory-deltas' substream occurs it will stop
1886
streaming, and store the interrupted substream and stream in
1887
self._last_substream and self._last_stream so that the stream can be
1888
resumed by _resume_stream_with_vfs.
1891
stream_iter = iter(stream)
1892
for substream_kind, substream in stream_iter:
1893
if substream_kind == 'inventory-deltas':
1894
self._last_substream = substream
1895
self._last_stream = stream_iter
1898
yield substream_kind, substream
1901
1707
class RemoteStreamSource(repository.StreamSource):
1902
1708
"""Stream data from a remote server."""
1905
1711
if (self.from_repository._fallback_repositories and
1906
1712
self.to_format._fetch_order == 'topological'):
1907
1713
return self._real_stream(self.from_repository, search)
1910
repos = [self.from_repository]
1916
repos.extend(repo._fallback_repositories)
1917
sources.append(repo)
1918
return self.missing_parents_chain(search, sources)
1920
def get_stream_for_missing_keys(self, missing_keys):
1921
self.from_repository._ensure_real()
1922
real_repo = self.from_repository._real_repository
1923
real_source = real_repo._get_source(self.to_format)
1924
return real_source.get_stream_for_missing_keys(missing_keys)
1714
return self.missing_parents_chain(search, [self.from_repository] +
1715
self.from_repository._fallback_repositories)
1926
1717
def _real_stream(self, repo, search):
1927
1718
"""Get a stream for search from repo.
1958
1748
return self._real_stream(repo, search)
1959
1749
client = repo._client
1960
1750
medium = client._medium
1751
if medium._is_remote_before((1, 13)):
1752
# streaming was added in 1.13
1753
return self._real_stream(repo, search)
1961
1754
path = repo.bzrdir._path_for_remote_call(client)
1962
search_bytes = repo._serialise_search_result(search)
1963
args = (path, self.to_format.network_name())
1965
('Repository.get_stream_1.19', (1, 19)),
1966
('Repository.get_stream', (1, 13))]
1968
for verb, version in candidate_verbs:
1969
if medium._is_remote_before(version):
1972
response = repo._call_with_body_bytes_expecting_body(
1973
verb, args, search_bytes)
1974
except errors.UnknownSmartMethod:
1975
medium._remember_remote_is_before(version)
1977
response_tuple, response_handler = response
1756
search_bytes = repo._serialise_search_result(search)
1757
response = repo._call_with_body_bytes_expecting_body(
1758
'Repository.get_stream',
1759
(path, self.to_format.network_name()), search_bytes)
1760
response_tuple, response_handler = response
1761
except errors.UnknownSmartMethod:
1762
medium._remember_remote_is_before((1,13))
1981
1763
return self._real_stream(repo, search)
1982
1764
if response_tuple[0] != 'ok':
1983
1765
raise errors.UnexpectedSmartServerResponse(response_tuple)
1984
1766
byte_stream = response_handler.read_streamed_body()
1985
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1986
self._record_counter)
1767
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1987
1768
if src_format.network_name() != repo._format.network_name():
1988
1769
raise AssertionError(
1989
1770
"Mismatched RemoteRepository and stream src %r, %r" % (
2065
1845
self._network_name)
2067
1847
def get_format_description(self):
2069
return 'Remote: ' + self._custom_format.get_format_description()
1848
return 'Remote BZR Branch'
2071
1850
def network_name(self):
2072
1851
return self._network_name
2074
def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2075
return a_bzrdir.open_branch(name=name,
2076
ignore_fallbacks=ignore_fallbacks)
1853
def open(self, a_bzrdir, ignore_fallbacks=False):
1854
return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2078
def _vfs_initialize(self, a_bzrdir, name):
1856
def _vfs_initialize(self, a_bzrdir):
2079
1857
# Initialisation when using a local bzrdir object, or a non-vfs init
2080
1858
# method is not available on the server.
2081
1859
# self._custom_format is always set - the start of initialize ensures
2083
1861
if isinstance(a_bzrdir, RemoteBzrDir):
2084
1862
a_bzrdir._ensure_real()
2085
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
1863
result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2088
1865
# We assume the bzrdir is parameterised; it may not be.
2089
result = self._custom_format.initialize(a_bzrdir, name)
1866
result = self._custom_format.initialize(a_bzrdir)
2090
1867
if (isinstance(a_bzrdir, RemoteBzrDir) and
2091
1868
not isinstance(result, RemoteBranch)):
2092
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
1869
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2096
def initialize(self, a_bzrdir, name=None):
1872
def initialize(self, a_bzrdir):
2097
1873
# 1) get the network name to use.
2098
1874
if self._custom_format:
2099
1875
network_name = self._custom_format.network_name()
2105
1881
network_name = reference_format.network_name()
2106
1882
# Being asked to create on a non RemoteBzrDir:
2107
1883
if not isinstance(a_bzrdir, RemoteBzrDir):
2108
return self._vfs_initialize(a_bzrdir, name=name)
1884
return self._vfs_initialize(a_bzrdir)
2109
1885
medium = a_bzrdir._client._medium
2110
1886
if medium._is_remote_before((1, 13)):
2111
return self._vfs_initialize(a_bzrdir, name=name)
1887
return self._vfs_initialize(a_bzrdir)
2112
1888
# Creating on a remote bzr dir.
2113
1889
# 2) try direct creation via RPC
2114
1890
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)
2118
1891
verb = 'BzrDir.create_branch'
2120
1893
response = a_bzrdir._call(verb, path, network_name)
2121
1894
except errors.UnknownSmartMethod:
2122
1895
# Fallback - use vfs methods
2123
1896
medium._remember_remote_is_before((1, 13))
2124
return self._vfs_initialize(a_bzrdir, name=name)
1897
return self._vfs_initialize(a_bzrdir)
2125
1898
if response[0] != 'ok':
2126
1899
raise errors.UnexpectedSmartServerResponse(response)
2127
1900
# Turn the response into a RemoteRepository object.
2161
1934
return self._custom_format.supports_set_append_revisions_only()
2164
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
1937
class RemoteBranch(branch.Branch, _RpcHelper):
2165
1938
"""Branch stored on a server accessed by HPSS RPC.
2167
1940
At the moment most operations are mapped down to simple file operations.
2170
1943
def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2171
_client=None, format=None, setup_stacking=True, name=None):
1944
_client=None, format=None, setup_stacking=True):
2172
1945
"""Create a RemoteBranch instance.
2174
1947
:param real_branch: An optional local implementation of the branch
2380
2146
return self._vfs_get_tags_bytes()
2381
2147
return response[0]
2383
def _vfs_set_tags_bytes(self, bytes):
2385
return self._real_branch._set_tags_bytes(bytes)
2387
def _set_tags_bytes(self, bytes):
2388
medium = self._client._medium
2389
if medium._is_remote_before((1, 18)):
2390
self._vfs_set_tags_bytes(bytes)
2394
self._remote_path(), self._lock_token, self._repo_lock_token)
2395
response = self._call_with_body_bytes(
2396
'Branch.set_tags_bytes', args, bytes)
2397
except errors.UnknownSmartMethod:
2398
medium._remember_remote_is_before((1, 18))
2399
self._vfs_set_tags_bytes(bytes)
2401
2149
def lock_read(self):
2402
"""Lock the branch for read operations.
2404
:return: A bzrlib.lock.LogicalLockResult.
2406
2150
self.repository.lock_read()
2407
2151
if not self._lock_mode:
2408
self._note_lock('r')
2409
2152
self._lock_mode = 'r'
2410
2153
self._lock_count = 1
2411
2154
if self._real_branch is not None:
2412
2155
self._real_branch.lock_read()
2414
2157
self._lock_count += 1
2415
return lock.LogicalLockResult(self.unlock)
2417
2159
def _remote_lock_write(self, token):
2418
2160
if token is None:
2419
2161
branch_token = repo_token = ''
2421
2163
branch_token = token
2422
repo_token = self.repository.lock_write().repository_token
2164
repo_token = self.repository.lock_write()
2423
2165
self.repository.unlock()
2424
2166
err_context = {'token': token}
2426
response = self._call(
2427
'Branch.lock_write', self._remote_path(), branch_token,
2428
repo_token or '', **err_context)
2429
except errors.LockContention, e:
2430
# The LockContention from the server doesn't have any
2431
# information about the lock_url. We re-raise LockContention
2432
# with valid lock_url.
2433
raise errors.LockContention('(remote lock)',
2434
self.repository.base.split('.bzr/')[0])
2167
response = self._call(
2168
'Branch.lock_write', self._remote_path(), branch_token,
2169
repo_token or '', **err_context)
2435
2170
if response[0] != 'ok':
2436
2171
raise errors.UnexpectedSmartServerResponse(response)
2437
2172
ok, branch_token, repo_token = response
2798
2534
medium = self._branch._client._medium
2799
2535
if medium._is_remote_before((1, 14)):
2800
2536
return self._vfs_set_option(value, name, section)
2801
if isinstance(value, dict):
2802
if medium._is_remote_before((2, 2)):
2803
return self._vfs_set_option(value, name, section)
2804
return self._set_config_option_dict(value, name, section)
2806
return self._set_config_option(value, name, section)
2808
def _set_config_option(self, value, name, section):
2810
2538
path = self._branch._remote_path()
2811
2539
response = self._branch._client.call('Branch.set_config_option',
2812
2540
path, self._branch._lock_token, self._branch._repo_lock_token,
2813
2541
value.encode('utf8'), name, section or '')
2814
2542
except errors.UnknownSmartMethod:
2815
medium = self._branch._client._medium
2816
2543
medium._remember_remote_is_before((1, 14))
2817
2544
return self._vfs_set_option(value, name, section)
2818
2545
if response != ():
2819
2546
raise errors.UnexpectedSmartServerResponse(response)
2821
def _serialize_option_dict(self, option_dict):
2823
for key, value in option_dict.items():
2824
if isinstance(key, unicode):
2825
key = key.encode('utf8')
2826
if isinstance(value, unicode):
2827
value = value.encode('utf8')
2828
utf8_dict[key] = value
2829
return bencode.bencode(utf8_dict)
2831
def _set_config_option_dict(self, value, name, section):
2833
path = self._branch._remote_path()
2834
serialised_dict = self._serialize_option_dict(value)
2835
response = self._branch._client.call(
2836
'Branch.set_config_option_dict',
2837
path, self._branch._lock_token, self._branch._repo_lock_token,
2838
serialised_dict, name, section or '')
2839
except errors.UnknownSmartMethod:
2840
medium = self._branch._client._medium
2841
medium._remember_remote_is_before((2, 2))
2842
return self._vfs_set_option(value, name, section)
2844
raise errors.UnexpectedSmartServerResponse(response)
2846
2548
def _real_object(self):
2847
2549
self._branch._ensure_real()
2848
2550
return self._branch._real_branch
2931
2633
'Missing key %r in context %r', key_err.args[0], context)
2934
if err.error_verb == 'IncompatibleRepositories':
2935
raise errors.IncompatibleRepositories(err.error_args[0],
2936
err.error_args[1], err.error_args[2])
2937
elif err.error_verb == 'NoSuchRevision':
2636
if err.error_verb == 'NoSuchRevision':
2938
2637
raise NoSuchRevision(find('branch'), err.error_args[0])
2939
2638
elif err.error_verb == 'nosuchrevision':
2940
2639
raise NoSuchRevision(find('repository'), err.error_args[0])
2941
elif err.error_verb == 'nobranch':
2942
if len(err.error_args) >= 1:
2943
extra = err.error_args[0]
2946
raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2640
elif err.error_tuple == ('nobranch',):
2641
raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2948
2642
elif err.error_verb == 'norepository':
2949
2643
raise errors.NoRepositoryPresent(find('bzrdir'))
2950
2644
elif err.error_verb == 'LockContention':