/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: Vincent Ladeuil
  • Date: 2009-09-07 08:46:00 UTC
  • mto: (4677.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4678.
  • Revision ID: v.ladeuil+lp@free.fr-20090907084600-g2gheboken7azq5y
FreeBSD and OSX create temp dirs with the 'wheel' group.

* bzrlib/tests/test_permissions.py:
(TestPermissions.test_new_files_group_sticky_bit): Same cause,
same fix.

* bzrlib/tests/per_branch/test_permissions.py:
(TestPermissions.test_new_branch_group_sticky_bit): Same cause,
same fix.

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
27
27
    lock,
28
28
    lockdir,
29
29
    repository,
30
 
    repository as _mod_repository,
31
30
    revision,
32
31
    revision as _mod_revision,
33
 
    static_tuple,
34
32
    symbol_versioning,
35
33
)
36
 
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
 
34
from bzrlib.branch import BranchReferenceFormat
37
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
 
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
 
36
from bzrlib.decorators import needs_read_lock, needs_write_lock
39
37
from bzrlib.errors import (
40
38
    NoSuchRevision,
41
39
    SmartProtocolError,
43
41
from bzrlib.lockable_files import LockableFiles
44
42
from bzrlib.smart import client, vfs, repository as smart_repo
45
43
from bzrlib.revision import ensure_null, NULL_REVISION
46
 
from bzrlib.repository import RepositoryWriteLockResult
47
44
from bzrlib.trace import mutter, note, warning
48
45
 
49
46
 
92
89
class RemoteBzrDir(BzrDir, _RpcHelper):
93
90
    """Control directory on a remote server, accessed via bzr:// or similar."""
94
91
 
95
 
    def __init__(self, transport, format, _client=None, _force_probe=False):
 
92
    def __init__(self, transport, format, _client=None):
96
93
        """Construct a RemoteBzrDir.
97
94
 
98
95
        :param _client: Private parameter for testing. Disables probing and the
102
99
        # this object holds a delegated bzrdir that uses file-level operations
103
100
        # to talk to the other side
104
101
        self._real_bzrdir = None
105
 
        self._has_working_tree = None
106
102
        # 1-shot cache for the call pattern 'create_branch; open_branch' - see
107
103
        # create_branch for details.
108
104
        self._next_open_branch_result = None
112
108
            self._client = client._SmartClient(medium)
113
109
        else:
114
110
            self._client = _client
115
 
            if not _force_probe:
116
 
                return
117
 
 
118
 
        self._probe_bzrdir()
119
 
 
120
 
    def __repr__(self):
121
 
        return '%s(%r)' % (self.__class__.__name__, self._client)
122
 
 
123
 
    def _probe_bzrdir(self):
124
 
        medium = self._client._medium
 
111
            return
 
112
 
125
113
        path = self._path_for_remote_call(self._client)
126
 
        if medium._is_remote_before((2, 1)):
127
 
            self._rpc_open(path)
128
 
            return
129
 
        try:
130
 
            self._rpc_open_2_1(path)
131
 
            return
132
 
        except errors.UnknownSmartMethod:
133
 
            medium._remember_remote_is_before((2, 1))
134
 
            self._rpc_open(path)
135
 
 
136
 
    def _rpc_open_2_1(self, path):
137
 
        response = self._call('BzrDir.open_2.1', path)
138
 
        if response == ('no',):
139
 
            raise errors.NotBranchError(path=self.root_transport.base)
140
 
        elif response[0] == 'yes':
141
 
            if response[1] == 'yes':
142
 
                self._has_working_tree = True
143
 
            elif response[1] == 'no':
144
 
                self._has_working_tree = False
145
 
            else:
146
 
                raise errors.UnexpectedSmartServerResponse(response)
147
 
        else:
148
 
            raise errors.UnexpectedSmartServerResponse(response)
149
 
 
150
 
    def _rpc_open(self, path):
151
114
        response = self._call('BzrDir.open', path)
152
115
        if response not in [('yes',), ('no',)]:
153
116
            raise errors.UnexpectedSmartServerResponse(response)
154
117
        if response == ('no',):
155
 
            raise errors.NotBranchError(path=self.root_transport.base)
 
118
            raise errors.NotBranchError(path=transport.base)
156
119
 
157
120
    def _ensure_real(self):
158
121
        """Ensure that there is a _real_bzrdir set.
160
123
        Used before calls to self._real_bzrdir.
161
124
        """
162
125
        if not self._real_bzrdir:
163
 
            if 'hpssvfs' in debug.debug_flags:
164
 
                import traceback
165
 
                warning('VFS BzrDir access triggered\n%s',
166
 
                    ''.join(traceback.format_stack()))
167
126
            self._real_bzrdir = BzrDir.open_from_transport(
168
127
                self.root_transport, _server_formats=False)
169
128
            self._format._network_name = \
245
204
        self._ensure_real()
246
205
        self._real_bzrdir.destroy_repository()
247
206
 
248
 
    def create_branch(self, name=None):
 
207
    def create_branch(self):
249
208
        # as per meta1 formats - just delegate to the format object which may
250
209
        # be parameterised.
251
 
        real_branch = self._format.get_branch_format().initialize(self,
252
 
            name=name)
 
210
        real_branch = self._format.get_branch_format().initialize(self)
253
211
        if not isinstance(real_branch, RemoteBranch):
254
 
            result = RemoteBranch(self, self.find_repository(), real_branch,
255
 
                                  name=name)
 
212
            result = RemoteBranch(self, self.find_repository(), real_branch)
256
213
        else:
257
214
            result = real_branch
258
215
        # BzrDir.clone_on_transport() uses the result of create_branch but does
264
221
        self._next_open_branch_result = result
265
222
        return result
266
223
 
267
 
    def destroy_branch(self, name=None):
 
224
    def destroy_branch(self):
268
225
        """See BzrDir.destroy_branch"""
269
226
        self._ensure_real()
270
 
        self._real_bzrdir.destroy_branch(name=name)
 
227
        self._real_bzrdir.destroy_branch()
271
228
        self._next_open_branch_result = None
272
229
 
273
230
    def create_workingtree(self, revision_id=None, from_branch=None):
274
231
        raise errors.NotLocalUrl(self.transport.base)
275
232
 
276
 
    def find_branch_format(self, name=None):
 
233
    def find_branch_format(self):
277
234
        """Find the branch 'format' for this bzrdir.
278
235
 
279
236
        This might be a synthetic object for e.g. RemoteBranch and SVN.
280
237
        """
281
 
        b = self.open_branch(name=name)
 
238
        b = self.open_branch()
282
239
        return b._format
283
240
 
284
 
    def get_branch_reference(self, name=None):
 
241
    def get_branch_reference(self):
285
242
        """See BzrDir.get_branch_reference()."""
286
 
        if name is not None:
287
 
            # XXX JRV20100304: Support opening colocated branches
288
 
            raise errors.NoColocatedBranchSupport(self)
289
243
        response = self._get_branch_reference()
290
244
        if response[0] == 'ref':
291
245
            return response[1]
295
249
    def _get_branch_reference(self):
296
250
        path = self._path_for_remote_call(self._client)
297
251
        medium = self._client._medium
298
 
        candidate_calls = [
299
 
            ('BzrDir.open_branchV3', (2, 1)),
300
 
            ('BzrDir.open_branchV2', (1, 13)),
301
 
            ('BzrDir.open_branch', None),
302
 
            ]
303
 
        for verb, required_version in candidate_calls:
304
 
            if required_version and medium._is_remote_before(required_version):
305
 
                continue
 
252
        if not medium._is_remote_before((1, 13)):
306
253
            try:
307
 
                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
308
258
            except errors.UnknownSmartMethod:
309
 
                if required_version is None:
310
 
                    raise
311
 
                medium._remember_remote_is_before(required_version)
312
 
            else:
313
 
                break
314
 
        if verb == 'BzrDir.open_branch':
315
 
            if response[0] != 'ok':
316
 
                raise errors.UnexpectedSmartServerResponse(response)
317
 
            if response[1] != '':
318
 
                return ('ref', response[1])
319
 
            else:
320
 
                return ('branch', '')
321
 
        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':
322
262
            raise errors.UnexpectedSmartServerResponse(response)
323
 
        return response
 
263
        if response[1] != '':
 
264
            return ('ref', response[1])
 
265
        else:
 
266
            return ('branch', '')
324
267
 
325
 
    def _get_tree_branch(self, name=None):
 
268
    def _get_tree_branch(self):
326
269
        """See BzrDir._get_tree_branch()."""
327
 
        return None, self.open_branch(name=name)
 
270
        return None, self.open_branch()
328
271
 
329
 
    def open_branch(self, name=None, unsupported=False,
330
 
                    ignore_fallbacks=False):
331
 
        if unsupported:
 
272
    def open_branch(self, _unsupported=False, ignore_fallbacks=False):
 
273
        if _unsupported:
332
274
            raise NotImplementedError('unsupported flag support not implemented yet.')
333
275
        if self._next_open_branch_result is not None:
334
276
            # See create_branch for details.
339
281
        if response[0] == 'ref':
340
282
            # a branch reference, use the existing BranchReference logic.
341
283
            format = BranchReferenceFormat()
342
 
            return format.open(self, name=name, _found=True,
343
 
                location=response[1], ignore_fallbacks=ignore_fallbacks)
 
284
            return format.open(self, _found=True, location=response[1],
 
285
                ignore_fallbacks=ignore_fallbacks)
344
286
        branch_format_name = response[1]
345
287
        if not branch_format_name:
346
288
            branch_format_name = None
347
289
        format = RemoteBranchFormat(network_name=branch_format_name)
348
290
        return RemoteBranch(self, self.find_repository(), format=format,
349
 
            setup_stacking=not ignore_fallbacks, name=name)
 
291
            setup_stacking=not ignore_fallbacks)
350
292
 
351
293
    def _open_repo_v1(self, path):
352
294
        verb = 'BzrDir.find_repository'
413
355
        else:
414
356
            raise errors.NoRepositoryPresent(self)
415
357
 
416
 
    def has_workingtree(self):
417
 
        if self._has_working_tree is None:
418
 
            self._ensure_real()
419
 
            self._has_working_tree = self._real_bzrdir.has_workingtree()
420
 
        return self._has_working_tree
421
 
 
422
358
    def open_workingtree(self, recommend_upgrade=True):
423
 
        if self.has_workingtree():
 
359
        self._ensure_real()
 
360
        if self._real_bzrdir.has_workingtree():
424
361
            raise errors.NotLocalUrl(self.root_transport)
425
362
        else:
426
363
            raise errors.NoWorkingTree(self.root_transport.base)
429
366
        """Return the path to be used for this bzrdir in a remote call."""
430
367
        return client.remote_path_from_transport(self.root_transport)
431
368
 
432
 
    def get_branch_transport(self, branch_format, name=None):
 
369
    def get_branch_transport(self, branch_format):
433
370
        self._ensure_real()
434
 
        return self._real_bzrdir.get_branch_transport(branch_format, name=name)
 
371
        return self._real_bzrdir.get_branch_transport(branch_format)
435
372
 
436
373
    def get_repository_transport(self, repository_format):
437
374
        self._ensure_real()
624
561
        return self._custom_format._fetch_reconcile
625
562
 
626
563
    def get_format_description(self):
627
 
        self._ensure_real()
628
 
        return 'Remote: ' + self._custom_format.get_format_description()
 
564
        return 'bzr remote repository'
629
565
 
630
566
    def __eq__(self, other):
631
567
        return self.__class__ is other.__class__
647
583
        return self._custom_format._serializer
648
584
 
649
585
 
650
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
651
 
    bzrdir.ControlComponent):
 
586
class RemoteRepository(_RpcHelper):
652
587
    """Repository accessed over rpc.
653
588
 
654
589
    For the moment most operations are performed using local transport-backed
697
632
        # Additional places to query for data.
698
633
        self._fallback_repositories = []
699
634
 
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
 
        
711
635
    def __str__(self):
712
636
        return "%s(%s)" % (self.__class__.__name__, self.base)
713
637
 
921
845
        parents_provider = self._make_parents_provider(other_repository)
922
846
        return graph.Graph(parents_provider)
923
847
 
924
 
    @needs_read_lock
925
 
    def get_known_graph_ancestry(self, revision_ids):
926
 
        """Return the known graph for a set of revision ids and their ancestors.
927
 
        """
928
 
        st = static_tuple.StaticTuple
929
 
        revision_keys = [st(r_id).intern() for r_id in revision_ids]
930
 
        known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
931
 
        return graph.GraphThunkIdsToKeys(known_graph)
932
 
 
933
848
    def gather_stats(self, revid=None, committers=None):
934
849
        """See Repository.gather_stats()."""
935
850
        path = self.bzrdir._path_for_remote_call(self._client)
995
910
    def is_write_locked(self):
996
911
        return self._lock_mode == 'w'
997
912
 
998
 
    def _warn_if_deprecated(self, branch=None):
999
 
        # If we have a real repository, the check will be done there, if we
1000
 
        # don't the check will be done remotely.
1001
 
        pass
1002
 
 
1003
913
    def lock_read(self):
1004
 
        """Lock the repository for read operations.
1005
 
 
1006
 
        :return: A bzrlib.lock.LogicalLockResult.
1007
 
        """
1008
914
        # wrong eventually - want a local lock cache context
1009
915
        if not self._lock_mode:
1010
 
            self._note_lock('r')
1011
916
            self._lock_mode = 'r'
1012
917
            self._lock_count = 1
1013
918
            self._unstacked_provider.enable_cache(cache_misses=True)
1017
922
                repo.lock_read()
1018
923
        else:
1019
924
            self._lock_count += 1
1020
 
        return lock.LogicalLockResult(self.unlock)
1021
925
 
1022
926
    def _remote_lock_write(self, token):
1023
927
        path = self.bzrdir._path_for_remote_call(self._client)
1034
938
 
1035
939
    def lock_write(self, token=None, _skip_rpc=False):
1036
940
        if not self._lock_mode:
1037
 
            self._note_lock('w')
1038
941
            if _skip_rpc:
1039
942
                if self._lock_token is not None:
1040
943
                    if token != self._lock_token:
1063
966
            raise errors.ReadOnlyError(self)
1064
967
        else:
1065
968
            self._lock_count += 1
1066
 
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
 
969
        return self._lock_token or None
1067
970
 
1068
971
    def leave_lock_in_place(self):
1069
972
        if not self._lock_token:
1143
1046
        else:
1144
1047
            raise errors.UnexpectedSmartServerResponse(response)
1145
1048
 
1146
 
    @only_raises(errors.LockNotHeld, errors.LockBroken)
1147
1049
    def unlock(self):
1148
1050
        if not self._lock_count:
1149
1051
            return lock.cant_unlock_not_held(self)
1249
1151
            # state, so always add a lock here. If a caller passes us a locked
1250
1152
            # repository, they are responsible for unlocking it later.
1251
1153
            repository.lock_read()
1252
 
        self._check_fallback_repository(repository)
1253
1154
        self._fallback_repositories.append(repository)
1254
1155
        # If self._real_repository was parameterised already (e.g. because a
1255
1156
        # _real_branch had its get_stacked_on_url method called), then the
1256
1157
        # repository to be added may already be in the _real_repositories list.
1257
1158
        if self._real_repository is not None:
1258
 
            fallback_locations = [repo.user_url for repo in
 
1159
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
1259
1160
                self._real_repository._fallback_repositories]
1260
 
            if repository.user_url not in fallback_locations:
 
1161
            if repository.bzrdir.root_transport.base not in fallback_locations:
1261
1162
                self._real_repository.add_fallback_repository(repository)
1262
1163
 
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
 
 
1273
1164
    def add_inventory(self, revid, inv, parents):
1274
1165
        self._ensure_real()
1275
1166
        return self._real_repository.add_inventory(revid, inv, parents)
1276
1167
 
1277
1168
    def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1278
 
            parents, basis_inv=None, propagate_caches=False):
 
1169
                               parents):
1279
1170
        self._ensure_real()
1280
1171
        return self._real_repository.add_inventory_by_delta(basis_revision_id,
1281
 
            delta, new_revision_id, parents, basis_inv=basis_inv,
1282
 
            propagate_caches=propagate_caches)
 
1172
            delta, new_revision_id, parents)
1283
1173
 
1284
1174
    def add_revision(self, rev_id, rev, inv=None, config=None):
1285
1175
        self._ensure_real()
1315
1205
        return self._real_repository.make_working_trees()
1316
1206
 
1317
1207
    def refresh_data(self):
1318
 
        """Re-read any data needed to synchronise with disk.
 
1208
        """Re-read any data needed to to synchronise with disk.
1319
1209
 
1320
1210
        This method is intended to be called after another repository instance
1321
1211
        (such as one used by a smart server) has inserted data into the
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.
 
1212
        repository. It may not be called during a write group, but may be
 
1213
        called at any other time.
1327
1214
        """
 
1215
        if self.is_in_write_group():
 
1216
            raise errors.InternalBzrError(
 
1217
                "May not refresh_data while in a write group.")
1328
1218
        if self._real_repository is not None:
1329
1219
            self._real_repository.refresh_data()
1330
1220
 
1544
1434
        return self._real_repository.get_signature_text(revision_id)
1545
1435
 
1546
1436
    @needs_read_lock
1547
 
    def _get_inventory_xml(self, revision_id):
1548
 
        self._ensure_real()
1549
 
        return self._real_repository._get_inventory_xml(revision_id)
 
1437
    def get_inventory_xml(self, revision_id):
 
1438
        self._ensure_real()
 
1439
        return self._real_repository.get_inventory_xml(revision_id)
 
1440
 
 
1441
    def deserialise_inventory(self, revision_id, xml):
 
1442
        self._ensure_real()
 
1443
        return self._real_repository.deserialise_inventory(revision_id, xml)
1550
1444
 
1551
1445
    def reconcile(self, other=None, thorough=False):
1552
1446
        self._ensure_real()
1628
1522
        return self._real_repository.inventories
1629
1523
 
1630
1524
    @needs_write_lock
1631
 
    def pack(self, hint=None, clean_obsolete_packs=False):
 
1525
    def pack(self, hint=None):
1632
1526
        """Compress the data within the repository.
1633
1527
 
1634
1528
        This is not currently implemented within the smart server.
1635
1529
        """
1636
1530
        self._ensure_real()
1637
 
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
 
1531
        return self._real_repository.pack(hint=hint)
1638
1532
 
1639
1533
    @property
1640
1534
    def revisions(self):
1845
1739
            # The stream included an inventory-delta record, but the remote
1846
1740
            # side isn't new enough to support them.  So we need to send the
1847
1741
            # rest of the stream via VFS.
1848
 
            self.target_repo.refresh_data()
1849
1742
            return self._resume_stream_with_vfs(response, src_format)
1850
1743
        if response[0][0] == 'missing-basis':
1851
1744
            tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1993
1886
        :param search: The overall search to satisfy with streams.
1994
1887
        :param sources: A list of Repository objects to query.
1995
1888
        """
1996
 
        self.from_serialiser = self.from_repository._format._serializer
 
1889
        self.serialiser = self.to_format._serializer
1997
1890
        self.seen_revs = set()
1998
1891
        self.referenced_revs = set()
1999
1892
        # If there are heads in the search, or the key count is > 0, we are not
2016
1909
    def missing_parents_rev_handler(self, substream):
2017
1910
        for content in substream:
2018
1911
            revision_bytes = content.get_bytes_as('fulltext')
2019
 
            revision = self.from_serialiser.read_revision_from_string(
2020
 
                revision_bytes)
 
1912
            revision = self.serialiser.read_revision_from_string(revision_bytes)
2021
1913
            self.seen_revs.add(content.key[-1])
2022
1914
            self.referenced_revs.update(revision.parent_ids)
2023
1915
            yield content
2062
1954
                self._network_name)
2063
1955
 
2064
1956
    def get_format_description(self):
2065
 
        self._ensure_real()
2066
 
        return 'Remote: ' + self._custom_format.get_format_description()
 
1957
        return 'Remote BZR Branch'
2067
1958
 
2068
1959
    def network_name(self):
2069
1960
        return self._network_name
2070
1961
 
2071
 
    def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2072
 
        return a_bzrdir.open_branch(name=name, 
2073
 
            ignore_fallbacks=ignore_fallbacks)
 
1962
    def open(self, a_bzrdir, ignore_fallbacks=False):
 
1963
        return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2074
1964
 
2075
 
    def _vfs_initialize(self, a_bzrdir, name):
 
1965
    def _vfs_initialize(self, a_bzrdir):
2076
1966
        # Initialisation when using a local bzrdir object, or a non-vfs init
2077
1967
        # method is not available on the server.
2078
1968
        # self._custom_format is always set - the start of initialize ensures
2079
1969
        # that.
2080
1970
        if isinstance(a_bzrdir, RemoteBzrDir):
2081
1971
            a_bzrdir._ensure_real()
2082
 
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2083
 
                name)
 
1972
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2084
1973
        else:
2085
1974
            # We assume the bzrdir is parameterised; it may not be.
2086
 
            result = self._custom_format.initialize(a_bzrdir, name)
 
1975
            result = self._custom_format.initialize(a_bzrdir)
2087
1976
        if (isinstance(a_bzrdir, RemoteBzrDir) and
2088
1977
            not isinstance(result, RemoteBranch)):
2089
 
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2090
 
                                  name=name)
 
1978
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2091
1979
        return result
2092
1980
 
2093
 
    def initialize(self, a_bzrdir, name=None):
 
1981
    def initialize(self, a_bzrdir):
2094
1982
        # 1) get the network name to use.
2095
1983
        if self._custom_format:
2096
1984
            network_name = self._custom_format.network_name()
2102
1990
            network_name = reference_format.network_name()
2103
1991
        # Being asked to create on a non RemoteBzrDir:
2104
1992
        if not isinstance(a_bzrdir, RemoteBzrDir):
2105
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
1993
            return self._vfs_initialize(a_bzrdir)
2106
1994
        medium = a_bzrdir._client._medium
2107
1995
        if medium._is_remote_before((1, 13)):
2108
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
1996
            return self._vfs_initialize(a_bzrdir)
2109
1997
        # Creating on a remote bzr dir.
2110
1998
        # 2) try direct creation via RPC
2111
1999
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2112
 
        if name is not None:
2113
 
            # XXX JRV20100304: Support creating colocated branches
2114
 
            raise errors.NoColocatedBranchSupport(self)
2115
2000
        verb = 'BzrDir.create_branch'
2116
2001
        try:
2117
2002
            response = a_bzrdir._call(verb, path, network_name)
2118
2003
        except errors.UnknownSmartMethod:
2119
2004
            # Fallback - use vfs methods
2120
2005
            medium._remember_remote_is_before((1, 13))
2121
 
            return self._vfs_initialize(a_bzrdir, name=name)
 
2006
            return self._vfs_initialize(a_bzrdir)
2122
2007
        if response[0] != 'ok':
2123
2008
            raise errors.UnexpectedSmartServerResponse(response)
2124
2009
        # Turn the response into a RemoteRepository object.
2132
2017
                a_bzrdir._client)
2133
2018
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2134
2019
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2135
 
            format=format, setup_stacking=False, name=name)
 
2020
            format=format, setup_stacking=False)
2136
2021
        # XXX: We know this is a new branch, so it must have revno 0, revid
2137
2022
        # NULL_REVISION. Creating the branch locked would make this be unable
2138
2023
        # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2158
2043
        return self._custom_format.supports_set_append_revisions_only()
2159
2044
 
2160
2045
 
2161
 
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
 
2046
class RemoteBranch(branch.Branch, _RpcHelper):
2162
2047
    """Branch stored on a server accessed by HPSS RPC.
2163
2048
 
2164
2049
    At the moment most operations are mapped down to simple file operations.
2165
2050
    """
2166
2051
 
2167
2052
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2168
 
        _client=None, format=None, setup_stacking=True, name=None):
 
2053
        _client=None, format=None, setup_stacking=True):
2169
2054
        """Create a RemoteBranch instance.
2170
2055
 
2171
2056
        :param real_branch: An optional local implementation of the branch
2177
2062
        :param setup_stacking: If True make an RPC call to determine the
2178
2063
            stacked (or not) status of the branch. If False assume the branch
2179
2064
            is not stacked.
2180
 
        :param name: Colocated branch name
2181
2065
        """
2182
2066
        # We intentionally don't call the parent class's __init__, because it
2183
2067
        # will try to assign to self.tags, which is a property in this subclass.
2202
2086
            self._real_branch = None
2203
2087
        # Fill out expected attributes of branch for bzrlib API users.
2204
2088
        self._clear_cached_state()
2205
 
        # TODO: deprecate self.base in favor of user_url
2206
 
        self.base = self.bzrdir.user_url
2207
 
        self._name = name
 
2089
        self.base = self.bzrdir.root_transport.base
2208
2090
        self._control_files = None
2209
2091
        self._lock_mode = None
2210
2092
        self._lock_token = None
2275
2157
                    'to use vfs implementation')
2276
2158
            self.bzrdir._ensure_real()
2277
2159
            self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2278
 
                ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
 
2160
                ignore_fallbacks=self._real_ignore_fallbacks)
2279
2161
            if self.repository._real_repository is None:
2280
2162
                # Give the remote repository the matching real repo.
2281
2163
                real_repo = self._real_branch.repository
2385
2267
        medium = self._client._medium
2386
2268
        if medium._is_remote_before((1, 18)):
2387
2269
            self._vfs_set_tags_bytes(bytes)
2388
 
            return
2389
2270
        try:
2390
2271
            args = (
2391
2272
                self._remote_path(), self._lock_token, self._repo_lock_token)
2396
2277
            self._vfs_set_tags_bytes(bytes)
2397
2278
 
2398
2279
    def lock_read(self):
2399
 
        """Lock the branch for read operations.
2400
 
 
2401
 
        :return: A bzrlib.lock.LogicalLockResult.
2402
 
        """
2403
2280
        self.repository.lock_read()
2404
2281
        if not self._lock_mode:
2405
 
            self._note_lock('r')
2406
2282
            self._lock_mode = 'r'
2407
2283
            self._lock_count = 1
2408
2284
            if self._real_branch is not None:
2409
2285
                self._real_branch.lock_read()
2410
2286
        else:
2411
2287
            self._lock_count += 1
2412
 
        return lock.LogicalLockResult(self.unlock)
2413
2288
 
2414
2289
    def _remote_lock_write(self, token):
2415
2290
        if token is None:
2416
2291
            branch_token = repo_token = ''
2417
2292
        else:
2418
2293
            branch_token = token
2419
 
            repo_token = self.repository.lock_write().repository_token
 
2294
            repo_token = self.repository.lock_write()
2420
2295
            self.repository.unlock()
2421
2296
        err_context = {'token': token}
2422
2297
        response = self._call(
2429
2304
 
2430
2305
    def lock_write(self, token=None):
2431
2306
        if not self._lock_mode:
2432
 
            self._note_lock('w')
2433
2307
            # Lock the branch and repo in one remote call.
2434
2308
            remote_tokens = self._remote_lock_write(token)
2435
2309
            self._lock_token, self._repo_lock_token = remote_tokens
2459
2333
            self._lock_count += 1
2460
2334
            # Re-lock the repository too.
2461
2335
            self.repository.lock_write(self._repo_lock_token)
2462
 
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
 
2336
        return self._lock_token or None
2463
2337
 
2464
2338
    def _unlock(self, branch_token, repo_token):
2465
2339
        err_context = {'token': str((branch_token, repo_token))}
2470
2344
            return
2471
2345
        raise errors.UnexpectedSmartServerResponse(response)
2472
2346
 
2473
 
    @only_raises(errors.LockNotHeld, errors.LockBroken)
2474
2347
    def unlock(self):
2475
2348
        try:
2476
2349
            self._lock_count -= 1
2516
2389
            raise NotImplementedError(self.dont_leave_lock_in_place)
2517
2390
        self._leave_lock = False
2518
2391
 
2519
 
    @needs_read_lock
2520
2392
    def get_rev_id(self, revno, history=None):
2521
2393
        if revno == 0:
2522
2394
            return _mod_revision.NULL_REVISION
2894
2766
        raise NoSuchRevision(find('branch'), err.error_args[0])
2895
2767
    elif err.error_verb == 'nosuchrevision':
2896
2768
        raise NoSuchRevision(find('repository'), err.error_args[0])
2897
 
    elif err.error_verb == 'nobranch':
2898
 
        if len(err.error_args) >= 1:
2899
 
            extra = err.error_args[0]
2900
 
        else:
2901
 
            extra = None
2902
 
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
2903
 
            detail=extra)
 
2769
    elif err.error_tuple == ('nobranch',):
 
2770
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
2904
2771
    elif err.error_verb == 'norepository':
2905
2772
        raise errors.NoRepositoryPresent(find('bzrdir'))
2906
2773
    elif err.error_verb == 'LockContention':