~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Martin
  • Date: 2010-05-16 15:18:43 UTC
  • mfrom: (5235 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5239.
  • Revision ID: gzlist@googlemail.com-20100516151843-lu53u7caehm3ie3i
Merge bzr.dev to resolve conflicts in NEWS and _chk_map_pyx

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
    lock,
28
28
    lockdir,
29
29
    repository,
 
30
    repository as _mod_repository,
30
31
    revision,
31
32
    revision as _mod_revision,
32
33
    static_tuple,
33
34
    symbol_versioning,
34
35
)
35
 
from bzrlib.branch import BranchReferenceFormat
 
36
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
36
37
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
37
38
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
38
39
from bzrlib.errors import (
42
43
from bzrlib.lockable_files import LockableFiles
43
44
from bzrlib.smart import client, vfs, repository as smart_repo
44
45
from bzrlib.revision import ensure_null, NULL_REVISION
 
46
from bzrlib.repository import RepositoryWriteLockResult
45
47
from bzrlib.trace import mutter, note, warning
46
48
 
47
49
 
271
273
    def create_workingtree(self, revision_id=None, from_branch=None):
272
274
        raise errors.NotLocalUrl(self.transport.base)
273
275
 
274
 
    def find_branch_format(self):
 
276
    def find_branch_format(self, name=None):
275
277
        """Find the branch 'format' for this bzrdir.
276
278
 
277
279
        This might be a synthetic object for e.g. RemoteBranch and SVN.
278
280
        """
279
 
        b = self.open_branch()
 
281
        b = self.open_branch(name=name)
280
282
        return b._format
281
283
 
282
 
    def get_branch_reference(self):
 
284
    def get_branch_reference(self, name=None):
283
285
        """See BzrDir.get_branch_reference()."""
 
286
        if name is not None:
 
287
            # XXX JRV20100304: Support opening colocated branches
 
288
            raise errors.NoColocatedBranchSupport(self)
284
289
        response = self._get_branch_reference()
285
290
        if response[0] == 'ref':
286
291
            return response[1]
317
322
            raise errors.UnexpectedSmartServerResponse(response)
318
323
        return response
319
324
 
320
 
    def _get_tree_branch(self):
 
325
    def _get_tree_branch(self, name=None):
321
326
        """See BzrDir._get_tree_branch()."""
322
 
        return None, self.open_branch()
 
327
        return None, self.open_branch(name=name)
323
328
 
324
329
    def open_branch(self, name=None, unsupported=False,
325
330
                    ignore_fallbacks=False):
642
647
        return self._custom_format._serializer
643
648
 
644
649
 
645
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):
 
650
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
 
651
    bzrdir.ControlComponent):
646
652
    """Repository accessed over rpc.
647
653
 
648
654
    For the moment most operations are performed using local transport-backed
691
697
        # Additional places to query for data.
692
698
        self._fallback_repositories = []
693
699
 
 
700
    @property
 
701
    def user_transport(self):
 
702
        return self.bzrdir.user_transport
 
703
 
 
704
    @property
 
705
    def control_transport(self):
 
706
        # XXX: Normally you shouldn't directly get at the remote repository
 
707
        # transport, but I'm not sure it's worth making this method
 
708
        # optional -- mbp 2010-04-21
 
709
        return self.bzrdir.get_repository_transport(None)
 
710
        
694
711
    def __str__(self):
695
712
        return "%s(%s)" % (self.__class__.__name__, self.base)
696
713
 
984
1001
        pass
985
1002
 
986
1003
    def lock_read(self):
 
1004
        """Lock the repository for read operations.
 
1005
 
 
1006
        :return: A bzrlib.lock.LogicalLockResult.
 
1007
        """
987
1008
        # wrong eventually - want a local lock cache context
988
1009
        if not self._lock_mode:
989
1010
            self._note_lock('r')
996
1017
                repo.lock_read()
997
1018
        else:
998
1019
            self._lock_count += 1
 
1020
        return lock.LogicalLockResult(self.unlock)
999
1021
 
1000
1022
    def _remote_lock_write(self, token):
1001
1023
        path = self.bzrdir._path_for_remote_call(self._client)
1041
1063
            raise errors.ReadOnlyError(self)
1042
1064
        else:
1043
1065
            self._lock_count += 1
1044
 
        return self._lock_token or None
 
1066
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
1045
1067
 
1046
1068
    def leave_lock_in_place(self):
1047
1069
        if not self._lock_token:
1227
1249
            # state, so always add a lock here. If a caller passes us a locked
1228
1250
            # repository, they are responsible for unlocking it later.
1229
1251
            repository.lock_read()
 
1252
        self._check_fallback_repository(repository)
1230
1253
        self._fallback_repositories.append(repository)
1231
1254
        # If self._real_repository was parameterised already (e.g. because a
1232
1255
        # _real_branch had its get_stacked_on_url method called), then the
1233
1256
        # repository to be added may already be in the _real_repositories list.
1234
1257
        if self._real_repository is not None:
1235
 
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
 
1258
            fallback_locations = [repo.user_url for repo in
1236
1259
                self._real_repository._fallback_repositories]
1237
 
            if repository.bzrdir.root_transport.base not in fallback_locations:
 
1260
            if repository.user_url not in fallback_locations:
1238
1261
                self._real_repository.add_fallback_repository(repository)
1239
1262
 
 
1263
    def _check_fallback_repository(self, repository):
 
1264
        """Check that this repository can fallback to repository safely.
 
1265
 
 
1266
        Raise an error if not.
 
1267
 
 
1268
        :param repository: A repository to fallback to.
 
1269
        """
 
1270
        return _mod_repository.InterRepository._assert_same_model(
 
1271
            self, repository)
 
1272
 
1240
1273
    def add_inventory(self, revid, inv, parents):
1241
1274
        self._ensure_real()
1242
1275
        return self._real_repository.add_inventory(revid, inv, parents)
1282
1315
        return self._real_repository.make_working_trees()
1283
1316
 
1284
1317
    def refresh_data(self):
1285
 
        """Re-read any data needed to to synchronise with disk.
 
1318
        """Re-read any data needed to synchronise with disk.
1286
1319
 
1287
1320
        This method is intended to be called after another repository instance
1288
1321
        (such as one used by a smart server) has inserted data into the
1289
 
        repository. It may not be called during a write group, but may be
1290
 
        called at any other time.
 
1322
        repository. On all repositories this will work outside of write groups.
 
1323
        Some repository formats (pack and newer for bzrlib native formats)
 
1324
        support refresh_data inside write groups. If called inside a write
 
1325
        group on a repository that does not support refreshing in a write group
 
1326
        IsInWriteGroupError will be raised.
1291
1327
        """
1292
 
        if self.is_in_write_group():
1293
 
            raise errors.InternalBzrError(
1294
 
                "May not refresh_data while in a write group.")
1295
1328
        if self._real_repository is not None:
1296
1329
            self._real_repository.refresh_data()
1297
1330
 
1595
1628
        return self._real_repository.inventories
1596
1629
 
1597
1630
    @needs_write_lock
1598
 
    def pack(self, hint=None):
 
1631
    def pack(self, hint=None, clean_obsolete_packs=False):
1599
1632
        """Compress the data within the repository.
1600
1633
 
1601
1634
        This is not currently implemented within the smart server.
1602
1635
        """
1603
1636
        self._ensure_real()
1604
 
        return self._real_repository.pack(hint=hint)
 
1637
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
1605
1638
 
1606
1639
    @property
1607
1640
    def revisions(self):
2169
2202
            self._real_branch = None
2170
2203
        # Fill out expected attributes of branch for bzrlib API users.
2171
2204
        self._clear_cached_state()
2172
 
        self.base = self.bzrdir.root_transport.base
 
2205
        # TODO: deprecate self.base in favor of user_url
 
2206
        self.base = self.bzrdir.user_url
2173
2207
        self._name = name
2174
2208
        self._control_files = None
2175
2209
        self._lock_mode = None
2362
2396
            self._vfs_set_tags_bytes(bytes)
2363
2397
 
2364
2398
    def lock_read(self):
 
2399
        """Lock the branch for read operations.
 
2400
 
 
2401
        :return: A bzrlib.lock.LogicalLockResult.
 
2402
        """
2365
2403
        self.repository.lock_read()
2366
2404
        if not self._lock_mode:
2367
2405
            self._note_lock('r')
2371
2409
                self._real_branch.lock_read()
2372
2410
        else:
2373
2411
            self._lock_count += 1
 
2412
        return lock.LogicalLockResult(self.unlock)
2374
2413
 
2375
2414
    def _remote_lock_write(self, token):
2376
2415
        if token is None:
2377
2416
            branch_token = repo_token = ''
2378
2417
        else:
2379
2418
            branch_token = token
2380
 
            repo_token = self.repository.lock_write()
 
2419
            repo_token = self.repository.lock_write().repository_token
2381
2420
            self.repository.unlock()
2382
2421
        err_context = {'token': token}
2383
2422
        response = self._call(
2420
2459
            self._lock_count += 1
2421
2460
            # Re-lock the repository too.
2422
2461
            self.repository.lock_write(self._repo_lock_token)
2423
 
        return self._lock_token or None
 
2462
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
2424
2463
 
2425
2464
    def _unlock(self, branch_token, repo_token):
2426
2465
        err_context = {'token': str((branch_token, repo_token))}
2749
2788
        medium = self._branch._client._medium
2750
2789
        if medium._is_remote_before((1, 14)):
2751
2790
            return self._vfs_set_option(value, name, section)
 
2791
        if isinstance(value, dict):
 
2792
            if medium._is_remote_before((2, 2)):
 
2793
                return self._vfs_set_option(value, name, section)
 
2794
            return self._set_config_option_dict(value, name, section)
 
2795
        else:
 
2796
            return self._set_config_option(value, name, section)
 
2797
 
 
2798
    def _set_config_option(self, value, name, section):
2752
2799
        try:
2753
2800
            path = self._branch._remote_path()
2754
2801
            response = self._branch._client.call('Branch.set_config_option',
2755
2802
                path, self._branch._lock_token, self._branch._repo_lock_token,
2756
2803
                value.encode('utf8'), name, section or '')
2757
2804
        except errors.UnknownSmartMethod:
 
2805
            medium = self._branch._client._medium
2758
2806
            medium._remember_remote_is_before((1, 14))
2759
2807
            return self._vfs_set_option(value, name, section)
2760
2808
        if response != ():
2761
2809
            raise errors.UnexpectedSmartServerResponse(response)
2762
2810
 
 
2811
    def _serialize_option_dict(self, option_dict):
 
2812
        utf8_dict = {}
 
2813
        for key, value in option_dict.items():
 
2814
            if isinstance(key, unicode):
 
2815
                key = key.encode('utf8')
 
2816
            if isinstance(value, unicode):
 
2817
                value = value.encode('utf8')
 
2818
            utf8_dict[key] = value
 
2819
        return bencode.bencode(utf8_dict)
 
2820
 
 
2821
    def _set_config_option_dict(self, value, name, section):
 
2822
        try:
 
2823
            path = self._branch._remote_path()
 
2824
            serialised_dict = self._serialize_option_dict(value)
 
2825
            response = self._branch._client.call(
 
2826
                'Branch.set_config_option_dict',
 
2827
                path, self._branch._lock_token, self._branch._repo_lock_token,
 
2828
                serialised_dict, name, section or '')
 
2829
        except errors.UnknownSmartMethod:
 
2830
            medium = self._branch._client._medium
 
2831
            medium._remember_remote_is_before((2, 2))
 
2832
            return self._vfs_set_option(value, name, section)
 
2833
        if response != ():
 
2834
            raise errors.UnexpectedSmartServerResponse(response)
 
2835
 
2763
2836
    def _real_object(self):
2764
2837
        self._branch._ensure_real()
2765
2838
        return self._branch._real_branch