31
repository as _mod_repository,
33
31
revision as _mod_revision,
37
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
34
from bzrlib.branch import BranchReferenceFormat
38
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
39
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
36
from bzrlib.decorators import needs_read_lock, needs_write_lock
40
37
from bzrlib.errors import (
42
39
SmartProtocolError,
93
89
class RemoteBzrDir(BzrDir, _RpcHelper):
94
90
"""Control directory on a remote server, accessed via bzr:// or similar."""
96
def __init__(self, transport, format, _client=None, _force_probe=False):
92
def __init__(self, transport, format, _client=None):
97
93
"""Construct a RemoteBzrDir.
99
95
:param _client: Private parameter for testing. Disables probing and the
113
108
self._client = client._SmartClient(medium)
115
110
self._client = _client
122
return '%s(%r)' % (self.__class__.__name__, self._client)
124
def _probe_bzrdir(self):
125
medium = self._client._medium
126
113
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
114
response = self._call('BzrDir.open', path)
153
115
if response not in [('yes',), ('no',)]:
154
116
raise errors.UnexpectedSmartServerResponse(response)
155
117
if response == ('no',):
156
raise errors.NotBranchError(path=self.root_transport.base)
118
raise errors.NotBranchError(path=transport.base)
158
120
def _ensure_real(self):
159
121
"""Ensure that there is a _real_bzrdir set.
161
123
Used before calls to self._real_bzrdir.
163
125
if not self._real_bzrdir:
164
if 'hpssvfs' in debug.debug_flags:
166
warning('VFS BzrDir access triggered\n%s',
167
''.join(traceback.format_stack()))
168
126
self._real_bzrdir = BzrDir.open_from_transport(
169
127
self.root_transport, _server_formats=False)
170
128
self._format._network_name = \
246
204
self._ensure_real()
247
205
self._real_bzrdir.destroy_repository()
249
def create_branch(self, name=None):
207
def create_branch(self):
250
208
# as per meta1 formats - just delegate to the format object which may
251
209
# be parameterised.
252
real_branch = self._format.get_branch_format().initialize(self,
210
real_branch = self._format.get_branch_format().initialize(self)
254
211
if not isinstance(real_branch, RemoteBranch):
255
result = RemoteBranch(self, self.find_repository(), real_branch,
212
result = RemoteBranch(self, self.find_repository(), real_branch)
258
214
result = real_branch
259
215
# BzrDir.clone_on_transport() uses the result of create_branch but does
265
221
self._next_open_branch_result = result
268
def destroy_branch(self, name=None):
224
def destroy_branch(self):
269
225
"""See BzrDir.destroy_branch"""
270
226
self._ensure_real()
271
self._real_bzrdir.destroy_branch(name=name)
227
self._real_bzrdir.destroy_branch()
272
228
self._next_open_branch_result = None
274
230
def create_workingtree(self, revision_id=None, from_branch=None):
275
231
raise errors.NotLocalUrl(self.transport.base)
277
def find_branch_format(self, name=None):
233
def find_branch_format(self):
278
234
"""Find the branch 'format' for this bzrdir.
280
236
This might be a synthetic object for e.g. RemoteBranch and SVN.
282
b = self.open_branch(name=name)
238
b = self.open_branch()
285
def get_branch_reference(self, name=None):
241
def get_branch_reference(self):
286
242
"""See BzrDir.get_branch_reference()."""
288
# XXX JRV20100304: Support opening colocated branches
289
raise errors.NoColocatedBranchSupport(self)
290
243
response = self._get_branch_reference()
291
244
if response[0] == 'ref':
292
245
return response[1]
296
249
def _get_branch_reference(self):
297
250
path = self._path_for_remote_call(self._client)
298
251
medium = self._client._medium
300
('BzrDir.open_branchV3', (2, 1)),
301
('BzrDir.open_branchV2', (1, 13)),
302
('BzrDir.open_branch', None),
304
for verb, required_version in candidate_calls:
305
if required_version and medium._is_remote_before(required_version):
252
if not medium._is_remote_before((1, 13)):
308
response = self._call(verb, path)
254
response = self._call('BzrDir.open_branchV2', path)
255
if response[0] not in ('ref', 'branch'):
256
raise errors.UnexpectedSmartServerResponse(response)
309
258
except errors.UnknownSmartMethod:
310
if required_version is None:
312
medium._remember_remote_is_before(required_version)
315
if verb == 'BzrDir.open_branch':
316
if response[0] != 'ok':
317
raise errors.UnexpectedSmartServerResponse(response)
318
if response[1] != '':
319
return ('ref', response[1])
321
return ('branch', '')
322
if response[0] not in ('ref', 'branch'):
259
medium._remember_remote_is_before((1, 13))
260
response = self._call('BzrDir.open_branch', path)
261
if response[0] != 'ok':
323
262
raise errors.UnexpectedSmartServerResponse(response)
263
if response[1] != '':
264
return ('ref', response[1])
266
return ('branch', '')
326
def _get_tree_branch(self, name=None):
268
def _get_tree_branch(self):
327
269
"""See BzrDir._get_tree_branch()."""
328
return None, self.open_branch(name=name)
270
return None, self.open_branch()
330
def open_branch(self, name=None, unsupported=False,
331
ignore_fallbacks=False):
272
def open_branch(self, _unsupported=False, ignore_fallbacks=False):
333
274
raise NotImplementedError('unsupported flag support not implemented yet.')
334
275
if self._next_open_branch_result is not None:
335
276
# See create_branch for details.
340
281
if response[0] == 'ref':
341
282
# a branch reference, use the existing BranchReference logic.
342
283
format = BranchReferenceFormat()
343
return format.open(self, name=name, _found=True,
344
location=response[1], ignore_fallbacks=ignore_fallbacks)
284
return format.open(self, _found=True, location=response[1],
285
ignore_fallbacks=ignore_fallbacks)
345
286
branch_format_name = response[1]
346
287
if not branch_format_name:
347
288
branch_format_name = None
348
289
format = RemoteBranchFormat(network_name=branch_format_name)
349
290
return RemoteBranch(self, self.find_repository(), format=format,
350
setup_stacking=not ignore_fallbacks, name=name)
291
setup_stacking=not ignore_fallbacks)
352
293
def _open_repo_v1(self, path):
353
294
verb = 'BzrDir.find_repository'
415
356
raise errors.NoRepositoryPresent(self)
417
def has_workingtree(self):
418
if self._has_working_tree is None:
420
self._has_working_tree = self._real_bzrdir.has_workingtree()
421
return self._has_working_tree
423
358
def open_workingtree(self, recommend_upgrade=True):
424
if self.has_workingtree():
360
if self._real_bzrdir.has_workingtree():
425
361
raise errors.NotLocalUrl(self.root_transport)
427
363
raise errors.NoWorkingTree(self.root_transport.base)
430
366
"""Return the path to be used for this bzrdir in a remote call."""
431
367
return client.remote_path_from_transport(self.root_transport)
433
def get_branch_transport(self, branch_format, name=None):
369
def get_branch_transport(self, branch_format):
434
370
self._ensure_real()
435
return self._real_bzrdir.get_branch_transport(branch_format, name=name)
371
return self._real_bzrdir.get_branch_transport(branch_format)
437
373
def get_repository_transport(self, repository_format):
438
374
self._ensure_real()
698
632
# Additional places to query for data.
699
633
self._fallback_repositories = []
702
def user_transport(self):
703
return self.bzrdir.user_transport
706
def control_transport(self):
707
# XXX: Normally you shouldn't directly get at the remote repository
708
# transport, but I'm not sure it's worth making this method
709
# optional -- mbp 2010-04-21
710
return self.bzrdir.get_repository_transport(None)
712
635
def __str__(self):
713
636
return "%s(%s)" % (self.__class__.__name__, self.base)
900
823
def _has_same_fallbacks(self, other_repo):
901
824
"""Returns true if the repositories have the same fallbacks."""
902
825
# XXX: copied from Repository; it should be unified into a base class
903
# <https://bugs.launchpad.net/bzr/+bug/401622>
826
# <https://bugs.edge.launchpad.net/bzr/+bug/401622>
904
827
my_fb = self._fallback_repositories
905
828
other_fb = other_repo._fallback_repositories
906
829
if len(my_fb) != len(other_fb):
922
845
parents_provider = self._make_parents_provider(other_repository)
923
846
return graph.Graph(parents_provider)
926
def get_known_graph_ancestry(self, revision_ids):
927
"""Return the known graph for a set of revision ids and their ancestors.
929
st = static_tuple.StaticTuple
930
revision_keys = [st(r_id).intern() for r_id in revision_ids]
931
known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
932
return graph.GraphThunkIdsToKeys(known_graph)
934
848
def gather_stats(self, revid=None, committers=None):
935
849
"""See Repository.gather_stats()."""
936
850
path = self.bzrdir._path_for_remote_call(self._client)
996
910
def is_write_locked(self):
997
911
return self._lock_mode == 'w'
999
def _warn_if_deprecated(self, branch=None):
1000
# If we have a real repository, the check will be done there, if we
1001
# don't the check will be done remotely.
1004
913
def lock_read(self):
1005
"""Lock the repository for read operations.
1007
:return: A bzrlib.lock.LogicalLockResult.
1009
914
# wrong eventually - want a local lock cache context
1010
915
if not self._lock_mode:
1011
self._note_lock('r')
1012
916
self._lock_mode = 'r'
1013
917
self._lock_count = 1
1014
918
self._unstacked_provider.enable_cache(cache_misses=True)
1250
1151
# state, so always add a lock here. If a caller passes us a locked
1251
1152
# repository, they are responsible for unlocking it later.
1252
1153
repository.lock_read()
1253
self._check_fallback_repository(repository)
1254
1154
self._fallback_repositories.append(repository)
1255
1155
# If self._real_repository was parameterised already (e.g. because a
1256
1156
# _real_branch had its get_stacked_on_url method called), then the
1257
1157
# repository to be added may already be in the _real_repositories list.
1258
1158
if self._real_repository is not None:
1259
fallback_locations = [repo.user_url for repo in
1159
fallback_locations = [repo.bzrdir.root_transport.base for repo in
1260
1160
self._real_repository._fallback_repositories]
1261
if repository.user_url not in fallback_locations:
1161
if repository.bzrdir.root_transport.base not in fallback_locations:
1262
1162
self._real_repository.add_fallback_repository(repository)
1264
def _check_fallback_repository(self, repository):
1265
"""Check that this repository can fallback to repository safely.
1267
Raise an error if not.
1269
:param repository: A repository to fallback to.
1271
return _mod_repository.InterRepository._assert_same_model(
1274
1164
def add_inventory(self, revid, inv, parents):
1275
1165
self._ensure_real()
1276
1166
return self._real_repository.add_inventory(revid, inv, parents)
1278
1168
def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1279
parents, basis_inv=None, propagate_caches=False):
1280
1170
self._ensure_real()
1281
1171
return self._real_repository.add_inventory_by_delta(basis_revision_id,
1282
delta, new_revision_id, parents, basis_inv=basis_inv,
1283
propagate_caches=propagate_caches)
1172
delta, new_revision_id, parents)
1285
1174
def add_revision(self, rev_id, rev, inv=None, config=None):
1286
1175
self._ensure_real()
1316
1205
return self._real_repository.make_working_trees()
1318
1207
def refresh_data(self):
1319
"""Re-read any data needed to synchronise with disk.
1208
"""Re-read any data needed to to synchronise with disk.
1321
1210
This method is intended to be called after another repository instance
1322
1211
(such as one used by a smart server) has inserted data into the
1323
repository. On all repositories this will work outside of write groups.
1324
Some repository formats (pack and newer for bzrlib native formats)
1325
support refresh_data inside write groups. If called inside a write
1326
group on a repository that does not support refreshing in a write group
1327
IsInWriteGroupError will be raised.
1212
repository. It may not be called during a write group, but may be
1213
called at any other time.
1215
if self.is_in_write_group():
1216
raise errors.InternalBzrError(
1217
"May not refresh_data while in a write group.")
1329
1218
if self._real_repository is not None:
1330
1219
self._real_repository.refresh_data()
1545
1434
return self._real_repository.get_signature_text(revision_id)
1547
1436
@needs_read_lock
1548
def _get_inventory_xml(self, revision_id):
1550
return self._real_repository._get_inventory_xml(revision_id)
1437
def get_inventory_xml(self, revision_id):
1439
return self._real_repository.get_inventory_xml(revision_id)
1441
def deserialise_inventory(self, revision_id, xml):
1443
return self._real_repository.deserialise_inventory(revision_id, xml)
1552
1445
def reconcile(self, other=None, thorough=False):
1553
1446
self._ensure_real()
1629
1522
return self._real_repository.inventories
1631
1524
@needs_write_lock
1632
def pack(self, hint=None, clean_obsolete_packs=False):
1525
def pack(self, hint=None):
1633
1526
"""Compress the data within the repository.
1635
1528
This is not currently implemented within the smart server.
1637
1530
self._ensure_real()
1638
return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
1531
return self._real_repository.pack(hint=hint)
1641
1534
def revisions(self):
1846
1739
# The stream included an inventory-delta record, but the remote
1847
1740
# side isn't new enough to support them. So we need to send the
1848
1741
# rest of the stream via VFS.
1849
self.target_repo.refresh_data()
1850
1742
return self._resume_stream_with_vfs(response, src_format)
1851
1743
if response[0][0] == 'missing-basis':
1852
1744
tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1981
1873
if response_tuple[0] != 'ok':
1982
1874
raise errors.UnexpectedSmartServerResponse(response_tuple)
1983
1875
byte_stream = response_handler.read_streamed_body()
1984
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1985
self._record_counter)
1876
src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1986
1877
if src_format.network_name() != repo._format.network_name():
1987
1878
raise AssertionError(
1988
1879
"Mismatched RemoteRepository and stream src %r, %r" % (
2018
1909
def missing_parents_rev_handler(self, substream):
2019
1910
for content in substream:
2020
1911
revision_bytes = content.get_bytes_as('fulltext')
2021
revision = self.from_serialiser.read_revision_from_string(
1912
revision = self.serialiser.read_revision_from_string(revision_bytes)
2023
1913
self.seen_revs.add(content.key[-1])
2024
1914
self.referenced_revs.update(revision.parent_ids)
2064
1954
self._network_name)
2066
1956
def get_format_description(self):
2068
return 'Remote: ' + self._custom_format.get_format_description()
1957
return 'Remote BZR Branch'
2070
1959
def network_name(self):
2071
1960
return self._network_name
2073
def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2074
return a_bzrdir.open_branch(name=name,
2075
ignore_fallbacks=ignore_fallbacks)
1962
def open(self, a_bzrdir, ignore_fallbacks=False):
1963
return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2077
def _vfs_initialize(self, a_bzrdir, name):
1965
def _vfs_initialize(self, a_bzrdir):
2078
1966
# Initialisation when using a local bzrdir object, or a non-vfs init
2079
1967
# method is not available on the server.
2080
1968
# self._custom_format is always set - the start of initialize ensures
2082
1970
if isinstance(a_bzrdir, RemoteBzrDir):
2083
1971
a_bzrdir._ensure_real()
2084
result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
1972
result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2087
1974
# We assume the bzrdir is parameterised; it may not be.
2088
result = self._custom_format.initialize(a_bzrdir, name)
1975
result = self._custom_format.initialize(a_bzrdir)
2089
1976
if (isinstance(a_bzrdir, RemoteBzrDir) and
2090
1977
not isinstance(result, RemoteBranch)):
2091
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
1978
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2095
def initialize(self, a_bzrdir, name=None):
1981
def initialize(self, a_bzrdir):
2096
1982
# 1) get the network name to use.
2097
1983
if self._custom_format:
2098
1984
network_name = self._custom_format.network_name()
2104
1990
network_name = reference_format.network_name()
2105
1991
# Being asked to create on a non RemoteBzrDir:
2106
1992
if not isinstance(a_bzrdir, RemoteBzrDir):
2107
return self._vfs_initialize(a_bzrdir, name=name)
1993
return self._vfs_initialize(a_bzrdir)
2108
1994
medium = a_bzrdir._client._medium
2109
1995
if medium._is_remote_before((1, 13)):
2110
return self._vfs_initialize(a_bzrdir, name=name)
1996
return self._vfs_initialize(a_bzrdir)
2111
1997
# Creating on a remote bzr dir.
2112
1998
# 2) try direct creation via RPC
2113
1999
path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2114
if name is not None:
2115
# XXX JRV20100304: Support creating colocated branches
2116
raise errors.NoColocatedBranchSupport(self)
2117
2000
verb = 'BzrDir.create_branch'
2119
2002
response = a_bzrdir._call(verb, path, network_name)
2120
2003
except errors.UnknownSmartMethod:
2121
2004
# Fallback - use vfs methods
2122
2005
medium._remember_remote_is_before((1, 13))
2123
return self._vfs_initialize(a_bzrdir, name=name)
2006
return self._vfs_initialize(a_bzrdir)
2124
2007
if response[0] != 'ok':
2125
2008
raise errors.UnexpectedSmartServerResponse(response)
2126
2009
# Turn the response into a RemoteRepository object.
2134
2017
a_bzrdir._client)
2135
2018
remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2136
2019
remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2137
format=format, setup_stacking=False, name=name)
2020
format=format, setup_stacking=False)
2138
2021
# XXX: We know this is a new branch, so it must have revno 0, revid
2139
2022
# NULL_REVISION. Creating the branch locked would make this be unable
2140
2023
# to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2160
2043
return self._custom_format.supports_set_append_revisions_only()
2163
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2046
class RemoteBranch(branch.Branch, _RpcHelper):
2164
2047
"""Branch stored on a server accessed by HPSS RPC.
2166
2049
At the moment most operations are mapped down to simple file operations.
2169
2052
def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2170
_client=None, format=None, setup_stacking=True, name=None):
2053
_client=None, format=None, setup_stacking=True):
2171
2054
"""Create a RemoteBranch instance.
2173
2056
:param real_branch: An optional local implementation of the branch
2277
2157
'to use vfs implementation')
2278
2158
self.bzrdir._ensure_real()
2279
2159
self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2280
ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
2160
ignore_fallbacks=self._real_ignore_fallbacks)
2281
2161
if self.repository._real_repository is None:
2282
2162
# Give the remote repository the matching real repo.
2283
2163
real_repo = self._real_branch.repository
2398
2277
self._vfs_set_tags_bytes(bytes)
2400
2279
def lock_read(self):
2401
"""Lock the branch for read operations.
2403
:return: A bzrlib.lock.LogicalLockResult.
2405
2280
self.repository.lock_read()
2406
2281
if not self._lock_mode:
2407
self._note_lock('r')
2408
2282
self._lock_mode = 'r'
2409
2283
self._lock_count = 1
2410
2284
if self._real_branch is not None:
2411
2285
self._real_branch.lock_read()
2413
2287
self._lock_count += 1
2414
return lock.LogicalLockResult(self.unlock)
2416
2289
def _remote_lock_write(self, token):
2417
2290
if token is None:
2418
2291
branch_token = repo_token = ''
2420
2293
branch_token = token
2421
repo_token = self.repository.lock_write().repository_token
2294
repo_token = self.repository.lock_write()
2422
2295
self.repository.unlock()
2423
2296
err_context = {'token': token}
2425
response = self._call(
2426
'Branch.lock_write', self._remote_path(), branch_token,
2427
repo_token or '', **err_context)
2428
except errors.LockContention, e:
2429
# The LockContention from the server doesn't have any
2430
# information about the lock_url. We re-raise LockContention
2431
# with valid lock_url.
2432
raise errors.LockContention('(remote lock)',
2433
self.repository.base.split('.bzr/')[0])
2297
response = self._call(
2298
'Branch.lock_write', self._remote_path(), branch_token,
2299
repo_token or '', **err_context)
2434
2300
if response[0] != 'ok':
2435
2301
raise errors.UnexpectedSmartServerResponse(response)
2436
2302
ok, branch_token, repo_token = response
2468
2333
self._lock_count += 1
2469
2334
# Re-lock the repository too.
2470
2335
self.repository.lock_write(self._repo_lock_token)
2471
return BranchWriteLockResult(self.unlock, self._lock_token or None)
2336
return self._lock_token or None
2473
2338
def _unlock(self, branch_token, repo_token):
2474
2339
err_context = {'token': str((branch_token, repo_token))}
2797
2660
medium = self._branch._client._medium
2798
2661
if medium._is_remote_before((1, 14)):
2799
2662
return self._vfs_set_option(value, name, section)
2800
if isinstance(value, dict):
2801
if medium._is_remote_before((2, 2)):
2802
return self._vfs_set_option(value, name, section)
2803
return self._set_config_option_dict(value, name, section)
2805
return self._set_config_option(value, name, section)
2807
def _set_config_option(self, value, name, section):
2809
2664
path = self._branch._remote_path()
2810
2665
response = self._branch._client.call('Branch.set_config_option',
2811
2666
path, self._branch._lock_token, self._branch._repo_lock_token,
2812
2667
value.encode('utf8'), name, section or '')
2813
2668
except errors.UnknownSmartMethod:
2814
medium = self._branch._client._medium
2815
2669
medium._remember_remote_is_before((1, 14))
2816
2670
return self._vfs_set_option(value, name, section)
2817
2671
if response != ():
2818
2672
raise errors.UnexpectedSmartServerResponse(response)
2820
def _serialize_option_dict(self, option_dict):
2822
for key, value in option_dict.items():
2823
if isinstance(key, unicode):
2824
key = key.encode('utf8')
2825
if isinstance(value, unicode):
2826
value = value.encode('utf8')
2827
utf8_dict[key] = value
2828
return bencode.bencode(utf8_dict)
2830
def _set_config_option_dict(self, value, name, section):
2832
path = self._branch._remote_path()
2833
serialised_dict = self._serialize_option_dict(value)
2834
response = self._branch._client.call(
2835
'Branch.set_config_option_dict',
2836
path, self._branch._lock_token, self._branch._repo_lock_token,
2837
serialised_dict, name, section or '')
2838
except errors.UnknownSmartMethod:
2839
medium = self._branch._client._medium
2840
medium._remember_remote_is_before((2, 2))
2841
return self._vfs_set_option(value, name, section)
2843
raise errors.UnexpectedSmartServerResponse(response)
2845
2674
def _real_object(self):
2846
2675
self._branch._ensure_real()
2847
2676
return self._branch._real_branch
2937
2766
raise NoSuchRevision(find('branch'), err.error_args[0])
2938
2767
elif err.error_verb == 'nosuchrevision':
2939
2768
raise NoSuchRevision(find('repository'), err.error_args[0])
2940
elif err.error_verb == 'nobranch':
2941
if len(err.error_args) >= 1:
2942
extra = err.error_args[0]
2945
raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2769
elif err.error_tuple == ('nobranch',):
2770
raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2947
2771
elif err.error_verb == 'norepository':
2948
2772
raise errors.NoRepositoryPresent(find('bzrdir'))
2949
2773
elif err.error_verb == 'LockContention':