/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

Add a NEWS entry and prepare submission.

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
 
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
 
34
from bzrlib.branch import BranchReferenceFormat
37
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
36
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
39
37
from bzrlib.errors import (
43
41
from bzrlib.lockable_files import LockableFiles
44
42
from bzrlib.smart import client, vfs, repository as smart_repo
45
43
from bzrlib.revision import ensure_null, NULL_REVISION
46
 
from bzrlib.repository import RepositoryWriteLockResult
47
44
from bzrlib.trace import mutter, note, warning
48
45
 
49
46
 
117
114
 
118
115
        self._probe_bzrdir()
119
116
 
120
 
    def __repr__(self):
121
 
        return '%s(%r)' % (self.__class__.__name__, self._client)
122
 
 
123
117
    def _probe_bzrdir(self):
124
118
        medium = self._client._medium
125
119
        path = self._path_for_remote_call(self._client)
245
239
        self._ensure_real()
246
240
        self._real_bzrdir.destroy_repository()
247
241
 
248
 
    def create_branch(self, name=None):
 
242
    def create_branch(self):
249
243
        # as per meta1 formats - just delegate to the format object which may
250
244
        # be parameterised.
251
 
        real_branch = self._format.get_branch_format().initialize(self,
252
 
            name=name)
 
245
        real_branch = self._format.get_branch_format().initialize(self)
253
246
        if not isinstance(real_branch, RemoteBranch):
254
 
            result = RemoteBranch(self, self.find_repository(), real_branch,
255
 
                                  name=name)
 
247
            result = RemoteBranch(self, self.find_repository(), real_branch)
256
248
        else:
257
249
            result = real_branch
258
250
        # BzrDir.clone_on_transport() uses the result of create_branch but does
264
256
        self._next_open_branch_result = result
265
257
        return result
266
258
 
267
 
    def destroy_branch(self, name=None):
 
259
    def destroy_branch(self):
268
260
        """See BzrDir.destroy_branch"""
269
261
        self._ensure_real()
270
 
        self._real_bzrdir.destroy_branch(name=name)
 
262
        self._real_bzrdir.destroy_branch()
271
263
        self._next_open_branch_result = None
272
264
 
273
265
    def create_workingtree(self, revision_id=None, from_branch=None):
274
266
        raise errors.NotLocalUrl(self.transport.base)
275
267
 
276
 
    def find_branch_format(self, name=None):
 
268
    def find_branch_format(self):
277
269
        """Find the branch 'format' for this bzrdir.
278
270
 
279
271
        This might be a synthetic object for e.g. RemoteBranch and SVN.
280
272
        """
281
 
        b = self.open_branch(name=name)
 
273
        b = self.open_branch()
282
274
        return b._format
283
275
 
284
 
    def get_branch_reference(self, name=None):
 
276
    def get_branch_reference(self):
285
277
        """See BzrDir.get_branch_reference()."""
286
 
        if name is not None:
287
 
            # XXX JRV20100304: Support opening colocated branches
288
 
            raise errors.NoColocatedBranchSupport(self)
289
278
        response = self._get_branch_reference()
290
279
        if response[0] == 'ref':
291
280
            return response[1]
295
284
    def _get_branch_reference(self):
296
285
        path = self._path_for_remote_call(self._client)
297
286
        medium = self._client._medium
298
 
        candidate_calls = [
299
 
            ('BzrDir.open_branchV3', (2, 1)),
300
 
            ('BzrDir.open_branchV2', (1, 13)),
301
 
            ('BzrDir.open_branch', None),
302
 
            ]
303
 
        for verb, required_version in candidate_calls:
304
 
            if required_version and medium._is_remote_before(required_version):
305
 
                continue
 
287
        if not medium._is_remote_before((1, 13)):
306
288
            try:
307
 
                response = self._call(verb, path)
 
289
                response = self._call('BzrDir.open_branchV2', path)
 
290
                if response[0] not in ('ref', 'branch'):
 
291
                    raise errors.UnexpectedSmartServerResponse(response)
 
292
                return response
308
293
            except errors.UnknownSmartMethod:
309
 
                if required_version is None:
310
 
                    raise
311
 
                medium._remember_remote_is_before(required_version)
312
 
            else:
313
 
                break
314
 
        if verb == 'BzrDir.open_branch':
315
 
            if response[0] != 'ok':
316
 
                raise errors.UnexpectedSmartServerResponse(response)
317
 
            if response[1] != '':
318
 
                return ('ref', response[1])
319
 
            else:
320
 
                return ('branch', '')
321
 
        if response[0] not in ('ref', 'branch'):
 
294
                medium._remember_remote_is_before((1, 13))
 
295
        response = self._call('BzrDir.open_branch', path)
 
296
        if response[0] != 'ok':
322
297
            raise errors.UnexpectedSmartServerResponse(response)
323
 
        return response
 
298
        if response[1] != '':
 
299
            return ('ref', response[1])
 
300
        else:
 
301
            return ('branch', '')
324
302
 
325
 
    def _get_tree_branch(self, name=None):
 
303
    def _get_tree_branch(self):
326
304
        """See BzrDir._get_tree_branch()."""
327
 
        return None, self.open_branch(name=name)
 
305
        return None, self.open_branch()
328
306
 
329
 
    def open_branch(self, name=None, unsupported=False,
330
 
                    ignore_fallbacks=False):
331
 
        if unsupported:
 
307
    def open_branch(self, _unsupported=False, ignore_fallbacks=False):
 
308
        if _unsupported:
332
309
            raise NotImplementedError('unsupported flag support not implemented yet.')
333
310
        if self._next_open_branch_result is not None:
334
311
            # See create_branch for details.
339
316
        if response[0] == 'ref':
340
317
            # a branch reference, use the existing BranchReference logic.
341
318
            format = BranchReferenceFormat()
342
 
            return format.open(self, name=name, _found=True,
343
 
                location=response[1], ignore_fallbacks=ignore_fallbacks)
 
319
            return format.open(self, _found=True, location=response[1],
 
320
                ignore_fallbacks=ignore_fallbacks)
344
321
        branch_format_name = response[1]
345
322
        if not branch_format_name:
346
323
            branch_format_name = None
347
324
        format = RemoteBranchFormat(network_name=branch_format_name)
348
325
        return RemoteBranch(self, self.find_repository(), format=format,
349
 
            setup_stacking=not ignore_fallbacks, name=name)
 
326
            setup_stacking=not ignore_fallbacks)
350
327
 
351
328
    def _open_repo_v1(self, path):
352
329
        verb = 'BzrDir.find_repository'
429
406
        """Return the path to be used for this bzrdir in a remote call."""
430
407
        return client.remote_path_from_transport(self.root_transport)
431
408
 
432
 
    def get_branch_transport(self, branch_format, name=None):
 
409
    def get_branch_transport(self, branch_format):
433
410
        self._ensure_real()
434
 
        return self._real_bzrdir.get_branch_transport(branch_format, name=name)
 
411
        return self._real_bzrdir.get_branch_transport(branch_format)
435
412
 
436
413
    def get_repository_transport(self, repository_format):
437
414
        self._ensure_real()
647
624
        return self._custom_format._serializer
648
625
 
649
626
 
650
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
651
 
    bzrdir.ControlComponent):
 
627
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):
652
628
    """Repository accessed over rpc.
653
629
 
654
630
    For the moment most operations are performed using local transport-backed
697
673
        # Additional places to query for data.
698
674
        self._fallback_repositories = []
699
675
 
700
 
    @property
701
 
    def user_transport(self):
702
 
        return self.bzrdir.user_transport
703
 
 
704
 
    @property
705
 
    def control_transport(self):
706
 
        # XXX: Normally you shouldn't directly get at the remote repository
707
 
        # transport, but I'm not sure it's worth making this method
708
 
        # optional -- mbp 2010-04-21
709
 
        return self.bzrdir.get_repository_transport(None)
710
 
        
711
676
    def __str__(self):
712
677
        return "%s(%s)" % (self.__class__.__name__, self.base)
713
678
 
899
864
    def _has_same_fallbacks(self, other_repo):
900
865
        """Returns true if the repositories have the same fallbacks."""
901
866
        # XXX: copied from Repository; it should be unified into a base class
902
 
        # <https://bugs.launchpad.net/bzr/+bug/401622>
 
867
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
903
868
        my_fb = self._fallback_repositories
904
869
        other_fb = other_repo._fallback_repositories
905
870
        if len(my_fb) != len(other_fb):
921
886
        parents_provider = self._make_parents_provider(other_repository)
922
887
        return graph.Graph(parents_provider)
923
888
 
924
 
    @needs_read_lock
925
 
    def get_known_graph_ancestry(self, revision_ids):
926
 
        """Return the known graph for a set of revision ids and their ancestors.
927
 
        """
928
 
        st = static_tuple.StaticTuple
929
 
        revision_keys = [st(r_id).intern() for r_id in revision_ids]
930
 
        known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
931
 
        return graph.GraphThunkIdsToKeys(known_graph)
932
 
 
933
889
    def gather_stats(self, revid=None, committers=None):
934
890
        """See Repository.gather_stats()."""
935
891
        path = self.bzrdir._path_for_remote_call(self._client)
995
951
    def is_write_locked(self):
996
952
        return self._lock_mode == 'w'
997
953
 
998
 
    def _warn_if_deprecated(self, branch=None):
999
 
        # If we have a real repository, the check will be done there, if we
1000
 
        # don't the check will be done remotely.
1001
 
        pass
1002
 
 
1003
954
    def lock_read(self):
1004
 
        """Lock the repository for read operations.
1005
 
 
1006
 
        :return: A bzrlib.lock.LogicalLockResult.
1007
 
        """
1008
955
        # wrong eventually - want a local lock cache context
1009
956
        if not self._lock_mode:
1010
957
            self._note_lock('r')
1017
964
                repo.lock_read()
1018
965
        else:
1019
966
            self._lock_count += 1
1020
 
        return lock.LogicalLockResult(self.unlock)
1021
967
 
1022
968
    def _remote_lock_write(self, token):
1023
969
        path = self.bzrdir._path_for_remote_call(self._client)
1063
1009
            raise errors.ReadOnlyError(self)
1064
1010
        else:
1065
1011
            self._lock_count += 1
1066
 
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
 
1012
        return self._lock_token or None
1067
1013
 
1068
1014
    def leave_lock_in_place(self):
1069
1015
        if not self._lock_token:
1249
1195
            # state, so always add a lock here. If a caller passes us a locked
1250
1196
            # repository, they are responsible for unlocking it later.
1251
1197
            repository.lock_read()
1252
 
        self._check_fallback_repository(repository)
1253
1198
        self._fallback_repositories.append(repository)
1254
1199
        # If self._real_repository was parameterised already (e.g. because a
1255
1200
        # _real_branch had its get_stacked_on_url method called), then the
1256
1201
        # repository to be added may already be in the _real_repositories list.
1257
1202
        if self._real_repository is not None:
1258
 
            fallback_locations = [repo.user_url for repo in
 
1203
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
1259
1204
                self._real_repository._fallback_repositories]
1260
 
            if repository.user_url not in fallback_locations:
 
1205
            if repository.bzrdir.root_transport.base not in fallback_locations:
1261
1206
                self._real_repository.add_fallback_repository(repository)
1262
1207
 
1263
 
    def _check_fallback_repository(self, repository):
1264
 
        """Check that this repository can fallback to repository safely.
1265
 
 
1266
 
        Raise an error if not.
1267
 
 
1268
 
        :param repository: A repository to fallback to.
1269
 
        """
1270
 
        return _mod_repository.InterRepository._assert_same_model(
1271
 
            self, repository)
1272
 
 
1273
1208
    def add_inventory(self, revid, inv, parents):
1274
1209
        self._ensure_real()
1275
1210
        return self._real_repository.add_inventory(revid, inv, parents)
1276
1211
 
1277
1212
    def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1278
 
            parents, basis_inv=None, propagate_caches=False):
 
1213
                               parents):
1279
1214
        self._ensure_real()
1280
1215
        return self._real_repository.add_inventory_by_delta(basis_revision_id,
1281
 
            delta, new_revision_id, parents, basis_inv=basis_inv,
1282
 
            propagate_caches=propagate_caches)
 
1216
            delta, new_revision_id, parents)
1283
1217
 
1284
1218
    def add_revision(self, rev_id, rev, inv=None, config=None):
1285
1219
        self._ensure_real()
1315
1249
        return self._real_repository.make_working_trees()
1316
1250
 
1317
1251
    def refresh_data(self):
1318
 
        """Re-read any data needed to synchronise with disk.
 
1252
        """Re-read any data needed to to synchronise with disk.
1319
1253
 
1320
1254
        This method is intended to be called after another repository instance
1321
1255
        (such as one used by a smart server) has inserted data into the
1322
 
        repository. On all repositories this will work outside of write groups.
1323
 
        Some repository formats (pack and newer for bzrlib native formats)
1324
 
        support refresh_data inside write groups. If called inside a write
1325
 
        group on a repository that does not support refreshing in a write group
1326
 
        IsInWriteGroupError will be raised.
 
1256
        repository. It may not be called during a write group, but may be
 
1257
        called at any other time.
1327
1258
        """
 
1259
        if self.is_in_write_group():
 
1260
            raise errors.InternalBzrError(
 
1261
                "May not refresh_data while in a write group.")
1328
1262
        if self._real_repository is not None:
1329
1263
            self._real_repository.refresh_data()
1330
1264
 
1544
1478
        return self._real_repository.get_signature_text(revision_id)
1545
1479
 
1546
1480
    @needs_read_lock
1547
 
    def _get_inventory_xml(self, revision_id):
1548
 
        self._ensure_real()
1549
 
        return self._real_repository._get_inventory_xml(revision_id)
 
1481
    def get_inventory_xml(self, revision_id):
 
1482
        self._ensure_real()
 
1483
        return self._real_repository.get_inventory_xml(revision_id)
 
1484
 
 
1485
    def deserialise_inventory(self, revision_id, xml):
 
1486
        self._ensure_real()
 
1487
        return self._real_repository.deserialise_inventory(revision_id, xml)
1550
1488
 
1551
1489
    def reconcile(self, other=None, thorough=False):
1552
1490
        self._ensure_real()
1628
1566
        return self._real_repository.inventories
1629
1567
 
1630
1568
    @needs_write_lock
1631
 
    def pack(self, hint=None, clean_obsolete_packs=False):
 
1569
    def pack(self, hint=None):
1632
1570
        """Compress the data within the repository.
1633
1571
 
1634
1572
        This is not currently implemented within the smart server.
1635
1573
        """
1636
1574
        self._ensure_real()
1637
 
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
 
1575
        return self._real_repository.pack(hint=hint)
1638
1576
 
1639
1577
    @property
1640
1578
    def revisions(self):
1980
1918
        if response_tuple[0] != 'ok':
1981
1919
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1982
1920
        byte_stream = response_handler.read_streamed_body()
1983
 
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1984
 
            self._record_counter)
 
1921
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1985
1922
        if src_format.network_name() != repo._format.network_name():
1986
1923
            raise AssertionError(
1987
1924
                "Mismatched RemoteRepository and stream src %r, %r" % (
2069
2006
    def network_name(self):
2070
2007
        return self._network_name
2071
2008
 
2072
 
    def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2073
 
        return a_bzrdir.open_branch(name=name, 
2074
 
            ignore_fallbacks=ignore_fallbacks)
 
2009
    def open(self, a_bzrdir, ignore_fallbacks=False):
 
2010
        return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2075
2011
 
2076
 
    def _vfs_initialize(self, a_bzrdir, name):
 
2012
    def _vfs_initialize(self, a_bzrdir):
2077
2013
        # Initialisation when using a local bzrdir object, or a non-vfs init
2078
2014
        # method is not available on the server.
2079
2015
        # self._custom_format is always set - the start of initialize ensures
2080
2016
        # that.
2081
2017
        if isinstance(a_bzrdir, RemoteBzrDir):
2082
2018
            a_bzrdir._ensure_real()
2083
 
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2084
 
                name)
 
2019
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2085
2020
        else:
2086
2021
            # We assume the bzrdir is parameterised; it may not be.
2087
 
            result = self._custom_format.initialize(a_bzrdir, name)
 
2022
            result = self._custom_format.initialize(a_bzrdir)
2088
2023
        if (isinstance(a_bzrdir, RemoteBzrDir) and
2089
2024
            not isinstance(result, RemoteBranch)):
2090
 
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2091
 
                                  name=name)
 
2025
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2092
2026
        return result
2093
2027
 
2094
 
    def initialize(self, a_bzrdir, name=None):
 
2028
    def initialize(self, a_bzrdir):
2095
2029
        # 1) get the network name to use.
2096
2030
        if self._custom_format:
2097
2031
            network_name = self._custom_format.network_name()
2103
2037
            network_name = reference_format.network_name()
2104
2038
        # Being asked to create on a non RemoteBzrDir:
2105
2039
        if not isinstance(a_bzrdir, RemoteBzrDir):
2106
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2040
            return self._vfs_initialize(a_bzrdir)
2107
2041
        medium = a_bzrdir._client._medium
2108
2042
        if medium._is_remote_before((1, 13)):
2109
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2043
            return self._vfs_initialize(a_bzrdir)
2110
2044
        # Creating on a remote bzr dir.
2111
2045
        # 2) try direct creation via RPC
2112
2046
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2113
 
        if name is not None:
2114
 
            # XXX JRV20100304: Support creating colocated branches
2115
 
            raise errors.NoColocatedBranchSupport(self)
2116
2047
        verb = 'BzrDir.create_branch'
2117
2048
        try:
2118
2049
            response = a_bzrdir._call(verb, path, network_name)
2119
2050
        except errors.UnknownSmartMethod:
2120
2051
            # Fallback - use vfs methods
2121
2052
            medium._remember_remote_is_before((1, 13))
2122
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2053
            return self._vfs_initialize(a_bzrdir)
2123
2054
        if response[0] != 'ok':
2124
2055
            raise errors.UnexpectedSmartServerResponse(response)
2125
2056
        # Turn the response into a RemoteRepository object.
2133
2064
                a_bzrdir._client)
2134
2065
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2135
2066
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2136
 
            format=format, setup_stacking=False, name=name)
 
2067
            format=format, setup_stacking=False)
2137
2068
        # XXX: We know this is a new branch, so it must have revno 0, revid
2138
2069
        # NULL_REVISION. Creating the branch locked would make this be unable
2139
2070
        # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2166
2097
    """
2167
2098
 
2168
2099
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2169
 
        _client=None, format=None, setup_stacking=True, name=None):
 
2100
        _client=None, format=None, setup_stacking=True):
2170
2101
        """Create a RemoteBranch instance.
2171
2102
 
2172
2103
        :param real_branch: An optional local implementation of the branch
2178
2109
        :param setup_stacking: If True make an RPC call to determine the
2179
2110
            stacked (or not) status of the branch. If False assume the branch
2180
2111
            is not stacked.
2181
 
        :param name: Colocated branch name
2182
2112
        """
2183
2113
        # We intentionally don't call the parent class's __init__, because it
2184
2114
        # will try to assign to self.tags, which is a property in this subclass.
2203
2133
            self._real_branch = None
2204
2134
        # Fill out expected attributes of branch for bzrlib API users.
2205
2135
        self._clear_cached_state()
2206
 
        # TODO: deprecate self.base in favor of user_url
2207
 
        self.base = self.bzrdir.user_url
2208
 
        self._name = name
 
2136
        self.base = self.bzrdir.root_transport.base
2209
2137
        self._control_files = None
2210
2138
        self._lock_mode = None
2211
2139
        self._lock_token = None
2276
2204
                    'to use vfs implementation')
2277
2205
            self.bzrdir._ensure_real()
2278
2206
            self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2279
 
                ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
 
2207
                ignore_fallbacks=self._real_ignore_fallbacks)
2280
2208
            if self.repository._real_repository is None:
2281
2209
                # Give the remote repository the matching real repo.
2282
2210
                real_repo = self._real_branch.repository
2397
2325
            self._vfs_set_tags_bytes(bytes)
2398
2326
 
2399
2327
    def lock_read(self):
2400
 
        """Lock the branch for read operations.
2401
 
 
2402
 
        :return: A bzrlib.lock.LogicalLockResult.
2403
 
        """
2404
2328
        self.repository.lock_read()
2405
2329
        if not self._lock_mode:
2406
2330
            self._note_lock('r')
2410
2334
                self._real_branch.lock_read()
2411
2335
        else:
2412
2336
            self._lock_count += 1
2413
 
        return lock.LogicalLockResult(self.unlock)
2414
2337
 
2415
2338
    def _remote_lock_write(self, token):
2416
2339
        if token is None:
2417
2340
            branch_token = repo_token = ''
2418
2341
        else:
2419
2342
            branch_token = token
2420
 
            repo_token = self.repository.lock_write().repository_token
 
2343
            repo_token = self.repository.lock_write()
2421
2344
            self.repository.unlock()
2422
2345
        err_context = {'token': token}
2423
2346
        response = self._call(
2449
2372
            self._lock_mode = 'w'
2450
2373
            self._lock_count = 1
2451
2374
        elif self._lock_mode == 'r':
2452
 
            raise errors.ReadOnlyError(self)
 
2375
            raise errors.ReadOnlyTransaction
2453
2376
        else:
2454
2377
            if token is not None:
2455
2378
                # A token was given to lock_write, and we're relocking, so
2460
2383
            self._lock_count += 1
2461
2384
            # Re-lock the repository too.
2462
2385
            self.repository.lock_write(self._repo_lock_token)
2463
 
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
 
2386
        return self._lock_token or None
2464
2387
 
2465
2388
    def _unlock(self, branch_token, repo_token):
2466
2389
        err_context = {'token': str((branch_token, repo_token))}
2789
2712
        medium = self._branch._client._medium
2790
2713
        if medium._is_remote_before((1, 14)):
2791
2714
            return self._vfs_set_option(value, name, section)
2792
 
        if isinstance(value, dict):
2793
 
            if medium._is_remote_before((2, 2)):
2794
 
                return self._vfs_set_option(value, name, section)
2795
 
            return self._set_config_option_dict(value, name, section)
2796
 
        else:
2797
 
            return self._set_config_option(value, name, section)
2798
 
 
2799
 
    def _set_config_option(self, value, name, section):
2800
2715
        try:
2801
2716
            path = self._branch._remote_path()
2802
2717
            response = self._branch._client.call('Branch.set_config_option',
2803
2718
                path, self._branch._lock_token, self._branch._repo_lock_token,
2804
2719
                value.encode('utf8'), name, section or '')
2805
2720
        except errors.UnknownSmartMethod:
2806
 
            medium = self._branch._client._medium
2807
2721
            medium._remember_remote_is_before((1, 14))
2808
2722
            return self._vfs_set_option(value, name, section)
2809
2723
        if response != ():
2810
2724
            raise errors.UnexpectedSmartServerResponse(response)
2811
2725
 
2812
 
    def _serialize_option_dict(self, option_dict):
2813
 
        utf8_dict = {}
2814
 
        for key, value in option_dict.items():
2815
 
            if isinstance(key, unicode):
2816
 
                key = key.encode('utf8')
2817
 
            if isinstance(value, unicode):
2818
 
                value = value.encode('utf8')
2819
 
            utf8_dict[key] = value
2820
 
        return bencode.bencode(utf8_dict)
2821
 
 
2822
 
    def _set_config_option_dict(self, value, name, section):
2823
 
        try:
2824
 
            path = self._branch._remote_path()
2825
 
            serialised_dict = self._serialize_option_dict(value)
2826
 
            response = self._branch._client.call(
2827
 
                'Branch.set_config_option_dict',
2828
 
                path, self._branch._lock_token, self._branch._repo_lock_token,
2829
 
                serialised_dict, name, section or '')
2830
 
        except errors.UnknownSmartMethod:
2831
 
            medium = self._branch._client._medium
2832
 
            medium._remember_remote_is_before((2, 2))
2833
 
            return self._vfs_set_option(value, name, section)
2834
 
        if response != ():
2835
 
            raise errors.UnexpectedSmartServerResponse(response)
2836
 
 
2837
2726
    def _real_object(self):
2838
2727
        self._branch._ensure_real()
2839
2728
        return self._branch._real_branch
2929
2818
        raise NoSuchRevision(find('branch'), err.error_args[0])
2930
2819
    elif err.error_verb == 'nosuchrevision':
2931
2820
        raise NoSuchRevision(find('repository'), err.error_args[0])
2932
 
    elif err.error_verb == 'nobranch':
2933
 
        if len(err.error_args) >= 1:
2934
 
            extra = err.error_args[0]
2935
 
        else:
2936
 
            extra = None
2937
 
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2938
 
            detail=extra)
 
2821
    elif err.error_tuple == ('nobranch',):
 
2822
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2939
2823
    elif err.error_verb == 'norepository':
2940
2824
        raise errors.NoRepositoryPresent(find('bzrdir'))
2941
2825
    elif err.error_verb == 'LockContention':