/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: John Arbash Meinel
  • Date: 2010-01-06 17:46:15 UTC
  • mto: (4634.119.1 2.0)
  • mto: This revision was merged to the branch mainline in revision 4951.
  • Revision ID: john@arbash-meinel.com-20100106174615-cq1nckxhbuyemgjx
Fix bug #503886, errors setting up logging go to stderr.

The basic issue is that we were using logging to describe failures
to set up logging. However, those fail with bad error messages
rather than giving us the output we want. This was especially bad
when the failure was occuring on the server. Since 'ssh' will pass
back the stderr stream without bzr handling it at all.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
27
27
    lock,
28
28
    lockdir,
29
29
    repository,
30
 
    repository as _mod_repository,
31
30
    revision,
32
31
    revision as _mod_revision,
33
 
    static_tuple,
34
32
    symbol_versioning,
35
33
)
36
34
from bzrlib.branch import BranchReferenceFormat
37
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
 
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
 
36
from bzrlib.decorators import needs_read_lock, needs_write_lock
39
37
from bzrlib.errors import (
40
38
    NoSuchRevision,
41
39
    SmartProtocolError,
91
89
class RemoteBzrDir(BzrDir, _RpcHelper):
92
90
    """Control directory on a remote server, accessed via bzr:// or similar."""
93
91
 
94
 
    def __init__(self, transport, format, _client=None, _force_probe=False):
 
92
    def __init__(self, transport, format, _client=None):
95
93
        """Construct a RemoteBzrDir.
96
94
 
97
95
        :param _client: Private parameter for testing. Disables probing and the
101
99
        # this object holds a delegated bzrdir that uses file-level operations
102
100
        # to talk to the other side
103
101
        self._real_bzrdir = None
104
 
        self._has_working_tree = None
105
102
        # 1-shot cache for the call pattern 'create_branch; open_branch' - see
106
103
        # create_branch for details.
107
104
        self._next_open_branch_result = None
111
108
            self._client = client._SmartClient(medium)
112
109
        else:
113
110
            self._client = _client
114
 
            if not _force_probe:
115
 
                return
116
 
 
117
 
        self._probe_bzrdir()
118
 
 
119
 
    def __repr__(self):
120
 
        return '%s(%r)' % (self.__class__.__name__, self._client)
121
 
 
122
 
    def _probe_bzrdir(self):
123
 
        medium = self._client._medium
 
111
            return
 
112
 
124
113
        path = self._path_for_remote_call(self._client)
125
 
        if medium._is_remote_before((2, 1)):
126
 
            self._rpc_open(path)
127
 
            return
128
 
        try:
129
 
            self._rpc_open_2_1(path)
130
 
            return
131
 
        except errors.UnknownSmartMethod:
132
 
            medium._remember_remote_is_before((2, 1))
133
 
            self._rpc_open(path)
134
 
 
135
 
    def _rpc_open_2_1(self, path):
136
 
        response = self._call('BzrDir.open_2.1', path)
137
 
        if response == ('no',):
138
 
            raise errors.NotBranchError(path=self.root_transport.base)
139
 
        elif response[0] == 'yes':
140
 
            if response[1] == 'yes':
141
 
                self._has_working_tree = True
142
 
            elif response[1] == 'no':
143
 
                self._has_working_tree = False
144
 
            else:
145
 
                raise errors.UnexpectedSmartServerResponse(response)
146
 
        else:
147
 
            raise errors.UnexpectedSmartServerResponse(response)
148
 
 
149
 
    def _rpc_open(self, path):
150
114
        response = self._call('BzrDir.open', path)
151
115
        if response not in [('yes',), ('no',)]:
152
116
            raise errors.UnexpectedSmartServerResponse(response)
153
117
        if response == ('no',):
154
 
            raise errors.NotBranchError(path=self.root_transport.base)
 
118
            raise errors.NotBranchError(path=transport.base)
155
119
 
156
120
    def _ensure_real(self):
157
121
        """Ensure that there is a _real_bzrdir set.
159
123
        Used before calls to self._real_bzrdir.
160
124
        """
161
125
        if not self._real_bzrdir:
162
 
            if 'hpssvfs' in debug.debug_flags:
163
 
                import traceback
164
 
                warning('VFS BzrDir access triggered\n%s',
165
 
                    ''.join(traceback.format_stack()))
166
126
            self._real_bzrdir = BzrDir.open_from_transport(
167
127
                self.root_transport, _server_formats=False)
168
128
            self._format._network_name = \
244
204
        self._ensure_real()
245
205
        self._real_bzrdir.destroy_repository()
246
206
 
247
 
    def create_branch(self, name=None):
 
207
    def create_branch(self):
248
208
        # as per meta1 formats - just delegate to the format object which may
249
209
        # be parameterised.
250
 
        real_branch = self._format.get_branch_format().initialize(self,
251
 
            name=name)
 
210
        real_branch = self._format.get_branch_format().initialize(self)
252
211
        if not isinstance(real_branch, RemoteBranch):
253
 
            result = RemoteBranch(self, self.find_repository(), real_branch,
254
 
                                  name=name)
 
212
            result = RemoteBranch(self, self.find_repository(), real_branch)
255
213
        else:
256
214
            result = real_branch
257
215
        # BzrDir.clone_on_transport() uses the result of create_branch but does
263
221
        self._next_open_branch_result = result
264
222
        return result
265
223
 
266
 
    def destroy_branch(self, name=None):
 
224
    def destroy_branch(self):
267
225
        """See BzrDir.destroy_branch"""
268
226
        self._ensure_real()
269
 
        self._real_bzrdir.destroy_branch(name=name)
 
227
        self._real_bzrdir.destroy_branch()
270
228
        self._next_open_branch_result = None
271
229
 
272
230
    def create_workingtree(self, revision_id=None, from_branch=None):
291
249
    def _get_branch_reference(self):
292
250
        path = self._path_for_remote_call(self._client)
293
251
        medium = self._client._medium
294
 
        candidate_calls = [
295
 
            ('BzrDir.open_branchV3', (2, 1)),
296
 
            ('BzrDir.open_branchV2', (1, 13)),
297
 
            ('BzrDir.open_branch', None),
298
 
            ]
299
 
        for verb, required_version in candidate_calls:
300
 
            if required_version and medium._is_remote_before(required_version):
301
 
                continue
 
252
        if not medium._is_remote_before((1, 13)):
302
253
            try:
303
 
                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)
 
257
                return response
304
258
            except errors.UnknownSmartMethod:
305
 
                if required_version is None:
306
 
                    raise
307
 
                medium._remember_remote_is_before(required_version)
308
 
            else:
309
 
                break
310
 
        if verb == 'BzrDir.open_branch':
311
 
            if response[0] != 'ok':
312
 
                raise errors.UnexpectedSmartServerResponse(response)
313
 
            if response[1] != '':
314
 
                return ('ref', response[1])
315
 
            else:
316
 
                return ('branch', '')
317
 
        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':
318
262
            raise errors.UnexpectedSmartServerResponse(response)
319
 
        return response
 
263
        if response[1] != '':
 
264
            return ('ref', response[1])
 
265
        else:
 
266
            return ('branch', '')
320
267
 
321
268
    def _get_tree_branch(self):
322
269
        """See BzrDir._get_tree_branch()."""
323
270
        return None, self.open_branch()
324
271
 
325
 
    def open_branch(self, name=None, unsupported=False,
326
 
                    ignore_fallbacks=False):
327
 
        if unsupported:
 
272
    def open_branch(self, _unsupported=False, ignore_fallbacks=False):
 
273
        if _unsupported:
328
274
            raise NotImplementedError('unsupported flag support not implemented yet.')
329
275
        if self._next_open_branch_result is not None:
330
276
            # See create_branch for details.
335
281
        if response[0] == 'ref':
336
282
            # a branch reference, use the existing BranchReference logic.
337
283
            format = BranchReferenceFormat()
338
 
            return format.open(self, name=name, _found=True,
339
 
                location=response[1], ignore_fallbacks=ignore_fallbacks)
 
284
            return format.open(self, _found=True, location=response[1],
 
285
                ignore_fallbacks=ignore_fallbacks)
340
286
        branch_format_name = response[1]
341
287
        if not branch_format_name:
342
288
            branch_format_name = None
343
289
        format = RemoteBranchFormat(network_name=branch_format_name)
344
290
        return RemoteBranch(self, self.find_repository(), format=format,
345
 
            setup_stacking=not ignore_fallbacks, name=name)
 
291
            setup_stacking=not ignore_fallbacks)
346
292
 
347
293
    def _open_repo_v1(self, path):
348
294
        verb = 'BzrDir.find_repository'
409
355
        else:
410
356
            raise errors.NoRepositoryPresent(self)
411
357
 
412
 
    def has_workingtree(self):
413
 
        if self._has_working_tree is None:
414
 
            self._ensure_real()
415
 
            self._has_working_tree = self._real_bzrdir.has_workingtree()
416
 
        return self._has_working_tree
417
 
 
418
358
    def open_workingtree(self, recommend_upgrade=True):
419
 
        if self.has_workingtree():
 
359
        self._ensure_real()
 
360
        if self._real_bzrdir.has_workingtree():
420
361
            raise errors.NotLocalUrl(self.root_transport)
421
362
        else:
422
363
            raise errors.NoWorkingTree(self.root_transport.base)
425
366
        """Return the path to be used for this bzrdir in a remote call."""
426
367
        return client.remote_path_from_transport(self.root_transport)
427
368
 
428
 
    def get_branch_transport(self, branch_format, name=None):
 
369
    def get_branch_transport(self, branch_format):
429
370
        self._ensure_real()
430
 
        return self._real_bzrdir.get_branch_transport(branch_format, name=name)
 
371
        return self._real_bzrdir.get_branch_transport(branch_format)
431
372
 
432
373
    def get_repository_transport(self, repository_format):
433
374
        self._ensure_real()
620
561
        return self._custom_format._fetch_reconcile
621
562
 
622
563
    def get_format_description(self):
623
 
        self._ensure_real()
624
 
        return 'Remote: ' + self._custom_format.get_format_description()
 
564
        return 'bzr remote repository'
625
565
 
626
566
    def __eq__(self, other):
627
567
        return self.__class__ is other.__class__
643
583
        return self._custom_format._serializer
644
584
 
645
585
 
646
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
647
 
    bzrdir.ControlComponent):
 
586
class RemoteRepository(_RpcHelper):
648
587
    """Repository accessed over rpc.
649
588
 
650
589
    For the moment most operations are performed using local transport-backed
693
632
        # Additional places to query for data.
694
633
        self._fallback_repositories = []
695
634
 
696
 
    @property
697
 
    def user_transport(self):
698
 
        return self.bzrdir.user_transport
699
 
 
700
 
    @property
701
 
    def control_transport(self):
702
 
        # XXX: Normally you shouldn't directly get at the remote repository
703
 
        # transport, but I'm not sure it's worth making this method
704
 
        # optional -- mbp 2010-04-21
705
 
        return self.bzrdir.get_repository_transport(None)
706
 
        
707
635
    def __str__(self):
708
636
        return "%s(%s)" % (self.__class__.__name__, self.base)
709
637
 
917
845
        parents_provider = self._make_parents_provider(other_repository)
918
846
        return graph.Graph(parents_provider)
919
847
 
920
 
    @needs_read_lock
921
 
    def get_known_graph_ancestry(self, revision_ids):
922
 
        """Return the known graph for a set of revision ids and their ancestors.
923
 
        """
924
 
        st = static_tuple.StaticTuple
925
 
        revision_keys = [st(r_id).intern() for r_id in revision_ids]
926
 
        known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
927
 
        return graph.GraphThunkIdsToKeys(known_graph)
928
 
 
929
848
    def gather_stats(self, revid=None, committers=None):
930
849
        """See Repository.gather_stats()."""
931
850
        path = self.bzrdir._path_for_remote_call(self._client)
991
910
    def is_write_locked(self):
992
911
        return self._lock_mode == 'w'
993
912
 
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.
997
 
        pass
998
 
 
999
913
    def lock_read(self):
1000
914
        # wrong eventually - want a local lock cache context
1001
915
        if not self._lock_mode:
1002
 
            self._note_lock('r')
1003
916
            self._lock_mode = 'r'
1004
917
            self._lock_count = 1
1005
918
            self._unstacked_provider.enable_cache(cache_misses=True)
1025
938
 
1026
939
    def lock_write(self, token=None, _skip_rpc=False):
1027
940
        if not self._lock_mode:
1028
 
            self._note_lock('w')
1029
941
            if _skip_rpc:
1030
942
                if self._lock_token is not None:
1031
943
                    if token != self._lock_token:
1134
1046
        else:
1135
1047
            raise errors.UnexpectedSmartServerResponse(response)
1136
1048
 
1137
 
    @only_raises(errors.LockNotHeld, errors.LockBroken)
1138
1049
    def unlock(self):
1139
1050
        if not self._lock_count:
1140
1051
            return lock.cant_unlock_not_held(self)
1240
1151
            # state, so always add a lock here. If a caller passes us a locked
1241
1152
            # repository, they are responsible for unlocking it later.
1242
1153
            repository.lock_read()
1243
 
        self._check_fallback_repository(repository)
1244
1154
        self._fallback_repositories.append(repository)
1245
1155
        # If self._real_repository was parameterised already (e.g. because a
1246
1156
        # _real_branch had its get_stacked_on_url method called), then the
1247
1157
        # repository to be added may already be in the _real_repositories list.
1248
1158
        if self._real_repository is not None:
1249
 
            fallback_locations = [repo.user_url for repo in
 
1159
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
1250
1160
                self._real_repository._fallback_repositories]
1251
 
            if repository.user_url not in fallback_locations:
 
1161
            if repository.bzrdir.root_transport.base not in fallback_locations:
1252
1162
                self._real_repository.add_fallback_repository(repository)
1253
1163
 
1254
 
    def _check_fallback_repository(self, repository):
1255
 
        """Check that this repository can fallback to repository safely.
1256
 
 
1257
 
        Raise an error if not.
1258
 
 
1259
 
        :param repository: A repository to fallback to.
1260
 
        """
1261
 
        return _mod_repository.InterRepository._assert_same_model(
1262
 
            self, repository)
1263
 
 
1264
1164
    def add_inventory(self, revid, inv, parents):
1265
1165
        self._ensure_real()
1266
1166
        return self._real_repository.add_inventory(revid, inv, parents)
1267
1167
 
1268
1168
    def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1269
 
            parents, basis_inv=None, propagate_caches=False):
 
1169
                               parents):
1270
1170
        self._ensure_real()
1271
1171
        return self._real_repository.add_inventory_by_delta(basis_revision_id,
1272
 
            delta, new_revision_id, parents, basis_inv=basis_inv,
1273
 
            propagate_caches=propagate_caches)
 
1172
            delta, new_revision_id, parents)
1274
1173
 
1275
1174
    def add_revision(self, rev_id, rev, inv=None, config=None):
1276
1175
        self._ensure_real()
1535
1434
        return self._real_repository.get_signature_text(revision_id)
1536
1435
 
1537
1436
    @needs_read_lock
1538
 
    def _get_inventory_xml(self, revision_id):
1539
 
        self._ensure_real()
1540
 
        return self._real_repository._get_inventory_xml(revision_id)
 
1437
    def get_inventory_xml(self, revision_id):
 
1438
        self._ensure_real()
 
1439
        return self._real_repository.get_inventory_xml(revision_id)
 
1440
 
 
1441
    def deserialise_inventory(self, revision_id, xml):
 
1442
        self._ensure_real()
 
1443
        return self._real_repository.deserialise_inventory(revision_id, xml)
1541
1444
 
1542
1445
    def reconcile(self, other=None, thorough=False):
1543
1446
        self._ensure_real()
1619
1522
        return self._real_repository.inventories
1620
1523
 
1621
1524
    @needs_write_lock
1622
 
    def pack(self, hint=None, clean_obsolete_packs=False):
 
1525
    def pack(self, hint=None):
1623
1526
        """Compress the data within the repository.
1624
1527
 
1625
1528
        This is not currently implemented within the smart server.
1626
1529
        """
1627
1530
        self._ensure_real()
1628
 
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
 
1531
        return self._real_repository.pack(hint=hint)
1629
1532
 
1630
1533
    @property
1631
1534
    def revisions(self):
2053
1956
                self._network_name)
2054
1957
 
2055
1958
    def get_format_description(self):
2056
 
        self._ensure_real()
2057
 
        return 'Remote: ' + self._custom_format.get_format_description()
 
1959
        return 'Remote BZR Branch'
2058
1960
 
2059
1961
    def network_name(self):
2060
1962
        return self._network_name
2061
1963
 
2062
 
    def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2063
 
        return a_bzrdir.open_branch(name=name, 
2064
 
            ignore_fallbacks=ignore_fallbacks)
 
1964
    def open(self, a_bzrdir, ignore_fallbacks=False):
 
1965
        return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2065
1966
 
2066
 
    def _vfs_initialize(self, a_bzrdir, name):
 
1967
    def _vfs_initialize(self, a_bzrdir):
2067
1968
        # Initialisation when using a local bzrdir object, or a non-vfs init
2068
1969
        # method is not available on the server.
2069
1970
        # self._custom_format is always set - the start of initialize ensures
2070
1971
        # that.
2071
1972
        if isinstance(a_bzrdir, RemoteBzrDir):
2072
1973
            a_bzrdir._ensure_real()
2073
 
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2074
 
                name)
 
1974
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2075
1975
        else:
2076
1976
            # We assume the bzrdir is parameterised; it may not be.
2077
 
            result = self._custom_format.initialize(a_bzrdir, name)
 
1977
            result = self._custom_format.initialize(a_bzrdir)
2078
1978
        if (isinstance(a_bzrdir, RemoteBzrDir) and
2079
1979
            not isinstance(result, RemoteBranch)):
2080
 
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2081
 
                                  name=name)
 
1980
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2082
1981
        return result
2083
1982
 
2084
 
    def initialize(self, a_bzrdir, name=None):
 
1983
    def initialize(self, a_bzrdir):
2085
1984
        # 1) get the network name to use.
2086
1985
        if self._custom_format:
2087
1986
            network_name = self._custom_format.network_name()
2093
1992
            network_name = reference_format.network_name()
2094
1993
        # Being asked to create on a non RemoteBzrDir:
2095
1994
        if not isinstance(a_bzrdir, RemoteBzrDir):
2096
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
1995
            return self._vfs_initialize(a_bzrdir)
2097
1996
        medium = a_bzrdir._client._medium
2098
1997
        if medium._is_remote_before((1, 13)):
2099
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
1998
            return self._vfs_initialize(a_bzrdir)
2100
1999
        # Creating on a remote bzr dir.
2101
2000
        # 2) try direct creation via RPC
2102
2001
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2103
 
        if name is not None:
2104
 
            # XXX JRV20100304: Support creating colocated branches
2105
 
            raise errors.NoColocatedBranchSupport(self)
2106
2002
        verb = 'BzrDir.create_branch'
2107
2003
        try:
2108
2004
            response = a_bzrdir._call(verb, path, network_name)
2109
2005
        except errors.UnknownSmartMethod:
2110
2006
            # Fallback - use vfs methods
2111
2007
            medium._remember_remote_is_before((1, 13))
2112
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2008
            return self._vfs_initialize(a_bzrdir)
2113
2009
        if response[0] != 'ok':
2114
2010
            raise errors.UnexpectedSmartServerResponse(response)
2115
2011
        # Turn the response into a RemoteRepository object.
2123
2019
                a_bzrdir._client)
2124
2020
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2125
2021
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2126
 
            format=format, setup_stacking=False, name=name)
 
2022
            format=format, setup_stacking=False)
2127
2023
        # XXX: We know this is a new branch, so it must have revno 0, revid
2128
2024
        # NULL_REVISION. Creating the branch locked would make this be unable
2129
2025
        # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2149
2045
        return self._custom_format.supports_set_append_revisions_only()
2150
2046
 
2151
2047
 
2152
 
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
 
2048
class RemoteBranch(branch.Branch, _RpcHelper):
2153
2049
    """Branch stored on a server accessed by HPSS RPC.
2154
2050
 
2155
2051
    At the moment most operations are mapped down to simple file operations.
2156
2052
    """
2157
2053
 
2158
2054
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2159
 
        _client=None, format=None, setup_stacking=True, name=None):
 
2055
        _client=None, format=None, setup_stacking=True):
2160
2056
        """Create a RemoteBranch instance.
2161
2057
 
2162
2058
        :param real_branch: An optional local implementation of the branch
2168
2064
        :param setup_stacking: If True make an RPC call to determine the
2169
2065
            stacked (or not) status of the branch. If False assume the branch
2170
2066
            is not stacked.
2171
 
        :param name: Colocated branch name
2172
2067
        """
2173
2068
        # We intentionally don't call the parent class's __init__, because it
2174
2069
        # will try to assign to self.tags, which is a property in this subclass.
2193
2088
            self._real_branch = None
2194
2089
        # Fill out expected attributes of branch for bzrlib API users.
2195
2090
        self._clear_cached_state()
2196
 
        # TODO: deprecate self.base in favor of user_url
2197
 
        self.base = self.bzrdir.user_url
2198
 
        self._name = name
 
2091
        self.base = self.bzrdir.root_transport.base
2199
2092
        self._control_files = None
2200
2093
        self._lock_mode = None
2201
2094
        self._lock_token = None
2266
2159
                    'to use vfs implementation')
2267
2160
            self.bzrdir._ensure_real()
2268
2161
            self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2269
 
                ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
 
2162
                ignore_fallbacks=self._real_ignore_fallbacks)
2270
2163
            if self.repository._real_repository is None:
2271
2164
                # Give the remote repository the matching real repo.
2272
2165
                real_repo = self._real_branch.repository
2389
2282
    def lock_read(self):
2390
2283
        self.repository.lock_read()
2391
2284
        if not self._lock_mode:
2392
 
            self._note_lock('r')
2393
2285
            self._lock_mode = 'r'
2394
2286
            self._lock_count = 1
2395
2287
            if self._real_branch is not None:
2415
2307
 
2416
2308
    def lock_write(self, token=None):
2417
2309
        if not self._lock_mode:
2418
 
            self._note_lock('w')
2419
2310
            # Lock the branch and repo in one remote call.
2420
2311
            remote_tokens = self._remote_lock_write(token)
2421
2312
            self._lock_token, self._repo_lock_token = remote_tokens
2456
2347
            return
2457
2348
        raise errors.UnexpectedSmartServerResponse(response)
2458
2349
 
2459
 
    @only_raises(errors.LockNotHeld, errors.LockBroken)
2460
2350
    def unlock(self):
2461
2351
        try:
2462
2352
            self._lock_count -= 1
2880
2770
        raise NoSuchRevision(find('branch'), err.error_args[0])
2881
2771
    elif err.error_verb == 'nosuchrevision':
2882
2772
        raise NoSuchRevision(find('repository'), err.error_args[0])
2883
 
    elif err.error_verb == 'nobranch':
2884
 
        if len(err.error_args) >= 1:
2885
 
            extra = err.error_args[0]
2886
 
        else:
2887
 
            extra = None
2888
 
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2889
 
            detail=extra)
 
2773
    elif err.error_tuple == ('nobranch',):
 
2774
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2890
2775
    elif err.error_verb == 'norepository':
2891
2776
        raise errors.NoRepositoryPresent(find('bzrdir'))
2892
2777
    elif err.error_verb == 'LockContention':