/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: Jelmer Vernooij
  • Date: 2011-03-10 13:23:20 UTC
  • mto: (5582.10.90 weave-plugin)
  • mto: This revision was merged to the branch mainline in revision 5717.
  • Revision ID: jelmer@samba.org-20110310132320-k6uclq04lapawivt
Fix imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 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
21
21
    branch,
22
22
    bzrdir,
23
23
    config,
 
24
    controldir,
24
25
    debug,
25
26
    errors,
26
27
    graph,
32
33
    revision as _mod_revision,
33
34
    static_tuple,
34
35
    symbol_versioning,
 
36
    urlutils,
35
37
)
36
 
from bzrlib.branch import BranchReferenceFormat
 
38
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
37
39
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
40
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
39
41
from bzrlib.errors import (
43
45
from bzrlib.lockable_files import LockableFiles
44
46
from bzrlib.smart import client, vfs, repository as smart_repo
45
47
from bzrlib.revision import ensure_null, NULL_REVISION
 
48
from bzrlib.repository import RepositoryWriteLockResult
46
49
from bzrlib.trace import mutter, note, warning
47
50
 
48
51
 
212
215
        if len(branch_info) != 2:
213
216
            raise errors.UnexpectedSmartServerResponse(response)
214
217
        branch_ref, branch_name = branch_info
215
 
        format = bzrdir.network_format_registry.get(control_name)
 
218
        format = controldir.network_format_registry.get(control_name)
216
219
        if repo_name:
217
220
            format.repository_format = repository.network_format_registry.get(
218
221
                repo_name)
244
247
        self._ensure_real()
245
248
        self._real_bzrdir.destroy_repository()
246
249
 
247
 
    def create_branch(self, name=None):
 
250
    def create_branch(self, name=None, repository=None):
248
251
        # as per meta1 formats - just delegate to the format object which may
249
252
        # be parameterised.
250
253
        real_branch = self._format.get_branch_format().initialize(self,
251
 
            name=name)
 
254
            name=name, repository=repository)
252
255
        if not isinstance(real_branch, RemoteBranch):
253
 
            result = RemoteBranch(self, self.find_repository(), real_branch,
254
 
                                  name=name)
 
256
            if not isinstance(repository, RemoteRepository):
 
257
                raise AssertionError(
 
258
                    'need a RemoteRepository to use with RemoteBranch, got %r'
 
259
                    % (repository,))
 
260
            result = RemoteBranch(self, repository, real_branch, name=name)
255
261
        else:
256
262
            result = real_branch
257
263
        # BzrDir.clone_on_transport() uses the result of create_branch but does
269
275
        self._real_bzrdir.destroy_branch(name=name)
270
276
        self._next_open_branch_result = None
271
277
 
272
 
    def create_workingtree(self, revision_id=None, from_branch=None):
 
278
    def create_workingtree(self, revision_id=None, from_branch=None,
 
279
        accelerator_tree=None, hardlink=False):
273
280
        raise errors.NotLocalUrl(self.transport.base)
274
281
 
275
 
    def find_branch_format(self):
 
282
    def find_branch_format(self, name=None):
276
283
        """Find the branch 'format' for this bzrdir.
277
284
 
278
285
        This might be a synthetic object for e.g. RemoteBranch and SVN.
279
286
        """
280
 
        b = self.open_branch()
 
287
        b = self.open_branch(name=name)
281
288
        return b._format
282
289
 
283
 
    def get_branch_reference(self):
 
290
    def get_branch_reference(self, name=None):
284
291
        """See BzrDir.get_branch_reference()."""
 
292
        if name is not None:
 
293
            # XXX JRV20100304: Support opening colocated branches
 
294
            raise errors.NoColocatedBranchSupport(self)
285
295
        response = self._get_branch_reference()
286
296
        if response[0] == 'ref':
287
297
            return response[1]
318
328
            raise errors.UnexpectedSmartServerResponse(response)
319
329
        return response
320
330
 
321
 
    def _get_tree_branch(self):
 
331
    def _get_tree_branch(self, name=None):
322
332
        """See BzrDir._get_tree_branch()."""
323
 
        return None, self.open_branch()
 
333
        return None, self.open_branch(name=name)
324
334
 
325
335
    def open_branch(self, name=None, unsupported=False,
326
336
                    ignore_fallbacks=False):
441
451
        """Upgrading of remote bzrdirs is not supported yet."""
442
452
        return False
443
453
 
444
 
    def needs_format_conversion(self, format=None):
 
454
    def needs_format_conversion(self, format):
445
455
        """Upgrading of remote bzrdirs is not supported yet."""
446
 
        if format is None:
447
 
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
448
 
                % 'needs_format_conversion(format=None)')
449
456
        return False
450
457
 
451
458
    def clone(self, url, revision_id=None, force_new_repo=False,
479
486
    """
480
487
 
481
488
    _matchingbzrdir = RemoteBzrDirFormat()
 
489
    supports_full_versioned_files = True
 
490
    supports_leaving_lock = True
482
491
 
483
492
    def __init__(self):
484
493
        repository.RepositoryFormat.__init__(self)
488
497
        self._supports_chks = None
489
498
        self._supports_external_lookups = None
490
499
        self._supports_tree_reference = None
 
500
        self._supports_funky_characters = None
491
501
        self._rich_root_data = None
492
502
 
493
503
    def __repr__(self):
522
532
        return self._supports_external_lookups
523
533
 
524
534
    @property
 
535
    def supports_funky_characters(self):
 
536
        if self._supports_funky_characters is None:
 
537
            self._ensure_real()
 
538
            self._supports_funky_characters = \
 
539
                self._custom_format.supports_funky_characters
 
540
        return self._supports_funky_characters
 
541
 
 
542
    @property
525
543
    def supports_tree_reference(self):
526
544
        if self._supports_tree_reference is None:
527
545
            self._ensure_real()
644
662
 
645
663
 
646
664
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
647
 
    bzrdir.ControlComponent):
 
665
    controldir.ControlComponent):
648
666
    """Repository accessed over rpc.
649
667
 
650
668
    For the moment most operations are performed using local transport-backed
895
913
    def _has_same_fallbacks(self, other_repo):
896
914
        """Returns true if the repositories have the same fallbacks."""
897
915
        # XXX: copied from Repository; it should be unified into a base class
898
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
 
916
        # <https://bugs.launchpad.net/bzr/+bug/401622>
899
917
        my_fb = self._fallback_repositories
900
918
        other_fb = other_repo._fallback_repositories
901
919
        if len(my_fb) != len(other_fb):
997
1015
        pass
998
1016
 
999
1017
    def lock_read(self):
 
1018
        """Lock the repository for read operations.
 
1019
 
 
1020
        :return: A bzrlib.lock.LogicalLockResult.
 
1021
        """
1000
1022
        # wrong eventually - want a local lock cache context
1001
1023
        if not self._lock_mode:
1002
1024
            self._note_lock('r')
1009
1031
                repo.lock_read()
1010
1032
        else:
1011
1033
            self._lock_count += 1
 
1034
        return lock.LogicalLockResult(self.unlock)
1012
1035
 
1013
1036
    def _remote_lock_write(self, token):
1014
1037
        path = self.bzrdir._path_for_remote_call(self._client)
1054
1077
            raise errors.ReadOnlyError(self)
1055
1078
        else:
1056
1079
            self._lock_count += 1
1057
 
        return self._lock_token or None
 
1080
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
1058
1081
 
1059
1082
    def leave_lock_in_place(self):
1060
1083
        if not self._lock_token:
1306
1329
        return self._real_repository.make_working_trees()
1307
1330
 
1308
1331
    def refresh_data(self):
1309
 
        """Re-read any data needed to to synchronise with disk.
 
1332
        """Re-read any data needed to synchronise with disk.
1310
1333
 
1311
1334
        This method is intended to be called after another repository instance
1312
1335
        (such as one used by a smart server) has inserted data into the
1313
 
        repository. It may not be called during a write group, but may be
1314
 
        called at any other time.
 
1336
        repository. On all repositories this will work outside of write groups.
 
1337
        Some repository formats (pack and newer for bzrlib native formats)
 
1338
        support refresh_data inside write groups. If called inside a write
 
1339
        group on a repository that does not support refreshing in a write group
 
1340
        IsInWriteGroupError will be raised.
1315
1341
        """
1316
 
        if self.is_in_write_group():
1317
 
            raise errors.InternalBzrError(
1318
 
                "May not refresh_data while in a write group.")
1319
1342
        if self._real_repository is not None:
1320
1343
            self._real_repository.refresh_data()
1321
1344
 
1333
1356
        return result
1334
1357
 
1335
1358
    @needs_read_lock
1336
 
    def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
 
1359
    def search_missing_revision_ids(self, other,
 
1360
            revision_id=symbol_versioning.DEPRECATED_PARAMETER,
 
1361
            find_ghosts=True, revision_ids=None, if_present_ids=None):
1337
1362
        """Return the revision ids that other has that this does not.
1338
1363
 
1339
1364
        These are returned in topological order.
1340
1365
 
1341
1366
        revision_id: only return revision ids included by revision_id.
1342
1367
        """
1343
 
        return repository.InterRepository.get(
1344
 
            other, self).search_missing_revision_ids(revision_id, find_ghosts)
 
1368
        if symbol_versioning.deprecated_passed(revision_id):
 
1369
            symbol_versioning.warn(
 
1370
                'search_missing_revision_ids(revision_id=...) was '
 
1371
                'deprecated in 2.4.  Use revision_ids=[...] instead.',
 
1372
                DeprecationWarning, stacklevel=2)
 
1373
            if revision_ids is not None:
 
1374
                raise AssertionError(
 
1375
                    'revision_ids is mutually exclusive with revision_id')
 
1376
            if revision_id is not None:
 
1377
                revision_ids = [revision_id]
 
1378
        inter_repo = repository.InterRepository.get(other, self)
 
1379
        return inter_repo.search_missing_revision_ids(
 
1380
            find_ghosts=find_ghosts, revision_ids=revision_ids,
 
1381
            if_present_ids=if_present_ids)
1345
1382
 
1346
 
    def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
 
1383
    def fetch(self, source, revision_id=None, find_ghosts=False,
1347
1384
            fetch_spec=None):
1348
1385
        # No base implementation to use as RemoteRepository is not a subclass
1349
1386
        # of Repository; so this is a copy of Repository.fetch().
1367
1404
        # the InterRepository base class, which raises an
1368
1405
        # IncompatibleRepositories when asked to fetch.
1369
1406
        inter = repository.InterRepository.get(source, self)
1370
 
        return inter.fetch(revision_id=revision_id, pb=pb,
 
1407
        return inter.fetch(revision_id=revision_id,
1371
1408
            find_ghosts=find_ghosts, fetch_spec=fetch_spec)
1372
1409
 
1373
1410
    def create_bundle(self, target, base, fileobj, format=None):
1748
1785
        return '\n'.join((start_keys, stop_keys, count))
1749
1786
 
1750
1787
    def _serialise_search_result(self, search_result):
1751
 
        if isinstance(search_result, graph.PendingAncestryResult):
1752
 
            parts = ['ancestry-of']
1753
 
            parts.extend(search_result.heads)
1754
 
        else:
1755
 
            recipe = search_result.get_recipe()
1756
 
            parts = [recipe[0], self._serialise_search_recipe(recipe)]
 
1788
        parts = search_result.get_network_struct()
1757
1789
        return '\n'.join(parts)
1758
1790
 
1759
1791
    def autopack(self):
1953
1985
        candidate_verbs = [
1954
1986
            ('Repository.get_stream_1.19', (1, 19)),
1955
1987
            ('Repository.get_stream', (1, 13))]
 
1988
 
1956
1989
        found_verb = False
1957
1990
        for verb, version in candidate_verbs:
1958
1991
            if medium._is_remote_before(version):
1962
1995
                    verb, args, search_bytes)
1963
1996
            except errors.UnknownSmartMethod:
1964
1997
                medium._remember_remote_is_before(version)
 
1998
            except errors.UnknownErrorFromSmartServer, e:
 
1999
                if isinstance(search, graph.EverythingResult):
 
2000
                    error_verb = e.error_from_smart_server.error_verb
 
2001
                    if error_verb == 'BadSearch':
 
2002
                        # Pre-2.4 servers don't support this sort of search.
 
2003
                        # XXX: perhaps falling back to VFS on BadSearch is a
 
2004
                        # good idea in general?  It might provide a little bit
 
2005
                        # of protection against client-side bugs.
 
2006
                        medium._remember_remote_is_before((2, 4))
 
2007
                        break
 
2008
                raise
1965
2009
            else:
1966
2010
                response_tuple, response_handler = response
1967
2011
                found_verb = True
1971
2015
        if response_tuple[0] != 'ok':
1972
2016
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1973
2017
        byte_stream = response_handler.read_streamed_body()
1974
 
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
 
2018
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
 
2019
            self._record_counter)
1975
2020
        if src_format.network_name() != repo._format.network_name():
1976
2021
            raise AssertionError(
1977
2022
                "Mismatched RemoteRepository and stream src %r, %r" % (
2081
2126
                                  name=name)
2082
2127
        return result
2083
2128
 
2084
 
    def initialize(self, a_bzrdir, name=None):
 
2129
    def initialize(self, a_bzrdir, name=None, repository=None):
2085
2130
        # 1) get the network name to use.
2086
2131
        if self._custom_format:
2087
2132
            network_name = self._custom_format.network_name()
2115
2160
        # Turn the response into a RemoteRepository object.
2116
2161
        format = RemoteBranchFormat(network_name=response[1])
2117
2162
        repo_format = response_tuple_to_repo_format(response[3:])
2118
 
        if response[2] == '':
2119
 
            repo_bzrdir = a_bzrdir
 
2163
        repo_path = response[2]
 
2164
        if repository is not None:
 
2165
            remote_repo_url = urlutils.join(a_bzrdir.user_url, repo_path)
 
2166
            url_diff = urlutils.relative_url(repository.user_url,
 
2167
                    remote_repo_url)
 
2168
            if url_diff != '.':
 
2169
                raise AssertionError(
 
2170
                    'repository.user_url %r does not match URL from server '
 
2171
                    'response (%r + %r)'
 
2172
                    % (repository.user_url, a_bzrdir.user_url, repo_path))
 
2173
            remote_repo = repository
2120
2174
        else:
2121
 
            repo_bzrdir = RemoteBzrDir(
2122
 
                a_bzrdir.root_transport.clone(response[2]), a_bzrdir._format,
2123
 
                a_bzrdir._client)
2124
 
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
 
2175
            if repo_path == '':
 
2176
                repo_bzrdir = a_bzrdir
 
2177
            else:
 
2178
                repo_bzrdir = RemoteBzrDir(
 
2179
                    a_bzrdir.root_transport.clone(repo_path), a_bzrdir._format,
 
2180
                    a_bzrdir._client)
 
2181
            remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2125
2182
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2126
2183
            format=format, setup_stacking=False, name=name)
2127
2184
        # XXX: We know this is a new branch, so it must have revno 0, revid
2148
2205
        self._ensure_real()
2149
2206
        return self._custom_format.supports_set_append_revisions_only()
2150
2207
 
 
2208
    def _use_default_local_heads_to_fetch(self):
 
2209
        # If the branch format is a metadir format *and* its heads_to_fetch
 
2210
        # implementation is not overridden vs the base class, we can use the
 
2211
        # base class logic rather than use the heads_to_fetch RPC.  This is
 
2212
        # usually cheaper in terms of net round trips, as the last-revision and
 
2213
        # tags info fetched is cached and would be fetched anyway.
 
2214
        self._ensure_real()
 
2215
        if isinstance(self._custom_format, branch.BranchFormatMetadir):
 
2216
            branch_class = self._custom_format._branch_class()
 
2217
            heads_to_fetch_impl = branch_class.heads_to_fetch.im_func
 
2218
            if heads_to_fetch_impl is branch.Branch.heads_to_fetch.im_func:
 
2219
                return True
 
2220
        return False
2151
2221
 
2152
2222
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2153
2223
    """Branch stored on a server accessed by HPSS RPC.
2357
2427
        self._ensure_real()
2358
2428
        return self._real_branch._get_tags_bytes()
2359
2429
 
 
2430
    @needs_read_lock
2360
2431
    def _get_tags_bytes(self):
 
2432
        if self._tags_bytes is None:
 
2433
            self._tags_bytes = self._get_tags_bytes_via_hpss()
 
2434
        return self._tags_bytes
 
2435
 
 
2436
    def _get_tags_bytes_via_hpss(self):
2361
2437
        medium = self._client._medium
2362
2438
        if medium._is_remote_before((1, 13)):
2363
2439
            return self._vfs_get_tags_bytes()
2373
2449
        return self._real_branch._set_tags_bytes(bytes)
2374
2450
 
2375
2451
    def _set_tags_bytes(self, bytes):
 
2452
        if self.is_locked():
 
2453
            self._tags_bytes = bytes
2376
2454
        medium = self._client._medium
2377
2455
        if medium._is_remote_before((1, 18)):
2378
2456
            self._vfs_set_tags_bytes(bytes)
2387
2465
            self._vfs_set_tags_bytes(bytes)
2388
2466
 
2389
2467
    def lock_read(self):
 
2468
        """Lock the branch for read operations.
 
2469
 
 
2470
        :return: A bzrlib.lock.LogicalLockResult.
 
2471
        """
2390
2472
        self.repository.lock_read()
2391
2473
        if not self._lock_mode:
2392
2474
            self._note_lock('r')
2396
2478
                self._real_branch.lock_read()
2397
2479
        else:
2398
2480
            self._lock_count += 1
 
2481
        return lock.LogicalLockResult(self.unlock)
2399
2482
 
2400
2483
    def _remote_lock_write(self, token):
2401
2484
        if token is None:
2402
2485
            branch_token = repo_token = ''
2403
2486
        else:
2404
2487
            branch_token = token
2405
 
            repo_token = self.repository.lock_write()
 
2488
            repo_token = self.repository.lock_write().repository_token
2406
2489
            self.repository.unlock()
2407
2490
        err_context = {'token': token}
2408
 
        response = self._call(
2409
 
            'Branch.lock_write', self._remote_path(), branch_token,
2410
 
            repo_token or '', **err_context)
 
2491
        try:
 
2492
            response = self._call(
 
2493
                'Branch.lock_write', self._remote_path(), branch_token,
 
2494
                repo_token or '', **err_context)
 
2495
        except errors.LockContention, e:
 
2496
            # The LockContention from the server doesn't have any
 
2497
            # information about the lock_url. We re-raise LockContention
 
2498
            # with valid lock_url.
 
2499
            raise errors.LockContention('(remote lock)',
 
2500
                self.repository.base.split('.bzr/')[0])
2411
2501
        if response[0] != 'ok':
2412
2502
            raise errors.UnexpectedSmartServerResponse(response)
2413
2503
        ok, branch_token, repo_token = response
2434
2524
            self._lock_mode = 'w'
2435
2525
            self._lock_count = 1
2436
2526
        elif self._lock_mode == 'r':
2437
 
            raise errors.ReadOnlyTransaction
 
2527
            raise errors.ReadOnlyError(self)
2438
2528
        else:
2439
2529
            if token is not None:
2440
2530
                # A token was given to lock_write, and we're relocking, so
2445
2535
            self._lock_count += 1
2446
2536
            # Re-lock the repository too.
2447
2537
            self.repository.lock_write(self._repo_lock_token)
2448
 
        return self._lock_token or None
 
2538
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
2449
2539
 
2450
2540
    def _unlock(self, branch_token, repo_token):
2451
2541
        err_context = {'token': str((branch_token, repo_token))}
2715
2805
        self._ensure_real()
2716
2806
        return self._real_branch.set_push_location(location)
2717
2807
 
 
2808
    def heads_to_fetch(self):
 
2809
        if self._format._use_default_local_heads_to_fetch():
 
2810
            # We recognise this format, and its heads-to-fetch implementation
 
2811
            # is the default one (tip + tags).  In this case it's cheaper to
 
2812
            # just use the default implementation rather than a special RPC as
 
2813
            # the tip and tags data is cached.
 
2814
            return branch.Branch.heads_to_fetch(self)
 
2815
        medium = self._client._medium
 
2816
        if medium._is_remote_before((2, 4)):
 
2817
            return self._vfs_heads_to_fetch()
 
2818
        try:
 
2819
            return self._rpc_heads_to_fetch()
 
2820
        except errors.UnknownSmartMethod:
 
2821
            medium._remember_remote_is_before((2, 4))
 
2822
            return self._vfs_heads_to_fetch()
 
2823
 
 
2824
    def _rpc_heads_to_fetch(self):
 
2825
        response = self._call('Branch.heads_to_fetch', self._remote_path())
 
2826
        if len(response) != 2:
 
2827
            raise errors.UnexpectedSmartServerResponse(response)
 
2828
        must_fetch, if_present_fetch = response
 
2829
        return set(must_fetch), set(if_present_fetch)
 
2830
 
 
2831
    def _vfs_heads_to_fetch(self):
 
2832
        self._ensure_real()
 
2833
        return self._real_branch.heads_to_fetch()
 
2834
 
2718
2835
 
2719
2836
class RemoteConfig(object):
2720
2837
    """A Config that reads and writes from smart verbs.
2774
2891
        medium = self._branch._client._medium
2775
2892
        if medium._is_remote_before((1, 14)):
2776
2893
            return self._vfs_set_option(value, name, section)
 
2894
        if isinstance(value, dict):
 
2895
            if medium._is_remote_before((2, 2)):
 
2896
                return self._vfs_set_option(value, name, section)
 
2897
            return self._set_config_option_dict(value, name, section)
 
2898
        else:
 
2899
            return self._set_config_option(value, name, section)
 
2900
 
 
2901
    def _set_config_option(self, value, name, section):
2777
2902
        try:
2778
2903
            path = self._branch._remote_path()
2779
2904
            response = self._branch._client.call('Branch.set_config_option',
2780
2905
                path, self._branch._lock_token, self._branch._repo_lock_token,
2781
2906
                value.encode('utf8'), name, section or '')
2782
2907
        except errors.UnknownSmartMethod:
 
2908
            medium = self._branch._client._medium
2783
2909
            medium._remember_remote_is_before((1, 14))
2784
2910
            return self._vfs_set_option(value, name, section)
2785
2911
        if response != ():
2786
2912
            raise errors.UnexpectedSmartServerResponse(response)
2787
2913
 
 
2914
    def _serialize_option_dict(self, option_dict):
 
2915
        utf8_dict = {}
 
2916
        for key, value in option_dict.items():
 
2917
            if isinstance(key, unicode):
 
2918
                key = key.encode('utf8')
 
2919
            if isinstance(value, unicode):
 
2920
                value = value.encode('utf8')
 
2921
            utf8_dict[key] = value
 
2922
        return bencode.bencode(utf8_dict)
 
2923
 
 
2924
    def _set_config_option_dict(self, value, name, section):
 
2925
        try:
 
2926
            path = self._branch._remote_path()
 
2927
            serialised_dict = self._serialize_option_dict(value)
 
2928
            response = self._branch._client.call(
 
2929
                'Branch.set_config_option_dict',
 
2930
                path, self._branch._lock_token, self._branch._repo_lock_token,
 
2931
                serialised_dict, name, section or '')
 
2932
        except errors.UnknownSmartMethod:
 
2933
            medium = self._branch._client._medium
 
2934
            medium._remember_remote_is_before((2, 2))
 
2935
            return self._vfs_set_option(value, name, section)
 
2936
        if response != ():
 
2937
            raise errors.UnexpectedSmartServerResponse(response)
 
2938
 
2788
2939
    def _real_object(self):
2789
2940
        self._branch._ensure_real()
2790
2941
        return self._branch._real_branch
2873
3024
                    'Missing key %r in context %r', key_err.args[0], context)
2874
3025
                raise err
2875
3026
 
2876
 
    if err.error_verb == 'IncompatibleRepositories':
2877
 
        raise errors.IncompatibleRepositories(err.error_args[0],
2878
 
            err.error_args[1], err.error_args[2])
2879
 
    elif err.error_verb == 'NoSuchRevision':
 
3027
    if err.error_verb == 'NoSuchRevision':
2880
3028
        raise NoSuchRevision(find('branch'), err.error_args[0])
2881
3029
    elif err.error_verb == 'nosuchrevision':
2882
3030
        raise NoSuchRevision(find('repository'), err.error_args[0])
2889
3037
            detail=extra)
2890
3038
    elif err.error_verb == 'norepository':
2891
3039
        raise errors.NoRepositoryPresent(find('bzrdir'))
2892
 
    elif err.error_verb == 'LockContention':
2893
 
        raise errors.LockContention('(remote lock)')
2894
3040
    elif err.error_verb == 'UnlockableTransport':
2895
3041
        raise errors.UnlockableTransport(find('bzrdir').root_transport)
2896
 
    elif err.error_verb == 'LockFailed':
2897
 
        raise errors.LockFailed(err.error_args[0], err.error_args[1])
2898
3042
    elif err.error_verb == 'TokenMismatch':
2899
3043
        raise errors.TokenMismatch(find('token'), '(remote token)')
2900
3044
    elif err.error_verb == 'Diverged':
2901
3045
        raise errors.DivergedBranches(find('branch'), find('other_branch'))
2902
 
    elif err.error_verb == 'TipChangeRejected':
2903
 
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
2904
 
    elif err.error_verb == 'UnstackableBranchFormat':
2905
 
        raise errors.UnstackableBranchFormat(*err.error_args)
2906
 
    elif err.error_verb == 'UnstackableRepositoryFormat':
2907
 
        raise errors.UnstackableRepositoryFormat(*err.error_args)
2908
3046
    elif err.error_verb == 'NotStacked':
2909
3047
        raise errors.NotStacked(branch=find('branch'))
2910
3048
    elif err.error_verb == 'PermissionDenied':
2920
3058
    elif err.error_verb == 'NoSuchFile':
2921
3059
        path = get_path()
2922
3060
        raise errors.NoSuchFile(path)
 
3061
    _translate_error_without_context(err)
 
3062
 
 
3063
 
 
3064
def _translate_error_without_context(err):
 
3065
    """Translate any ErrorFromSmartServer values that don't require context"""
 
3066
    if err.error_verb == 'IncompatibleRepositories':
 
3067
        raise errors.IncompatibleRepositories(err.error_args[0],
 
3068
            err.error_args[1], err.error_args[2])
 
3069
    elif err.error_verb == 'LockContention':
 
3070
        raise errors.LockContention('(remote lock)')
 
3071
    elif err.error_verb == 'LockFailed':
 
3072
        raise errors.LockFailed(err.error_args[0], err.error_args[1])
 
3073
    elif err.error_verb == 'TipChangeRejected':
 
3074
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
 
3075
    elif err.error_verb == 'UnstackableBranchFormat':
 
3076
        raise errors.UnstackableBranchFormat(*err.error_args)
 
3077
    elif err.error_verb == 'UnstackableRepositoryFormat':
 
3078
        raise errors.UnstackableRepositoryFormat(*err.error_args)
2923
3079
    elif err.error_verb == 'FileExists':
2924
3080
        raise errors.FileExists(err.error_args[0])
2925
3081
    elif err.error_verb == 'DirectoryNotEmpty':
2944
3100
            raise UnicodeEncodeError(encoding, val, start, end, reason)
2945
3101
    elif err.error_verb == 'ReadOnlyError':
2946
3102
        raise errors.TransportNotPossible('readonly transport')
 
3103
    elif err.error_verb == 'MemoryError':
 
3104
        raise errors.BzrError("remote server out of memory\n"
 
3105
            "Retry non-remotely, or contact the server admin for details.")
2947
3106
    raise errors.UnknownErrorFromSmartServer(err)