~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Ian Clatworthy
  • Date: 2009-09-09 00:49:50 UTC
  • mto: (4634.37.2 prepare-2.0)
  • mto: This revision was merged to the branch mainline in revision 4689.
  • Revision ID: ian.clatworthy@canonical.com-20090909004950-43z4zdicb5u91iet
tweak quick reference naming to make it consistent with other PDFs

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
33
33
)
34
34
from bzrlib.branch import BranchReferenceFormat
35
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
36
 
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
 
36
from bzrlib.decorators import needs_read_lock, needs_write_lock
37
37
from bzrlib.errors import (
38
38
    NoSuchRevision,
39
39
    SmartProtocolError,
89
89
class RemoteBzrDir(BzrDir, _RpcHelper):
90
90
    """Control directory on a remote server, accessed via bzr:// or similar."""
91
91
 
92
 
    def __init__(self, transport, format, _client=None, _force_probe=False):
 
92
    def __init__(self, transport, format, _client=None):
93
93
        """Construct a RemoteBzrDir.
94
94
 
95
95
        :param _client: Private parameter for testing. Disables probing and the
99
99
        # this object holds a delegated bzrdir that uses file-level operations
100
100
        # to talk to the other side
101
101
        self._real_bzrdir = None
102
 
        self._has_working_tree = None
103
102
        # 1-shot cache for the call pattern 'create_branch; open_branch' - see
104
103
        # create_branch for details.
105
104
        self._next_open_branch_result = None
109
108
            self._client = client._SmartClient(medium)
110
109
        else:
111
110
            self._client = _client
112
 
            if not _force_probe:
113
 
                return
114
 
 
115
 
        self._probe_bzrdir()
116
 
 
117
 
    def __repr__(self):
118
 
        return '%s(%r)' % (self.__class__.__name__, self._client)
119
 
 
120
 
    def _probe_bzrdir(self):
121
 
        medium = self._client._medium
 
111
            return
 
112
 
122
113
        path = self._path_for_remote_call(self._client)
123
 
        if medium._is_remote_before((2, 1)):
124
 
            self._rpc_open(path)
125
 
            return
126
 
        try:
127
 
            self._rpc_open_2_1(path)
128
 
            return
129
 
        except errors.UnknownSmartMethod:
130
 
            medium._remember_remote_is_before((2, 1))
131
 
            self._rpc_open(path)
132
 
 
133
 
    def _rpc_open_2_1(self, path):
134
 
        response = self._call('BzrDir.open_2.1', path)
135
 
        if response == ('no',):
136
 
            raise errors.NotBranchError(path=self.root_transport.base)
137
 
        elif response[0] == 'yes':
138
 
            if response[1] == 'yes':
139
 
                self._has_working_tree = True
140
 
            elif response[1] == 'no':
141
 
                self._has_working_tree = False
142
 
            else:
143
 
                raise errors.UnexpectedSmartServerResponse(response)
144
 
        else:
145
 
            raise errors.UnexpectedSmartServerResponse(response)
146
 
 
147
 
    def _rpc_open(self, path):
148
114
        response = self._call('BzrDir.open', path)
149
115
        if response not in [('yes',), ('no',)]:
150
116
            raise errors.UnexpectedSmartServerResponse(response)
151
117
        if response == ('no',):
152
 
            raise errors.NotBranchError(path=self.root_transport.base)
 
118
            raise errors.NotBranchError(path=transport.base)
153
119
 
154
120
    def _ensure_real(self):
155
121
        """Ensure that there is a _real_bzrdir set.
157
123
        Used before calls to self._real_bzrdir.
158
124
        """
159
125
        if not self._real_bzrdir:
160
 
            if 'hpssvfs' in debug.debug_flags:
161
 
                import traceback
162
 
                warning('VFS BzrDir access triggered\n%s',
163
 
                    ''.join(traceback.format_stack()))
164
126
            self._real_bzrdir = BzrDir.open_from_transport(
165
127
                self.root_transport, _server_formats=False)
166
128
            self._format._network_name = \
287
249
    def _get_branch_reference(self):
288
250
        path = self._path_for_remote_call(self._client)
289
251
        medium = self._client._medium
290
 
        candidate_calls = [
291
 
            ('BzrDir.open_branchV3', (2, 1)),
292
 
            ('BzrDir.open_branchV2', (1, 13)),
293
 
            ('BzrDir.open_branch', None),
294
 
            ]
295
 
        for verb, required_version in candidate_calls:
296
 
            if required_version and medium._is_remote_before(required_version):
297
 
                continue
 
252
        if not medium._is_remote_before((1, 13)):
298
253
            try:
299
 
                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
300
258
            except errors.UnknownSmartMethod:
301
 
                if required_version is None:
302
 
                    raise
303
 
                medium._remember_remote_is_before(required_version)
304
 
            else:
305
 
                break
306
 
        if verb == 'BzrDir.open_branch':
307
 
            if response[0] != 'ok':
308
 
                raise errors.UnexpectedSmartServerResponse(response)
309
 
            if response[1] != '':
310
 
                return ('ref', response[1])
311
 
            else:
312
 
                return ('branch', '')
313
 
        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':
314
262
            raise errors.UnexpectedSmartServerResponse(response)
315
 
        return response
 
263
        if response[1] != '':
 
264
            return ('ref', response[1])
 
265
        else:
 
266
            return ('branch', '')
316
267
 
317
268
    def _get_tree_branch(self):
318
269
        """See BzrDir._get_tree_branch()."""
404
355
        else:
405
356
            raise errors.NoRepositoryPresent(self)
406
357
 
407
 
    def has_workingtree(self):
408
 
        if self._has_working_tree is None:
409
 
            self._ensure_real()
410
 
            self._has_working_tree = self._real_bzrdir.has_workingtree()
411
 
        return self._has_working_tree
412
 
 
413
358
    def open_workingtree(self, recommend_upgrade=True):
414
 
        if self.has_workingtree():
 
359
        self._ensure_real()
 
360
        if self._real_bzrdir.has_workingtree():
415
361
            raise errors.NotLocalUrl(self.root_transport)
416
362
        else:
417
363
            raise errors.NoWorkingTree(self.root_transport.base)
615
561
        return self._custom_format._fetch_reconcile
616
562
 
617
563
    def get_format_description(self):
618
 
        self._ensure_real()
619
 
        return 'Remote: ' + self._custom_format.get_format_description()
 
564
        return 'bzr remote repository'
620
565
 
621
566
    def __eq__(self, other):
622
567
        return self.__class__ is other.__class__
638
583
        return self._custom_format._serializer
639
584
 
640
585
 
641
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):
 
586
class RemoteRepository(_RpcHelper):
642
587
    """Repository accessed over rpc.
643
588
 
644
589
    For the moment most operations are performed using local transport-backed
965
910
    def is_write_locked(self):
966
911
        return self._lock_mode == 'w'
967
912
 
968
 
    def _warn_if_deprecated(self, branch=None):
969
 
        # If we have a real repository, the check will be done there, if we
970
 
        # don't the check will be done remotely.
971
 
        pass
972
 
 
973
913
    def lock_read(self):
974
914
        # wrong eventually - want a local lock cache context
975
915
        if not self._lock_mode:
976
 
            self._note_lock('r')
977
916
            self._lock_mode = 'r'
978
917
            self._lock_count = 1
979
918
            self._unstacked_provider.enable_cache(cache_misses=True)
999
938
 
1000
939
    def lock_write(self, token=None, _skip_rpc=False):
1001
940
        if not self._lock_mode:
1002
 
            self._note_lock('w')
1003
941
            if _skip_rpc:
1004
942
                if self._lock_token is not None:
1005
943
                    if token != self._lock_token:
1108
1046
        else:
1109
1047
            raise errors.UnexpectedSmartServerResponse(response)
1110
1048
 
1111
 
    @only_raises(errors.LockNotHeld, errors.LockBroken)
1112
1049
    def unlock(self):
1113
1050
        if not self._lock_count:
1114
1051
            return lock.cant_unlock_not_held(self)
1497
1434
        return self._real_repository.get_signature_text(revision_id)
1498
1435
 
1499
1436
    @needs_read_lock
1500
 
    def _get_inventory_xml(self, revision_id):
 
1437
    def get_inventory_xml(self, revision_id):
1501
1438
        self._ensure_real()
1502
 
        return self._real_repository._get_inventory_xml(revision_id)
 
1439
        return self._real_repository.get_inventory_xml(revision_id)
1503
1440
 
1504
 
    def _deserialise_inventory(self, revision_id, xml):
 
1441
    def deserialise_inventory(self, revision_id, xml):
1505
1442
        self._ensure_real()
1506
 
        return self._real_repository._deserialise_inventory(revision_id, xml)
 
1443
        return self._real_repository.deserialise_inventory(revision_id, xml)
1507
1444
 
1508
1445
    def reconcile(self, other=None, thorough=False):
1509
1446
        self._ensure_real()
1802
1739
            # The stream included an inventory-delta record, but the remote
1803
1740
            # side isn't new enough to support them.  So we need to send the
1804
1741
            # rest of the stream via VFS.
1805
 
            self.target_repo.refresh_data()
1806
1742
            return self._resume_stream_with_vfs(response, src_format)
1807
1743
        if response[0][0] == 'missing-basis':
1808
1744
            tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1950
1886
        :param search: The overall search to satisfy with streams.
1951
1887
        :param sources: A list of Repository objects to query.
1952
1888
        """
1953
 
        self.from_serialiser = self.from_repository._format._serializer
 
1889
        self.serialiser = self.to_format._serializer
1954
1890
        self.seen_revs = set()
1955
1891
        self.referenced_revs = set()
1956
1892
        # If there are heads in the search, or the key count is > 0, we are not
1973
1909
    def missing_parents_rev_handler(self, substream):
1974
1910
        for content in substream:
1975
1911
            revision_bytes = content.get_bytes_as('fulltext')
1976
 
            revision = self.from_serialiser.read_revision_from_string(
1977
 
                revision_bytes)
 
1912
            revision = self.serialiser.read_revision_from_string(revision_bytes)
1978
1913
            self.seen_revs.add(content.key[-1])
1979
1914
            self.referenced_revs.update(revision.parent_ids)
1980
1915
            yield content
2019
1954
                self._network_name)
2020
1955
 
2021
1956
    def get_format_description(self):
2022
 
        self._ensure_real()
2023
 
        return 'Remote: ' + self._custom_format.get_format_description()
 
1957
        return 'Remote BZR Branch'
2024
1958
 
2025
1959
    def network_name(self):
2026
1960
        return self._network_name
2109
2043
        return self._custom_format.supports_set_append_revisions_only()
2110
2044
 
2111
2045
 
2112
 
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
 
2046
class RemoteBranch(branch.Branch, _RpcHelper):
2113
2047
    """Branch stored on a server accessed by HPSS RPC.
2114
2048
 
2115
2049
    At the moment most operations are mapped down to simple file operations.
2333
2267
        medium = self._client._medium
2334
2268
        if medium._is_remote_before((1, 18)):
2335
2269
            self._vfs_set_tags_bytes(bytes)
2336
 
            return
2337
2270
        try:
2338
2271
            args = (
2339
2272
                self._remote_path(), self._lock_token, self._repo_lock_token)
2346
2279
    def lock_read(self):
2347
2280
        self.repository.lock_read()
2348
2281
        if not self._lock_mode:
2349
 
            self._note_lock('r')
2350
2282
            self._lock_mode = 'r'
2351
2283
            self._lock_count = 1
2352
2284
            if self._real_branch is not None:
2372
2304
 
2373
2305
    def lock_write(self, token=None):
2374
2306
        if not self._lock_mode:
2375
 
            self._note_lock('w')
2376
2307
            # Lock the branch and repo in one remote call.
2377
2308
            remote_tokens = self._remote_lock_write(token)
2378
2309
            self._lock_token, self._repo_lock_token = remote_tokens
2413
2344
            return
2414
2345
        raise errors.UnexpectedSmartServerResponse(response)
2415
2346
 
2416
 
    @only_raises(errors.LockNotHeld, errors.LockBroken)
2417
2347
    def unlock(self):
2418
2348
        try:
2419
2349
            self._lock_count -= 1
2459
2389
            raise NotImplementedError(self.dont_leave_lock_in_place)
2460
2390
        self._leave_lock = False
2461
2391
 
2462
 
    @needs_read_lock
2463
2392
    def get_rev_id(self, revno, history=None):
2464
2393
        if revno == 0:
2465
2394
            return _mod_revision.NULL_REVISION
2837
2766
        raise NoSuchRevision(find('branch'), err.error_args[0])
2838
2767
    elif err.error_verb == 'nosuchrevision':
2839
2768
        raise NoSuchRevision(find('repository'), err.error_args[0])
2840
 
    elif err.error_verb == 'nobranch':
2841
 
        if len(err.error_args) >= 1:
2842
 
            extra = err.error_args[0]
2843
 
        else:
2844
 
            extra = None
2845
 
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2846
 
            detail=extra)
 
2769
    elif err.error_tuple == ('nobranch',):
 
2770
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2847
2771
    elif err.error_verb == 'norepository':
2848
2772
        raise errors.NoRepositoryPresent(find('bzrdir'))
2849
2773
    elif err.error_verb == 'LockContention':