/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: Andrew Bennetts
  • Date: 2011-01-06 06:26:23 UTC
  • mto: This revision was merged to the branch mainline in revision 5612.
  • Revision ID: andrew.bennetts@canonical.com-20110106062623-43tda58mqroybjui
Start of a developer doc describing how fetch works.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
38
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
37
39
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
213
215
        if len(branch_info) != 2:
214
216
            raise errors.UnexpectedSmartServerResponse(response)
215
217
        branch_ref, branch_name = branch_info
216
 
        format = bzrdir.network_format_registry.get(control_name)
 
218
        format = controldir.network_format_registry.get(control_name)
217
219
        if repo_name:
218
220
            format.repository_format = repository.network_format_registry.get(
219
221
                repo_name)
245
247
        self._ensure_real()
246
248
        self._real_bzrdir.destroy_repository()
247
249
 
248
 
    def create_branch(self, name=None):
 
250
    def create_branch(self, name=None, repository=None):
249
251
        # as per meta1 formats - just delegate to the format object which may
250
252
        # be parameterised.
251
253
        real_branch = self._format.get_branch_format().initialize(self,
252
 
            name=name)
 
254
            name=name, repository=repository)
253
255
        if not isinstance(real_branch, RemoteBranch):
254
 
            result = RemoteBranch(self, self.find_repository(), real_branch,
255
 
                                  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)
256
261
        else:
257
262
            result = real_branch
258
263
        # BzrDir.clone_on_transport() uses the result of create_branch but does
270
275
        self._real_bzrdir.destroy_branch(name=name)
271
276
        self._next_open_branch_result = None
272
277
 
273
 
    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):
274
280
        raise errors.NotLocalUrl(self.transport.base)
275
281
 
276
282
    def find_branch_format(self, name=None):
648
654
 
649
655
 
650
656
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
651
 
    bzrdir.ControlComponent):
 
657
    controldir.ControlComponent):
652
658
    """Repository accessed over rpc.
653
659
 
654
660
    For the moment most operations are performed using local transport-backed
899
905
    def _has_same_fallbacks(self, other_repo):
900
906
        """Returns true if the repositories have the same fallbacks."""
901
907
        # XXX: copied from Repository; it should be unified into a base class
902
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
 
908
        # <https://bugs.launchpad.net/bzr/+bug/401622>
903
909
        my_fb = self._fallback_repositories
904
910
        other_fb = other_repo._fallback_repositories
905
911
        if len(my_fb) != len(other_fb):
1342
1348
        return result
1343
1349
 
1344
1350
    @needs_read_lock
1345
 
    def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
 
1351
    def search_missing_revision_ids(self, other,
 
1352
            revision_id=symbol_versioning.DEPRECATED_PARAMETER,
 
1353
            find_ghosts=True, revision_ids=None, if_present_ids=None):
1346
1354
        """Return the revision ids that other has that this does not.
1347
1355
 
1348
1356
        These are returned in topological order.
1349
1357
 
1350
1358
        revision_id: only return revision ids included by revision_id.
1351
1359
        """
1352
 
        return repository.InterRepository.get(
1353
 
            other, self).search_missing_revision_ids(revision_id, find_ghosts)
 
1360
        if symbol_versioning.deprecated_passed(revision_id):
 
1361
            symbol_versioning.warn(
 
1362
                'search_missing_revision_ids(revision_id=...) was '
 
1363
                'deprecated in 2.3.  Use revision_ids=[...] instead.',
 
1364
                DeprecationWarning, stacklevel=2)
 
1365
            if revision_ids is not None:
 
1366
                raise AssertionError(
 
1367
                    'revision_ids is mutually exclusive with revision_id')
 
1368
            if revision_id is not None:
 
1369
                revision_ids = [revision_id]
 
1370
        inter_repo = repository.InterRepository.get(other, self)
 
1371
        return inter_repo.search_missing_revision_ids(
 
1372
            find_ghosts=find_ghosts, revision_ids=revision_ids,
 
1373
            if_present_ids=if_present_ids)
1354
1374
 
1355
1375
    def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
1356
1376
            fetch_spec=None):
1757
1777
        return '\n'.join((start_keys, stop_keys, count))
1758
1778
 
1759
1779
    def _serialise_search_result(self, search_result):
1760
 
        if isinstance(search_result, graph.PendingAncestryResult):
1761
 
            parts = ['ancestry-of']
1762
 
            parts.extend(search_result.heads)
1763
 
        else:
1764
 
            recipe = search_result.get_recipe()
1765
 
            parts = [recipe[0], self._serialise_search_recipe(recipe)]
 
1780
        parts = search_result.get_network_struct()
1766
1781
        return '\n'.join(parts)
1767
1782
 
1768
1783
    def autopack(self):
1962
1977
        candidate_verbs = [
1963
1978
            ('Repository.get_stream_1.19', (1, 19)),
1964
1979
            ('Repository.get_stream', (1, 13))]
 
1980
 
1965
1981
        found_verb = False
1966
1982
        for verb, version in candidate_verbs:
1967
1983
            if medium._is_remote_before(version):
1971
1987
                    verb, args, search_bytes)
1972
1988
            except errors.UnknownSmartMethod:
1973
1989
                medium._remember_remote_is_before(version)
 
1990
            except errors.UnknownErrorFromSmartServer, e:
 
1991
                if isinstance(search, graph.EverythingResult):
 
1992
                    error_verb = e.error_from_smart_server.error_verb
 
1993
                    if error_verb == 'BadSearch':
 
1994
                        # Pre-2.3 servers don't support this sort of search.
 
1995
                        # XXX: perhaps falling back to VFS on BadSearch is a
 
1996
                        # good idea in general?  It might provide a little bit
 
1997
                        # of protection against client-side bugs.
 
1998
                        medium._remember_remote_is_before((2, 3))
 
1999
                        break
 
2000
                raise
1974
2001
            else:
1975
2002
                response_tuple, response_handler = response
1976
2003
                found_verb = True
1980
2007
        if response_tuple[0] != 'ok':
1981
2008
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1982
2009
        byte_stream = response_handler.read_streamed_body()
1983
 
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
 
2010
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
 
2011
            self._record_counter)
1984
2012
        if src_format.network_name() != repo._format.network_name():
1985
2013
            raise AssertionError(
1986
2014
                "Mismatched RemoteRepository and stream src %r, %r" % (
2090
2118
                                  name=name)
2091
2119
        return result
2092
2120
 
2093
 
    def initialize(self, a_bzrdir, name=None):
 
2121
    def initialize(self, a_bzrdir, name=None, repository=None):
2094
2122
        # 1) get the network name to use.
2095
2123
        if self._custom_format:
2096
2124
            network_name = self._custom_format.network_name()
2124
2152
        # Turn the response into a RemoteRepository object.
2125
2153
        format = RemoteBranchFormat(network_name=response[1])
2126
2154
        repo_format = response_tuple_to_repo_format(response[3:])
2127
 
        if response[2] == '':
2128
 
            repo_bzrdir = a_bzrdir
 
2155
        repo_path = response[2]
 
2156
        if repository is not None:
 
2157
            remote_repo_url = urlutils.join(medium.base, repo_path)
 
2158
            url_diff = urlutils.relative_url(repository.user_url,
 
2159
                    remote_repo_url)
 
2160
            if url_diff != '.':
 
2161
                raise AssertionError(
 
2162
                    'repository.user_url %r does not match URL from server '
 
2163
                    'response (%r + %r)'
 
2164
                    % (repository.user_url, medium.base, repo_path))
 
2165
            remote_repo = repository
2129
2166
        else:
2130
 
            repo_bzrdir = RemoteBzrDir(
2131
 
                a_bzrdir.root_transport.clone(response[2]), a_bzrdir._format,
2132
 
                a_bzrdir._client)
2133
 
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
 
2167
            if repo_path == '':
 
2168
                repo_bzrdir = a_bzrdir
 
2169
            else:
 
2170
                repo_bzrdir = RemoteBzrDir(
 
2171
                    a_bzrdir.root_transport.clone(repo_path), a_bzrdir._format,
 
2172
                    a_bzrdir._client)
 
2173
            remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2134
2174
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2135
2175
            format=format, setup_stacking=False, name=name)
2136
2176
        # XXX: We know this is a new branch, so it must have revno 0, revid
2366
2406
        self._ensure_real()
2367
2407
        return self._real_branch._get_tags_bytes()
2368
2408
 
 
2409
    @needs_read_lock
2369
2410
    def _get_tags_bytes(self):
 
2411
        if self._tags_bytes is None:
 
2412
            self._tags_bytes = self._get_tags_bytes_via_hpss()
 
2413
        return self._tags_bytes
 
2414
 
 
2415
    def _get_tags_bytes_via_hpss(self):
2370
2416
        medium = self._client._medium
2371
2417
        if medium._is_remote_before((1, 13)):
2372
2418
            return self._vfs_get_tags_bytes()
2382
2428
        return self._real_branch._set_tags_bytes(bytes)
2383
2429
 
2384
2430
    def _set_tags_bytes(self, bytes):
 
2431
        if self.is_locked():
 
2432
            self._tags_bytes = bytes
2385
2433
        medium = self._client._medium
2386
2434
        if medium._is_remote_before((1, 18)):
2387
2435
            self._vfs_set_tags_bytes(bytes)
2419
2467
            repo_token = self.repository.lock_write().repository_token
2420
2468
            self.repository.unlock()
2421
2469
        err_context = {'token': token}
2422
 
        response = self._call(
2423
 
            'Branch.lock_write', self._remote_path(), branch_token,
2424
 
            repo_token or '', **err_context)
 
2470
        try:
 
2471
            response = self._call(
 
2472
                'Branch.lock_write', self._remote_path(), branch_token,
 
2473
                repo_token or '', **err_context)
 
2474
        except errors.LockContention, e:
 
2475
            # The LockContention from the server doesn't have any
 
2476
            # information about the lock_url. We re-raise LockContention
 
2477
            # with valid lock_url.
 
2478
            raise errors.LockContention('(remote lock)',
 
2479
                self.repository.base.split('.bzr/')[0])
2425
2480
        if response[0] != 'ok':
2426
2481
            raise errors.UnexpectedSmartServerResponse(response)
2427
2482
        ok, branch_token, repo_token = response
2448
2503
            self._lock_mode = 'w'
2449
2504
            self._lock_count = 1
2450
2505
        elif self._lock_mode == 'r':
2451
 
            raise errors.ReadOnlyTransaction
 
2506
            raise errors.ReadOnlyError(self)
2452
2507
        else:
2453
2508
            if token is not None:
2454
2509
                # A token was given to lock_write, and we're relocking, so
2788
2843
        medium = self._branch._client._medium
2789
2844
        if medium._is_remote_before((1, 14)):
2790
2845
            return self._vfs_set_option(value, name, section)
 
2846
        if isinstance(value, dict):
 
2847
            if medium._is_remote_before((2, 2)):
 
2848
                return self._vfs_set_option(value, name, section)
 
2849
            return self._set_config_option_dict(value, name, section)
 
2850
        else:
 
2851
            return self._set_config_option(value, name, section)
 
2852
 
 
2853
    def _set_config_option(self, value, name, section):
2791
2854
        try:
2792
2855
            path = self._branch._remote_path()
2793
2856
            response = self._branch._client.call('Branch.set_config_option',
2794
2857
                path, self._branch._lock_token, self._branch._repo_lock_token,
2795
2858
                value.encode('utf8'), name, section or '')
2796
2859
        except errors.UnknownSmartMethod:
 
2860
            medium = self._branch._client._medium
2797
2861
            medium._remember_remote_is_before((1, 14))
2798
2862
            return self._vfs_set_option(value, name, section)
2799
2863
        if response != ():
2800
2864
            raise errors.UnexpectedSmartServerResponse(response)
2801
2865
 
 
2866
    def _serialize_option_dict(self, option_dict):
 
2867
        utf8_dict = {}
 
2868
        for key, value in option_dict.items():
 
2869
            if isinstance(key, unicode):
 
2870
                key = key.encode('utf8')
 
2871
            if isinstance(value, unicode):
 
2872
                value = value.encode('utf8')
 
2873
            utf8_dict[key] = value
 
2874
        return bencode.bencode(utf8_dict)
 
2875
 
 
2876
    def _set_config_option_dict(self, value, name, section):
 
2877
        try:
 
2878
            path = self._branch._remote_path()
 
2879
            serialised_dict = self._serialize_option_dict(value)
 
2880
            response = self._branch._client.call(
 
2881
                'Branch.set_config_option_dict',
 
2882
                path, self._branch._lock_token, self._branch._repo_lock_token,
 
2883
                serialised_dict, name, section or '')
 
2884
        except errors.UnknownSmartMethod:
 
2885
            medium = self._branch._client._medium
 
2886
            medium._remember_remote_is_before((2, 2))
 
2887
            return self._vfs_set_option(value, name, section)
 
2888
        if response != ():
 
2889
            raise errors.UnexpectedSmartServerResponse(response)
 
2890
 
2802
2891
    def _real_object(self):
2803
2892
        self._branch._ensure_real()
2804
2893
        return self._branch._real_branch