/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: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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,
25
24
    debug,
26
25
    errors,
27
26
    graph,
33
32
    revision as _mod_revision,
34
33
    static_tuple,
35
34
    symbol_versioning,
36
 
    urlutils,
37
35
)
38
 
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
 
36
from bzrlib.branch import BranchReferenceFormat
39
37
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
40
38
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
41
39
from bzrlib.errors import (
45
43
from bzrlib.lockable_files import LockableFiles
46
44
from bzrlib.smart import client, vfs, repository as smart_repo
47
45
from bzrlib.revision import ensure_null, NULL_REVISION
48
 
from bzrlib.repository import RepositoryWriteLockResult
49
46
from bzrlib.trace import mutter, note, warning
50
47
 
51
48
 
215
212
        if len(branch_info) != 2:
216
213
            raise errors.UnexpectedSmartServerResponse(response)
217
214
        branch_ref, branch_name = branch_info
218
 
        format = controldir.network_format_registry.get(control_name)
 
215
        format = bzrdir.network_format_registry.get(control_name)
219
216
        if repo_name:
220
217
            format.repository_format = repository.network_format_registry.get(
221
218
                repo_name)
247
244
        self._ensure_real()
248
245
        self._real_bzrdir.destroy_repository()
249
246
 
250
 
    def create_branch(self, name=None, repository=None):
 
247
    def create_branch(self, name=None):
251
248
        # as per meta1 formats - just delegate to the format object which may
252
249
        # be parameterised.
253
250
        real_branch = self._format.get_branch_format().initialize(self,
254
 
            name=name, repository=repository)
 
251
            name=name)
255
252
        if not isinstance(real_branch, RemoteBranch):
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)
 
253
            result = RemoteBranch(self, self.find_repository(), real_branch,
 
254
                                  name=name)
261
255
        else:
262
256
            result = real_branch
263
257
        # BzrDir.clone_on_transport() uses the result of create_branch but does
275
269
        self._real_bzrdir.destroy_branch(name=name)
276
270
        self._next_open_branch_result = None
277
271
 
278
 
    def create_workingtree(self, revision_id=None, from_branch=None,
279
 
        accelerator_tree=None, hardlink=False):
 
272
    def create_workingtree(self, revision_id=None, from_branch=None):
280
273
        raise errors.NotLocalUrl(self.transport.base)
281
274
 
282
 
    def find_branch_format(self, name=None):
 
275
    def find_branch_format(self):
283
276
        """Find the branch 'format' for this bzrdir.
284
277
 
285
278
        This might be a synthetic object for e.g. RemoteBranch and SVN.
286
279
        """
287
 
        b = self.open_branch(name=name)
 
280
        b = self.open_branch()
288
281
        return b._format
289
282
 
290
 
    def get_branch_reference(self, name=None):
 
283
    def get_branch_reference(self):
291
284
        """See BzrDir.get_branch_reference()."""
292
 
        if name is not None:
293
 
            # XXX JRV20100304: Support opening colocated branches
294
 
            raise errors.NoColocatedBranchSupport(self)
295
285
        response = self._get_branch_reference()
296
286
        if response[0] == 'ref':
297
287
            return response[1]
328
318
            raise errors.UnexpectedSmartServerResponse(response)
329
319
        return response
330
320
 
331
 
    def _get_tree_branch(self, name=None):
 
321
    def _get_tree_branch(self):
332
322
        """See BzrDir._get_tree_branch()."""
333
 
        return None, self.open_branch(name=name)
 
323
        return None, self.open_branch()
334
324
 
335
325
    def open_branch(self, name=None, unsupported=False,
336
326
                    ignore_fallbacks=False):
654
644
 
655
645
 
656
646
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
657
 
    controldir.ControlComponent):
 
647
    bzrdir.ControlComponent):
658
648
    """Repository accessed over rpc.
659
649
 
660
650
    For the moment most operations are performed using local transport-backed
905
895
    def _has_same_fallbacks(self, other_repo):
906
896
        """Returns true if the repositories have the same fallbacks."""
907
897
        # XXX: copied from Repository; it should be unified into a base class
908
 
        # <https://bugs.launchpad.net/bzr/+bug/401622>
 
898
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
909
899
        my_fb = self._fallback_repositories
910
900
        other_fb = other_repo._fallback_repositories
911
901
        if len(my_fb) != len(other_fb):
1007
997
        pass
1008
998
 
1009
999
    def lock_read(self):
1010
 
        """Lock the repository for read operations.
1011
 
 
1012
 
        :return: A bzrlib.lock.LogicalLockResult.
1013
 
        """
1014
1000
        # wrong eventually - want a local lock cache context
1015
1001
        if not self._lock_mode:
1016
1002
            self._note_lock('r')
1023
1009
                repo.lock_read()
1024
1010
        else:
1025
1011
            self._lock_count += 1
1026
 
        return lock.LogicalLockResult(self.unlock)
1027
1012
 
1028
1013
    def _remote_lock_write(self, token):
1029
1014
        path = self.bzrdir._path_for_remote_call(self._client)
1069
1054
            raise errors.ReadOnlyError(self)
1070
1055
        else:
1071
1056
            self._lock_count += 1
1072
 
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
 
1057
        return self._lock_token or None
1073
1058
 
1074
1059
    def leave_lock_in_place(self):
1075
1060
        if not self._lock_token:
1321
1306
        return self._real_repository.make_working_trees()
1322
1307
 
1323
1308
    def refresh_data(self):
1324
 
        """Re-read any data needed to synchronise with disk.
 
1309
        """Re-read any data needed to to synchronise with disk.
1325
1310
 
1326
1311
        This method is intended to be called after another repository instance
1327
1312
        (such as one used by a smart server) has inserted data into the
1328
 
        repository. On all repositories this will work outside of write groups.
1329
 
        Some repository formats (pack and newer for bzrlib native formats)
1330
 
        support refresh_data inside write groups. If called inside a write
1331
 
        group on a repository that does not support refreshing in a write group
1332
 
        IsInWriteGroupError will be raised.
 
1313
        repository. It may not be called during a write group, but may be
 
1314
        called at any other time.
1333
1315
        """
 
1316
        if self.is_in_write_group():
 
1317
            raise errors.InternalBzrError(
 
1318
                "May not refresh_data while in a write group.")
1334
1319
        if self._real_repository is not None:
1335
1320
            self._real_repository.refresh_data()
1336
1321
 
1986
1971
        if response_tuple[0] != 'ok':
1987
1972
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1988
1973
        byte_stream = response_handler.read_streamed_body()
1989
 
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
1990
 
            self._record_counter)
 
1974
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
1991
1975
        if src_format.network_name() != repo._format.network_name():
1992
1976
            raise AssertionError(
1993
1977
                "Mismatched RemoteRepository and stream src %r, %r" % (
2097
2081
                                  name=name)
2098
2082
        return result
2099
2083
 
2100
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2084
    def initialize(self, a_bzrdir, name=None):
2101
2085
        # 1) get the network name to use.
2102
2086
        if self._custom_format:
2103
2087
            network_name = self._custom_format.network_name()
2131
2115
        # Turn the response into a RemoteRepository object.
2132
2116
        format = RemoteBranchFormat(network_name=response[1])
2133
2117
        repo_format = response_tuple_to_repo_format(response[3:])
2134
 
        repo_path = response[2]
2135
 
        if repository is not None:
2136
 
            remote_repo_url = urlutils.join(medium.base, repo_path)
2137
 
            url_diff = urlutils.relative_url(repository.user_url,
2138
 
                    remote_repo_url)
2139
 
            if url_diff != '.':
2140
 
                raise AssertionError(
2141
 
                    'repository.user_url %r does not match URL from server '
2142
 
                    'response (%r + %r)'
2143
 
                    % (repository.user_url, medium.base, repo_path))
2144
 
            remote_repo = repository
 
2118
        if response[2] == '':
 
2119
            repo_bzrdir = a_bzrdir
2145
2120
        else:
2146
 
            if repo_path == '':
2147
 
                repo_bzrdir = a_bzrdir
2148
 
            else:
2149
 
                repo_bzrdir = RemoteBzrDir(
2150
 
                    a_bzrdir.root_transport.clone(repo_path), a_bzrdir._format,
2151
 
                    a_bzrdir._client)
2152
 
            remote_repo = RemoteRepository(repo_bzrdir, repo_format)
 
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)
2153
2125
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2154
2126
            format=format, setup_stacking=False, name=name)
2155
2127
        # XXX: We know this is a new branch, so it must have revno 0, revid
2385
2357
        self._ensure_real()
2386
2358
        return self._real_branch._get_tags_bytes()
2387
2359
 
2388
 
    @needs_read_lock
2389
2360
    def _get_tags_bytes(self):
2390
 
        if self._tags_bytes is None:
2391
 
            self._tags_bytes = self._get_tags_bytes_via_hpss()
2392
 
        return self._tags_bytes
2393
 
 
2394
 
    def _get_tags_bytes_via_hpss(self):
2395
2361
        medium = self._client._medium
2396
2362
        if medium._is_remote_before((1, 13)):
2397
2363
            return self._vfs_get_tags_bytes()
2407
2373
        return self._real_branch._set_tags_bytes(bytes)
2408
2374
 
2409
2375
    def _set_tags_bytes(self, bytes):
2410
 
        if self.is_locked():
2411
 
            self._tags_bytes = bytes
2412
2376
        medium = self._client._medium
2413
2377
        if medium._is_remote_before((1, 18)):
2414
2378
            self._vfs_set_tags_bytes(bytes)
2423
2387
            self._vfs_set_tags_bytes(bytes)
2424
2388
 
2425
2389
    def lock_read(self):
2426
 
        """Lock the branch for read operations.
2427
 
 
2428
 
        :return: A bzrlib.lock.LogicalLockResult.
2429
 
        """
2430
2390
        self.repository.lock_read()
2431
2391
        if not self._lock_mode:
2432
2392
            self._note_lock('r')
2436
2396
                self._real_branch.lock_read()
2437
2397
        else:
2438
2398
            self._lock_count += 1
2439
 
        return lock.LogicalLockResult(self.unlock)
2440
2399
 
2441
2400
    def _remote_lock_write(self, token):
2442
2401
        if token is None:
2443
2402
            branch_token = repo_token = ''
2444
2403
        else:
2445
2404
            branch_token = token
2446
 
            repo_token = self.repository.lock_write().repository_token
 
2405
            repo_token = self.repository.lock_write()
2447
2406
            self.repository.unlock()
2448
2407
        err_context = {'token': token}
2449
 
        try:
2450
 
            response = self._call(
2451
 
                'Branch.lock_write', self._remote_path(), branch_token,
2452
 
                repo_token or '', **err_context)
2453
 
        except errors.LockContention, e:
2454
 
            # The LockContention from the server doesn't have any
2455
 
            # information about the lock_url. We re-raise LockContention
2456
 
            # with valid lock_url.
2457
 
            raise errors.LockContention('(remote lock)',
2458
 
                self.repository.base.split('.bzr/')[0])
 
2408
        response = self._call(
 
2409
            'Branch.lock_write', self._remote_path(), branch_token,
 
2410
            repo_token or '', **err_context)
2459
2411
        if response[0] != 'ok':
2460
2412
            raise errors.UnexpectedSmartServerResponse(response)
2461
2413
        ok, branch_token, repo_token = response
2482
2434
            self._lock_mode = 'w'
2483
2435
            self._lock_count = 1
2484
2436
        elif self._lock_mode == 'r':
2485
 
            raise errors.ReadOnlyError(self)
 
2437
            raise errors.ReadOnlyTransaction
2486
2438
        else:
2487
2439
            if token is not None:
2488
2440
                # A token was given to lock_write, and we're relocking, so
2493
2445
            self._lock_count += 1
2494
2446
            # Re-lock the repository too.
2495
2447
            self.repository.lock_write(self._repo_lock_token)
2496
 
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
 
2448
        return self._lock_token or None
2497
2449
 
2498
2450
    def _unlock(self, branch_token, repo_token):
2499
2451
        err_context = {'token': str((branch_token, repo_token))}
2822
2774
        medium = self._branch._client._medium
2823
2775
        if medium._is_remote_before((1, 14)):
2824
2776
            return self._vfs_set_option(value, name, section)
2825
 
        if isinstance(value, dict):
2826
 
            if medium._is_remote_before((2, 2)):
2827
 
                return self._vfs_set_option(value, name, section)
2828
 
            return self._set_config_option_dict(value, name, section)
2829
 
        else:
2830
 
            return self._set_config_option(value, name, section)
2831
 
 
2832
 
    def _set_config_option(self, value, name, section):
2833
2777
        try:
2834
2778
            path = self._branch._remote_path()
2835
2779
            response = self._branch._client.call('Branch.set_config_option',
2836
2780
                path, self._branch._lock_token, self._branch._repo_lock_token,
2837
2781
                value.encode('utf8'), name, section or '')
2838
2782
        except errors.UnknownSmartMethod:
2839
 
            medium = self._branch._client._medium
2840
2783
            medium._remember_remote_is_before((1, 14))
2841
2784
            return self._vfs_set_option(value, name, section)
2842
2785
        if response != ():
2843
2786
            raise errors.UnexpectedSmartServerResponse(response)
2844
2787
 
2845
 
    def _serialize_option_dict(self, option_dict):
2846
 
        utf8_dict = {}
2847
 
        for key, value in option_dict.items():
2848
 
            if isinstance(key, unicode):
2849
 
                key = key.encode('utf8')
2850
 
            if isinstance(value, unicode):
2851
 
                value = value.encode('utf8')
2852
 
            utf8_dict[key] = value
2853
 
        return bencode.bencode(utf8_dict)
2854
 
 
2855
 
    def _set_config_option_dict(self, value, name, section):
2856
 
        try:
2857
 
            path = self._branch._remote_path()
2858
 
            serialised_dict = self._serialize_option_dict(value)
2859
 
            response = self._branch._client.call(
2860
 
                'Branch.set_config_option_dict',
2861
 
                path, self._branch._lock_token, self._branch._repo_lock_token,
2862
 
                serialised_dict, name, section or '')
2863
 
        except errors.UnknownSmartMethod:
2864
 
            medium = self._branch._client._medium
2865
 
            medium._remember_remote_is_before((2, 2))
2866
 
            return self._vfs_set_option(value, name, section)
2867
 
        if response != ():
2868
 
            raise errors.UnexpectedSmartServerResponse(response)
2869
 
 
2870
2788
    def _real_object(self):
2871
2789
        self._branch._ensure_real()
2872
2790
        return self._branch._real_branch