~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Robert Collins
  • Date: 2010-04-10 09:22:04 UTC
  • mto: This revision was merged to the branch mainline in revision 5142.
  • Revision ID: robertc@robertcollins.net-20100410092204-jrdwwf7vtfr0t41k
``bzrlib.mutabletree.MutableTree.commit`` will now support a passed in
config as in previous versions of bzrlib. (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
    branch,
22
22
    bzrdir,
23
23
    config,
24
 
    controldir,
25
24
    debug,
26
25
    errors,
27
26
    graph,
28
27
    lock,
29
28
    lockdir,
30
29
    repository,
31
 
    repository as _mod_repository,
32
30
    revision,
33
31
    revision as _mod_revision,
34
 
    static_tuple,
35
32
    symbol_versioning,
36
33
)
37
 
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
 
34
from bzrlib.branch import BranchReferenceFormat
38
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
39
36
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
40
37
from bzrlib.errors import (
44
41
from bzrlib.lockable_files import LockableFiles
45
42
from bzrlib.smart import client, vfs, repository as smart_repo
46
43
from bzrlib.revision import ensure_null, NULL_REVISION
47
 
from bzrlib.repository import RepositoryWriteLockResult
48
44
from bzrlib.trace import mutter, note, warning
49
45
 
50
46
 
274
270
    def create_workingtree(self, revision_id=None, from_branch=None):
275
271
        raise errors.NotLocalUrl(self.transport.base)
276
272
 
277
 
    def find_branch_format(self, name=None):
 
273
    def find_branch_format(self):
278
274
        """Find the branch 'format' for this bzrdir.
279
275
 
280
276
        This might be a synthetic object for e.g. RemoteBranch and SVN.
281
277
        """
282
 
        b = self.open_branch(name=name)
 
278
        b = self.open_branch()
283
279
        return b._format
284
280
 
285
 
    def get_branch_reference(self, name=None):
 
281
    def get_branch_reference(self):
286
282
        """See BzrDir.get_branch_reference()."""
287
 
        if name is not None:
288
 
            # XXX JRV20100304: Support opening colocated branches
289
 
            raise errors.NoColocatedBranchSupport(self)
290
283
        response = self._get_branch_reference()
291
284
        if response[0] == 'ref':
292
285
            return response[1]
323
316
            raise errors.UnexpectedSmartServerResponse(response)
324
317
        return response
325
318
 
326
 
    def _get_tree_branch(self, name=None):
 
319
    def _get_tree_branch(self):
327
320
        """See BzrDir._get_tree_branch()."""
328
 
        return None, self.open_branch(name=name)
 
321
        return None, self.open_branch()
329
322
 
330
323
    def open_branch(self, name=None, unsupported=False,
331
324
                    ignore_fallbacks=False):
648
641
        return self._custom_format._serializer
649
642
 
650
643
 
651
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
652
 
    controldir.ControlComponent):
 
644
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):
653
645
    """Repository accessed over rpc.
654
646
 
655
647
    For the moment most operations are performed using local transport-backed
698
690
        # Additional places to query for data.
699
691
        self._fallback_repositories = []
700
692
 
701
 
    @property
702
 
    def user_transport(self):
703
 
        return self.bzrdir.user_transport
704
 
 
705
 
    @property
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)
711
 
        
712
693
    def __str__(self):
713
694
        return "%s(%s)" % (self.__class__.__name__, self.base)
714
695
 
900
881
    def _has_same_fallbacks(self, other_repo):
901
882
        """Returns true if the repositories have the same fallbacks."""
902
883
        # XXX: copied from Repository; it should be unified into a base class
903
 
        # <https://bugs.launchpad.net/bzr/+bug/401622>
 
884
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
904
885
        my_fb = self._fallback_repositories
905
886
        other_fb = other_repo._fallback_repositories
906
887
        if len(my_fb) != len(other_fb):
922
903
        parents_provider = self._make_parents_provider(other_repository)
923
904
        return graph.Graph(parents_provider)
924
905
 
925
 
    @needs_read_lock
926
 
    def get_known_graph_ancestry(self, revision_ids):
927
 
        """Return the known graph for a set of revision ids and their ancestors.
928
 
        """
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)
933
 
 
934
906
    def gather_stats(self, revid=None, committers=None):
935
907
        """See Repository.gather_stats()."""
936
908
        path = self.bzrdir._path_for_remote_call(self._client)
1002
974
        pass
1003
975
 
1004
976
    def lock_read(self):
1005
 
        """Lock the repository for read operations.
1006
 
 
1007
 
        :return: A bzrlib.lock.LogicalLockResult.
1008
 
        """
1009
977
        # wrong eventually - want a local lock cache context
1010
978
        if not self._lock_mode:
1011
979
            self._note_lock('r')
1018
986
                repo.lock_read()
1019
987
        else:
1020
988
            self._lock_count += 1
1021
 
        return lock.LogicalLockResult(self.unlock)
1022
989
 
1023
990
    def _remote_lock_write(self, token):
1024
991
        path = self.bzrdir._path_for_remote_call(self._client)
1064
1031
            raise errors.ReadOnlyError(self)
1065
1032
        else:
1066
1033
            self._lock_count += 1
1067
 
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
 
1034
        return self._lock_token or None
1068
1035
 
1069
1036
    def leave_lock_in_place(self):
1070
1037
        if not self._lock_token:
1250
1217
            # state, so always add a lock here. If a caller passes us a locked
1251
1218
            # repository, they are responsible for unlocking it later.
1252
1219
            repository.lock_read()
1253
 
        self._check_fallback_repository(repository)
1254
1220
        self._fallback_repositories.append(repository)
1255
1221
        # If self._real_repository was parameterised already (e.g. because a
1256
1222
        # _real_branch had its get_stacked_on_url method called), then the
1257
1223
        # repository to be added may already be in the _real_repositories list.
1258
1224
        if self._real_repository is not None:
1259
 
            fallback_locations = [repo.user_url for repo in
 
1225
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
1260
1226
                self._real_repository._fallback_repositories]
1261
 
            if repository.user_url not in fallback_locations:
 
1227
            if repository.bzrdir.root_transport.base not in fallback_locations:
1262
1228
                self._real_repository.add_fallback_repository(repository)
1263
1229
 
1264
 
    def _check_fallback_repository(self, repository):
1265
 
        """Check that this repository can fallback to repository safely.
1266
 
 
1267
 
        Raise an error if not.
1268
 
 
1269
 
        :param repository: A repository to fallback to.
1270
 
        """
1271
 
        return _mod_repository.InterRepository._assert_same_model(
1272
 
            self, repository)
1273
 
 
1274
1230
    def add_inventory(self, revid, inv, parents):
1275
1231
        self._ensure_real()
1276
1232
        return self._real_repository.add_inventory(revid, inv, parents)
1316
1272
        return self._real_repository.make_working_trees()
1317
1273
 
1318
1274
    def refresh_data(self):
1319
 
        """Re-read any data needed to synchronise with disk.
 
1275
        """Re-read any data needed to to synchronise with disk.
1320
1276
 
1321
1277
        This method is intended to be called after another repository instance
1322
1278
        (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.
 
1279
        repository. It may not be called during a write group, but may be
 
1280
        called at any other time.
1328
1281
        """
 
1282
        if self.is_in_write_group():
 
1283
            raise errors.InternalBzrError(
 
1284
                "May not refresh_data while in a write group.")
1329
1285
        if self._real_repository is not None:
1330
1286
            self._real_repository.refresh_data()
1331
1287
 
1629
1585
        return self._real_repository.inventories
1630
1586
 
1631
1587
    @needs_write_lock
1632
 
    def pack(self, hint=None, clean_obsolete_packs=False):
 
1588
    def pack(self, hint=None):
1633
1589
        """Compress the data within the repository.
1634
1590
 
1635
1591
        This is not currently implemented within the smart server.
1636
1592
        """
1637
1593
        self._ensure_real()
1638
 
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
 
1594
        return self._real_repository.pack(hint=hint)
1639
1595
 
1640
1596
    @property
1641
1597
    def revisions(self):
1981
1937
        if response_tuple[0] != 'ok':
1982
1938
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1983
1939
        byte_stream = response_handler.read_streamed_body()
1984
 
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1985
 
            self._record_counter)
 
1940
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1986
1941
        if src_format.network_name() != repo._format.network_name():
1987
1942
            raise AssertionError(
1988
1943
                "Mismatched RemoteRepository and stream src %r, %r" % (
2204
2159
            self._real_branch = None
2205
2160
        # Fill out expected attributes of branch for bzrlib API users.
2206
2161
        self._clear_cached_state()
2207
 
        # TODO: deprecate self.base in favor of user_url
2208
 
        self.base = self.bzrdir.user_url
 
2162
        self.base = self.bzrdir.root_transport.base
2209
2163
        self._name = name
2210
2164
        self._control_files = None
2211
2165
        self._lock_mode = None
2398
2352
            self._vfs_set_tags_bytes(bytes)
2399
2353
 
2400
2354
    def lock_read(self):
2401
 
        """Lock the branch for read operations.
2402
 
 
2403
 
        :return: A bzrlib.lock.LogicalLockResult.
2404
 
        """
2405
2355
        self.repository.lock_read()
2406
2356
        if not self._lock_mode:
2407
2357
            self._note_lock('r')
2411
2361
                self._real_branch.lock_read()
2412
2362
        else:
2413
2363
            self._lock_count += 1
2414
 
        return lock.LogicalLockResult(self.unlock)
2415
2364
 
2416
2365
    def _remote_lock_write(self, token):
2417
2366
        if token is None:
2418
2367
            branch_token = repo_token = ''
2419
2368
        else:
2420
2369
            branch_token = token
2421
 
            repo_token = self.repository.lock_write().repository_token
 
2370
            repo_token = self.repository.lock_write()
2422
2371
            self.repository.unlock()
2423
2372
        err_context = {'token': token}
2424
 
        try:
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])
 
2373
        response = self._call(
 
2374
            'Branch.lock_write', self._remote_path(), branch_token,
 
2375
            repo_token or '', **err_context)
2434
2376
        if response[0] != 'ok':
2435
2377
            raise errors.UnexpectedSmartServerResponse(response)
2436
2378
        ok, branch_token, repo_token = response
2457
2399
            self._lock_mode = 'w'
2458
2400
            self._lock_count = 1
2459
2401
        elif self._lock_mode == 'r':
2460
 
            raise errors.ReadOnlyError(self)
 
2402
            raise errors.ReadOnlyTransaction
2461
2403
        else:
2462
2404
            if token is not None:
2463
2405
                # A token was given to lock_write, and we're relocking, so
2468
2410
            self._lock_count += 1
2469
2411
            # Re-lock the repository too.
2470
2412
            self.repository.lock_write(self._repo_lock_token)
2471
 
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
 
2413
        return self._lock_token or None
2472
2414
 
2473
2415
    def _unlock(self, branch_token, repo_token):
2474
2416
        err_context = {'token': str((branch_token, repo_token))}
2797
2739
        medium = self._branch._client._medium
2798
2740
        if medium._is_remote_before((1, 14)):
2799
2741
            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)
2804
 
        else:
2805
 
            return self._set_config_option(value, name, section)
2806
 
 
2807
 
    def _set_config_option(self, value, name, section):
2808
2742
        try:
2809
2743
            path = self._branch._remote_path()
2810
2744
            response = self._branch._client.call('Branch.set_config_option',
2811
2745
                path, self._branch._lock_token, self._branch._repo_lock_token,
2812
2746
                value.encode('utf8'), name, section or '')
2813
2747
        except errors.UnknownSmartMethod:
2814
 
            medium = self._branch._client._medium
2815
2748
            medium._remember_remote_is_before((1, 14))
2816
2749
            return self._vfs_set_option(value, name, section)
2817
2750
        if response != ():
2818
2751
            raise errors.UnexpectedSmartServerResponse(response)
2819
2752
 
2820
 
    def _serialize_option_dict(self, option_dict):
2821
 
        utf8_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)
2829
 
 
2830
 
    def _set_config_option_dict(self, value, name, section):
2831
 
        try:
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)
2842
 
        if response != ():
2843
 
            raise errors.UnexpectedSmartServerResponse(response)
2844
 
 
2845
2753
    def _real_object(self):
2846
2754
        self._branch._ensure_real()
2847
2755
        return self._branch._real_branch