~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Martin Pool
  • Date: 2010-12-16 06:24:14 UTC
  • mfrom: (5538.2.4 bzr-docs-textfixes)
  • mto: This revision was merged to the branch mainline in revision 5572.
  • Revision ID: mbp@sourcefrog.net-20101216062414-y14p9t3otmmbtpsw
merge uppercasing of acronyms

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