~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-12-09 02:53:42 UTC
  • mfrom: (4873.2.3 2.1.0b4-win32-test-imports)
  • Revision ID: pqm@pqm.ubuntu.com-20091209025342-sidvxfcqdgxmuz59
(jam) Get the test suite running again on Windows, (bug #492561)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 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
19
19
from bzrlib import (
20
20
    bencode,
21
21
    branch,
22
 
    bzrdir as _mod_bzrdir,
 
22
    bzrdir,
23
23
    config,
24
 
    controldir,
25
24
    debug,
26
25
    errors,
27
26
    graph,
28
27
    lock,
29
28
    lockdir,
30
 
    repository as _mod_repository,
 
29
    repository,
 
30
    revision,
31
31
    revision as _mod_revision,
32
 
    static_tuple,
33
32
    symbol_versioning,
34
 
    urlutils,
35
 
    vf_repository,
36
 
    )
37
 
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
 
33
)
 
34
from bzrlib.branch import BranchReferenceFormat
 
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
36
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
39
37
from bzrlib.errors import (
40
38
    NoSuchRevision,
42
40
    )
43
41
from bzrlib.lockable_files import LockableFiles
44
42
from bzrlib.smart import client, vfs, repository as smart_repo
45
 
from bzrlib.smart.client import _SmartClient
46
 
from bzrlib.revision import NULL_REVISION
47
 
from bzrlib.repository import RepositoryWriteLockResult, _LazyListJoin
 
43
from bzrlib.revision import ensure_null, NULL_REVISION
48
44
from bzrlib.trace import mutter, note, warning
49
45
 
50
46
 
51
 
_DEFAULT_SEARCH_DEPTH = 100
52
 
 
53
 
 
54
47
class _RpcHelper(object):
55
48
    """Mixin class that helps with issuing RPCs."""
56
49
 
91
84
    return format
92
85
 
93
86
 
94
 
# Note that RemoteBzrDirProber lives in bzrlib.bzrdir so bzrlib.remote
95
 
# does not have to be imported unless a remote format is involved.
96
 
 
97
 
class RemoteBzrDirFormat(_mod_bzrdir.BzrDirMetaFormat1):
98
 
    """Format representing bzrdirs accessed via a smart server"""
99
 
 
100
 
    supports_workingtrees = False
101
 
 
102
 
    def __init__(self):
103
 
        _mod_bzrdir.BzrDirMetaFormat1.__init__(self)
104
 
        # XXX: It's a bit ugly that the network name is here, because we'd
105
 
        # like to believe that format objects are stateless or at least
106
 
        # immutable,  However, we do at least avoid mutating the name after
107
 
        # it's returned.  See <https://bugs.launchpad.net/bzr/+bug/504102>
108
 
        self._network_name = None
109
 
 
110
 
    def __repr__(self):
111
 
        return "%s(_network_name=%r)" % (self.__class__.__name__,
112
 
            self._network_name)
113
 
 
114
 
    def get_format_description(self):
115
 
        if self._network_name:
116
 
            real_format = controldir.network_format_registry.get(self._network_name)
117
 
            return 'Remote: ' + real_format.get_format_description()
118
 
        return 'bzr remote bzrdir'
119
 
 
120
 
    def get_format_string(self):
121
 
        raise NotImplementedError(self.get_format_string)
122
 
 
123
 
    def network_name(self):
124
 
        if self._network_name:
125
 
            return self._network_name
126
 
        else:
127
 
            raise AssertionError("No network name set.")
128
 
 
129
 
    def initialize_on_transport(self, transport):
130
 
        try:
131
 
            # hand off the request to the smart server
132
 
            client_medium = transport.get_smart_medium()
133
 
        except errors.NoSmartMedium:
134
 
            # TODO: lookup the local format from a server hint.
135
 
            local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
136
 
            return local_dir_format.initialize_on_transport(transport)
137
 
        client = _SmartClient(client_medium)
138
 
        path = client.remote_path_from_transport(transport)
139
 
        try:
140
 
            response = client.call('BzrDirFormat.initialize', path)
141
 
        except errors.ErrorFromSmartServer, err:
142
 
            _translate_error(err, path=path)
143
 
        if response[0] != 'ok':
144
 
            raise errors.SmartProtocolError('unexpected response code %s' % (response,))
145
 
        format = RemoteBzrDirFormat()
146
 
        self._supply_sub_formats_to(format)
147
 
        return RemoteBzrDir(transport, format)
148
 
 
149
 
    def parse_NoneTrueFalse(self, arg):
150
 
        if not arg:
151
 
            return None
152
 
        if arg == 'False':
153
 
            return False
154
 
        if arg == 'True':
155
 
            return True
156
 
        raise AssertionError("invalid arg %r" % arg)
157
 
 
158
 
    def _serialize_NoneTrueFalse(self, arg):
159
 
        if arg is False:
160
 
            return 'False'
161
 
        if arg:
162
 
            return 'True'
163
 
        return ''
164
 
 
165
 
    def _serialize_NoneString(self, arg):
166
 
        return arg or ''
167
 
 
168
 
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
169
 
        create_prefix=False, force_new_repo=False, stacked_on=None,
170
 
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
171
 
        shared_repo=False):
172
 
        try:
173
 
            # hand off the request to the smart server
174
 
            client_medium = transport.get_smart_medium()
175
 
        except errors.NoSmartMedium:
176
 
            do_vfs = True
177
 
        else:
178
 
            # Decline to open it if the server doesn't support our required
179
 
            # version (3) so that the VFS-based transport will do it.
180
 
            if client_medium.should_probe():
181
 
                try:
182
 
                    server_version = client_medium.protocol_version()
183
 
                    if server_version != '2':
184
 
                        do_vfs = True
185
 
                    else:
186
 
                        do_vfs = False
187
 
                except errors.SmartProtocolError:
188
 
                    # Apparently there's no usable smart server there, even though
189
 
                    # the medium supports the smart protocol.
190
 
                    do_vfs = True
191
 
            else:
192
 
                do_vfs = False
193
 
        if not do_vfs:
194
 
            client = _SmartClient(client_medium)
195
 
            path = client.remote_path_from_transport(transport)
196
 
            if client_medium._is_remote_before((1, 16)):
197
 
                do_vfs = True
198
 
        if do_vfs:
199
 
            # TODO: lookup the local format from a server hint.
200
 
            local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
201
 
            self._supply_sub_formats_to(local_dir_format)
202
 
            return local_dir_format.initialize_on_transport_ex(transport,
203
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
204
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
205
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
206
 
                make_working_trees=make_working_trees, shared_repo=shared_repo,
207
 
                vfs_only=True)
208
 
        return self._initialize_on_transport_ex_rpc(client, path, transport,
209
 
            use_existing_dir, create_prefix, force_new_repo, stacked_on,
210
 
            stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
211
 
 
212
 
    def _initialize_on_transport_ex_rpc(self, client, path, transport,
213
 
        use_existing_dir, create_prefix, force_new_repo, stacked_on,
214
 
        stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
215
 
        args = []
216
 
        args.append(self._serialize_NoneTrueFalse(use_existing_dir))
217
 
        args.append(self._serialize_NoneTrueFalse(create_prefix))
218
 
        args.append(self._serialize_NoneTrueFalse(force_new_repo))
219
 
        args.append(self._serialize_NoneString(stacked_on))
220
 
        # stack_on_pwd is often/usually our transport
221
 
        if stack_on_pwd:
222
 
            try:
223
 
                stack_on_pwd = transport.relpath(stack_on_pwd)
224
 
                if not stack_on_pwd:
225
 
                    stack_on_pwd = '.'
226
 
            except errors.PathNotChild:
227
 
                pass
228
 
        args.append(self._serialize_NoneString(stack_on_pwd))
229
 
        args.append(self._serialize_NoneString(repo_format_name))
230
 
        args.append(self._serialize_NoneTrueFalse(make_working_trees))
231
 
        args.append(self._serialize_NoneTrueFalse(shared_repo))
232
 
        request_network_name = self._network_name or \
233
 
            _mod_bzrdir.BzrDirFormat.get_default_format().network_name()
234
 
        try:
235
 
            response = client.call('BzrDirFormat.initialize_ex_1.16',
236
 
                request_network_name, path, *args)
237
 
        except errors.UnknownSmartMethod:
238
 
            client._medium._remember_remote_is_before((1,16))
239
 
            local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
240
 
            self._supply_sub_formats_to(local_dir_format)
241
 
            return local_dir_format.initialize_on_transport_ex(transport,
242
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
243
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
244
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
245
 
                make_working_trees=make_working_trees, shared_repo=shared_repo,
246
 
                vfs_only=True)
247
 
        except errors.ErrorFromSmartServer, err:
248
 
            _translate_error(err, path=path)
249
 
        repo_path = response[0]
250
 
        bzrdir_name = response[6]
251
 
        require_stacking = response[7]
252
 
        require_stacking = self.parse_NoneTrueFalse(require_stacking)
253
 
        format = RemoteBzrDirFormat()
254
 
        format._network_name = bzrdir_name
255
 
        self._supply_sub_formats_to(format)
256
 
        bzrdir = RemoteBzrDir(transport, format, _client=client)
257
 
        if repo_path:
258
 
            repo_format = response_tuple_to_repo_format(response[1:])
259
 
            if repo_path == '.':
260
 
                repo_path = ''
261
 
            if repo_path:
262
 
                repo_bzrdir_format = RemoteBzrDirFormat()
263
 
                repo_bzrdir_format._network_name = response[5]
264
 
                repo_bzr = RemoteBzrDir(transport.clone(repo_path),
265
 
                    repo_bzrdir_format)
266
 
            else:
267
 
                repo_bzr = bzrdir
268
 
            final_stack = response[8] or None
269
 
            final_stack_pwd = response[9] or None
270
 
            if final_stack_pwd:
271
 
                final_stack_pwd = urlutils.join(
272
 
                    transport.base, final_stack_pwd)
273
 
            remote_repo = RemoteRepository(repo_bzr, repo_format)
274
 
            if len(response) > 10:
275
 
                # Updated server verb that locks remotely.
276
 
                repo_lock_token = response[10] or None
277
 
                remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
278
 
                if repo_lock_token:
279
 
                    remote_repo.dont_leave_lock_in_place()
280
 
            else:
281
 
                remote_repo.lock_write()
282
 
            policy = _mod_bzrdir.UseExistingRepository(remote_repo, final_stack,
283
 
                final_stack_pwd, require_stacking)
284
 
            policy.acquire_repository()
285
 
        else:
286
 
            remote_repo = None
287
 
            policy = None
288
 
        bzrdir._format.set_branch_format(self.get_branch_format())
289
 
        if require_stacking:
290
 
            # The repo has already been created, but we need to make sure that
291
 
            # we'll make a stackable branch.
292
 
            bzrdir._format.require_stacking(_skip_repo=True)
293
 
        return remote_repo, bzrdir, require_stacking, policy
294
 
 
295
 
    def _open(self, transport):
296
 
        return RemoteBzrDir(transport, self)
297
 
 
298
 
    def __eq__(self, other):
299
 
        if not isinstance(other, RemoteBzrDirFormat):
300
 
            return False
301
 
        return self.get_format_description() == other.get_format_description()
302
 
 
303
 
    def __return_repository_format(self):
304
 
        # Always return a RemoteRepositoryFormat object, but if a specific bzr
305
 
        # repository format has been asked for, tell the RemoteRepositoryFormat
306
 
        # that it should use that for init() etc.
307
 
        result = RemoteRepositoryFormat()
308
 
        custom_format = getattr(self, '_repository_format', None)
309
 
        if custom_format:
310
 
            if isinstance(custom_format, RemoteRepositoryFormat):
311
 
                return custom_format
312
 
            else:
313
 
                # We will use the custom format to create repositories over the
314
 
                # wire; expose its details like rich_root_data for code to
315
 
                # query
316
 
                result._custom_format = custom_format
317
 
        return result
318
 
 
319
 
    def get_branch_format(self):
320
 
        result = _mod_bzrdir.BzrDirMetaFormat1.get_branch_format(self)
321
 
        if not isinstance(result, RemoteBranchFormat):
322
 
            new_result = RemoteBranchFormat()
323
 
            new_result._custom_format = result
324
 
            # cache the result
325
 
            self.set_branch_format(new_result)
326
 
            result = new_result
327
 
        return result
328
 
 
329
 
    repository_format = property(__return_repository_format,
330
 
        _mod_bzrdir.BzrDirMetaFormat1._set_repository_format) #.im_func)
331
 
 
332
 
 
333
 
class RemoteBzrDir(_mod_bzrdir.BzrDir, _RpcHelper):
 
87
# Note: RemoteBzrDirFormat is in bzrdir.py
 
88
 
 
89
class RemoteBzrDir(BzrDir, _RpcHelper):
334
90
    """Control directory on a remote server, accessed via bzr:// or similar."""
335
91
 
336
92
    def __init__(self, transport, format, _client=None, _force_probe=False):
339
95
        :param _client: Private parameter for testing. Disables probing and the
340
96
            use of a real bzrdir.
341
97
        """
342
 
        _mod_bzrdir.BzrDir.__init__(self, transport, format)
 
98
        BzrDir.__init__(self, transport, format)
343
99
        # this object holds a delegated bzrdir that uses file-level operations
344
100
        # to talk to the other side
345
101
        self._real_bzrdir = None
358
114
 
359
115
        self._probe_bzrdir()
360
116
 
361
 
    def __repr__(self):
362
 
        return '%s(%r)' % (self.__class__.__name__, self._client)
363
 
 
364
117
    def _probe_bzrdir(self):
365
118
        medium = self._client._medium
366
119
        path = self._path_for_remote_call(self._client)
405
158
                import traceback
406
159
                warning('VFS BzrDir access triggered\n%s',
407
160
                    ''.join(traceback.format_stack()))
408
 
            self._real_bzrdir = _mod_bzrdir.BzrDir.open_from_transport(
 
161
            self._real_bzrdir = BzrDir.open_from_transport(
409
162
                self.root_transport, _server_formats=False)
410
163
            self._format._network_name = \
411
164
                self._real_bzrdir._format.network_name()
417
170
        # Prevent aliasing problems in the next_open_branch_result cache.
418
171
        # See create_branch for rationale.
419
172
        self._next_open_branch_result = None
420
 
        return _mod_bzrdir.BzrDir.break_lock(self)
 
173
        return BzrDir.break_lock(self)
421
174
 
422
175
    def _vfs_cloning_metadir(self, require_stacking=False):
423
176
        self._ensure_real()
454
207
        if len(branch_info) != 2:
455
208
            raise errors.UnexpectedSmartServerResponse(response)
456
209
        branch_ref, branch_name = branch_info
457
 
        format = controldir.network_format_registry.get(control_name)
 
210
        format = bzrdir.network_format_registry.get(control_name)
458
211
        if repo_name:
459
 
            format.repository_format = _mod_repository.network_format_registry.get(
 
212
            format.repository_format = repository.network_format_registry.get(
460
213
                repo_name)
461
214
        if branch_ref == 'ref':
462
215
            # XXX: we need possible_transports here to avoid reopening the
463
216
            # connection to the referenced location
464
 
            ref_bzrdir = _mod_bzrdir.BzrDir.open(branch_name)
 
217
            ref_bzrdir = BzrDir.open(branch_name)
465
218
            branch_format = ref_bzrdir.cloning_metadir().get_branch_format()
466
219
            format.set_branch_format(branch_format)
467
220
        elif branch_ref == 'branch':
486
239
        self._ensure_real()
487
240
        self._real_bzrdir.destroy_repository()
488
241
 
489
 
    def create_branch(self, name=None, repository=None,
490
 
                      append_revisions_only=None):
 
242
    def create_branch(self):
491
243
        # as per meta1 formats - just delegate to the format object which may
492
244
        # be parameterised.
493
 
        real_branch = self._format.get_branch_format().initialize(self,
494
 
            name=name, repository=repository,
495
 
            append_revisions_only=append_revisions_only)
 
245
        real_branch = self._format.get_branch_format().initialize(self)
496
246
        if not isinstance(real_branch, RemoteBranch):
497
 
            if not isinstance(repository, RemoteRepository):
498
 
                raise AssertionError(
499
 
                    'need a RemoteRepository to use with RemoteBranch, got %r'
500
 
                    % (repository,))
501
 
            result = RemoteBranch(self, repository, real_branch, name=name)
 
247
            result = RemoteBranch(self, self.find_repository(), real_branch)
502
248
        else:
503
249
            result = real_branch
504
250
        # BzrDir.clone_on_transport() uses the result of create_branch but does
510
256
        self._next_open_branch_result = result
511
257
        return result
512
258
 
513
 
    def destroy_branch(self, name=None):
 
259
    def destroy_branch(self):
514
260
        """See BzrDir.destroy_branch"""
515
261
        self._ensure_real()
516
 
        self._real_bzrdir.destroy_branch(name=name)
 
262
        self._real_bzrdir.destroy_branch()
517
263
        self._next_open_branch_result = None
518
264
 
519
 
    def create_workingtree(self, revision_id=None, from_branch=None,
520
 
        accelerator_tree=None, hardlink=False):
 
265
    def create_workingtree(self, revision_id=None, from_branch=None):
521
266
        raise errors.NotLocalUrl(self.transport.base)
522
267
 
523
 
    def find_branch_format(self, name=None):
 
268
    def find_branch_format(self):
524
269
        """Find the branch 'format' for this bzrdir.
525
270
 
526
271
        This might be a synthetic object for e.g. RemoteBranch and SVN.
527
272
        """
528
 
        b = self.open_branch(name=name)
 
273
        b = self.open_branch()
529
274
        return b._format
530
275
 
531
 
    def get_branch_reference(self, name=None):
 
276
    def get_branch_reference(self):
532
277
        """See BzrDir.get_branch_reference()."""
533
 
        if name is not None:
534
 
            # XXX JRV20100304: Support opening colocated branches
535
 
            raise errors.NoColocatedBranchSupport(self)
536
278
        response = self._get_branch_reference()
537
279
        if response[0] == 'ref':
538
280
            return response[1]
542
284
    def _get_branch_reference(self):
543
285
        path = self._path_for_remote_call(self._client)
544
286
        medium = self._client._medium
545
 
        candidate_calls = [
546
 
            ('BzrDir.open_branchV3', (2, 1)),
547
 
            ('BzrDir.open_branchV2', (1, 13)),
548
 
            ('BzrDir.open_branch', None),
549
 
            ]
550
 
        for verb, required_version in candidate_calls:
551
 
            if required_version and medium._is_remote_before(required_version):
552
 
                continue
 
287
        if not medium._is_remote_before((1, 13)):
553
288
            try:
554
 
                response = self._call(verb, path)
 
289
                response = self._call('BzrDir.open_branchV2', path)
 
290
                if response[0] not in ('ref', 'branch'):
 
291
                    raise errors.UnexpectedSmartServerResponse(response)
 
292
                return response
555
293
            except errors.UnknownSmartMethod:
556
 
                if required_version is None:
557
 
                    raise
558
 
                medium._remember_remote_is_before(required_version)
559
 
            else:
560
 
                break
561
 
        if verb == 'BzrDir.open_branch':
562
 
            if response[0] != 'ok':
563
 
                raise errors.UnexpectedSmartServerResponse(response)
564
 
            if response[1] != '':
565
 
                return ('ref', response[1])
566
 
            else:
567
 
                return ('branch', '')
568
 
        if response[0] not in ('ref', 'branch'):
 
294
                medium._remember_remote_is_before((1, 13))
 
295
        response = self._call('BzrDir.open_branch', path)
 
296
        if response[0] != 'ok':
569
297
            raise errors.UnexpectedSmartServerResponse(response)
570
 
        return response
 
298
        if response[1] != '':
 
299
            return ('ref', response[1])
 
300
        else:
 
301
            return ('branch', '')
571
302
 
572
 
    def _get_tree_branch(self, name=None):
 
303
    def _get_tree_branch(self):
573
304
        """See BzrDir._get_tree_branch()."""
574
 
        return None, self.open_branch(name=name)
 
305
        return None, self.open_branch()
575
306
 
576
 
    def open_branch(self, name=None, unsupported=False,
577
 
                    ignore_fallbacks=False):
578
 
        if unsupported:
 
307
    def open_branch(self, _unsupported=False, ignore_fallbacks=False):
 
308
        if _unsupported:
579
309
            raise NotImplementedError('unsupported flag support not implemented yet.')
580
310
        if self._next_open_branch_result is not None:
581
311
            # See create_branch for details.
586
316
        if response[0] == 'ref':
587
317
            # a branch reference, use the existing BranchReference logic.
588
318
            format = BranchReferenceFormat()
589
 
            return format.open(self, name=name, _found=True,
590
 
                location=response[1], ignore_fallbacks=ignore_fallbacks)
 
319
            return format.open(self, _found=True, location=response[1],
 
320
                ignore_fallbacks=ignore_fallbacks)
591
321
        branch_format_name = response[1]
592
322
        if not branch_format_name:
593
323
            branch_format_name = None
594
324
        format = RemoteBranchFormat(network_name=branch_format_name)
595
325
        return RemoteBranch(self, self.find_repository(), format=format,
596
 
            setup_stacking=not ignore_fallbacks, name=name)
 
326
            setup_stacking=not ignore_fallbacks)
597
327
 
598
328
    def _open_repo_v1(self, path):
599
329
        verb = 'BzrDir.find_repository'
674
404
 
675
405
    def _path_for_remote_call(self, client):
676
406
        """Return the path to be used for this bzrdir in a remote call."""
677
 
        return urlutils.split_segment_parameters_raw(
678
 
            client.remote_path_from_transport(self.root_transport))[0]
 
407
        return client.remote_path_from_transport(self.root_transport)
679
408
 
680
 
    def get_branch_transport(self, branch_format, name=None):
 
409
    def get_branch_transport(self, branch_format):
681
410
        self._ensure_real()
682
 
        return self._real_bzrdir.get_branch_transport(branch_format, name=name)
 
411
        return self._real_bzrdir.get_branch_transport(branch_format)
683
412
 
684
413
    def get_repository_transport(self, repository_format):
685
414
        self._ensure_real()
693
422
        """Upgrading of remote bzrdirs is not supported yet."""
694
423
        return False
695
424
 
696
 
    def needs_format_conversion(self, format):
 
425
    def needs_format_conversion(self, format=None):
697
426
        """Upgrading of remote bzrdirs is not supported yet."""
 
427
        if format is None:
 
428
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
 
429
                % 'needs_format_conversion(format=None)')
698
430
        return False
699
431
 
700
432
    def clone(self, url, revision_id=None, force_new_repo=False,
707
439
        return RemoteBzrDirConfig(self)
708
440
 
709
441
 
710
 
class RemoteRepositoryFormat(vf_repository.VersionedFileRepositoryFormat):
 
442
class RemoteRepositoryFormat(repository.RepositoryFormat):
711
443
    """Format for repositories accessed over a _SmartClient.
712
444
 
713
445
    Instances of this repository are represented by RemoteRepository
728
460
    """
729
461
 
730
462
    _matchingbzrdir = RemoteBzrDirFormat()
731
 
    supports_full_versioned_files = True
732
 
    supports_leaving_lock = True
733
463
 
734
464
    def __init__(self):
735
 
        _mod_repository.RepositoryFormat.__init__(self)
 
465
        repository.RepositoryFormat.__init__(self)
736
466
        self._custom_format = None
737
467
        self._network_name = None
738
468
        self._creating_bzrdir = None
739
 
        self._revision_graph_can_have_wrong_parents = None
740
469
        self._supports_chks = None
741
470
        self._supports_external_lookups = None
742
471
        self._supports_tree_reference = None
743
 
        self._supports_funky_characters = None
744
472
        self._rich_root_data = None
745
473
 
746
474
    def __repr__(self):
775
503
        return self._supports_external_lookups
776
504
 
777
505
    @property
778
 
    def supports_funky_characters(self):
779
 
        if self._supports_funky_characters is None:
780
 
            self._ensure_real()
781
 
            self._supports_funky_characters = \
782
 
                self._custom_format.supports_funky_characters
783
 
        return self._supports_funky_characters
784
 
 
785
 
    @property
786
506
    def supports_tree_reference(self):
787
507
        if self._supports_tree_reference is None:
788
508
            self._ensure_real()
790
510
                self._custom_format.supports_tree_reference
791
511
        return self._supports_tree_reference
792
512
 
793
 
    @property
794
 
    def revision_graph_can_have_wrong_parents(self):
795
 
        if self._revision_graph_can_have_wrong_parents is None:
796
 
            self._ensure_real()
797
 
            self._revision_graph_can_have_wrong_parents = \
798
 
                self._custom_format.revision_graph_can_have_wrong_parents
799
 
        return self._revision_graph_can_have_wrong_parents
800
 
 
801
513
    def _vfs_initialize(self, a_bzrdir, shared):
802
514
        """Helper for common code in initialize."""
803
515
        if self._custom_format:
838
550
            network_name = self._network_name
839
551
        else:
840
552
            # Select the current bzrlib default and ask for that.
841
 
            reference_bzrdir_format = _mod_bzrdir.format_registry.get('default')()
 
553
            reference_bzrdir_format = bzrdir.format_registry.get('default')()
842
554
            reference_format = reference_bzrdir_format.repository_format
843
555
            network_name = reference_format.network_name()
844
556
        # 2) try direct creation via RPC
870
582
 
871
583
    def _ensure_real(self):
872
584
        if self._custom_format is None:
873
 
            self._custom_format = _mod_repository.network_format_registry.get(
 
585
            self._custom_format = repository.network_format_registry.get(
874
586
                self._network_name)
875
587
 
876
588
    @property
912
624
        return self._custom_format._serializer
913
625
 
914
626
 
915
 
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin,
916
 
    controldir.ControlComponent):
 
627
class RemoteRepository(_RpcHelper, lock._RelockDebugMixin):
917
628
    """Repository accessed over rpc.
918
629
 
919
630
    For the moment most operations are performed using local transport-backed
962
673
        # Additional places to query for data.
963
674
        self._fallback_repositories = []
964
675
 
965
 
    @property
966
 
    def user_transport(self):
967
 
        return self.bzrdir.user_transport
968
 
 
969
 
    @property
970
 
    def control_transport(self):
971
 
        # XXX: Normally you shouldn't directly get at the remote repository
972
 
        # transport, but I'm not sure it's worth making this method
973
 
        # optional -- mbp 2010-04-21
974
 
        return self.bzrdir.get_repository_transport(None)
975
 
 
976
676
    def __str__(self):
977
677
        return "%s(%s)" % (self.__class__.__name__, self.base)
978
678
 
1086
786
    def find_text_key_references(self):
1087
787
        """Find the text key references within the repository.
1088
788
 
 
789
        :return: a dictionary mapping (file_id, revision_id) tuples to altered file-ids to an iterable of
 
790
        revision_ids. Each altered file-ids has the exact revision_ids that
 
791
        altered it listed explicitly.
1089
792
        :return: A dictionary mapping text keys ((fileid, revision_id) tuples)
1090
793
            to whether they were referred to by the inventory of the
1091
794
            revision_id that they contain. The inventory texts from all present
1109
812
        """Private method for using with old (< 1.2) servers to fallback."""
1110
813
        if revision_id is None:
1111
814
            revision_id = ''
1112
 
        elif _mod_revision.is_null(revision_id):
 
815
        elif revision.is_null(revision_id):
1113
816
            return {}
1114
817
 
1115
818
        path = self.bzrdir._path_for_remote_call(self._client)
1139
842
        return RemoteStreamSource(self, to_format)
1140
843
 
1141
844
    @needs_read_lock
1142
 
    def get_file_graph(self):
1143
 
        return graph.Graph(self.texts)
1144
 
 
1145
 
    @needs_read_lock
1146
845
    def has_revision(self, revision_id):
1147
846
        """True if this repository has a copy of the revision."""
1148
847
        # Copy of bzrlib.repository.Repository.has_revision
1165
864
    def _has_same_fallbacks(self, other_repo):
1166
865
        """Returns true if the repositories have the same fallbacks."""
1167
866
        # XXX: copied from Repository; it should be unified into a base class
1168
 
        # <https://bugs.launchpad.net/bzr/+bug/401622>
 
867
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
1169
868
        my_fb = self._fallback_repositories
1170
869
        other_fb = other_repo._fallback_repositories
1171
870
        if len(my_fb) != len(other_fb):
1187
886
        parents_provider = self._make_parents_provider(other_repository)
1188
887
        return graph.Graph(parents_provider)
1189
888
 
1190
 
    @needs_read_lock
1191
 
    def get_known_graph_ancestry(self, revision_ids):
1192
 
        """Return the known graph for a set of revision ids and their ancestors.
1193
 
        """
1194
 
        st = static_tuple.StaticTuple
1195
 
        revision_keys = [st(r_id).intern() for r_id in revision_ids]
1196
 
        known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
1197
 
        return graph.GraphThunkIdsToKeys(known_graph)
1198
 
 
1199
889
    def gather_stats(self, revid=None, committers=None):
1200
890
        """See Repository.gather_stats()."""
1201
891
        path = self.bzrdir._path_for_remote_call(self._client)
1202
892
        # revid can be None to indicate no revisions, not just NULL_REVISION
1203
 
        if revid is None or _mod_revision.is_null(revid):
 
893
        if revid is None or revision.is_null(revid):
1204
894
            fmt_revid = ''
1205
895
        else:
1206
896
            fmt_revid = revid
1261
951
    def is_write_locked(self):
1262
952
        return self._lock_mode == 'w'
1263
953
 
1264
 
    def _warn_if_deprecated(self, branch=None):
1265
 
        # If we have a real repository, the check will be done there, if we
1266
 
        # don't the check will be done remotely.
1267
 
        pass
1268
 
 
1269
954
    def lock_read(self):
1270
 
        """Lock the repository for read operations.
1271
 
 
1272
 
        :return: A bzrlib.lock.LogicalLockResult.
1273
 
        """
1274
955
        # wrong eventually - want a local lock cache context
1275
956
        if not self._lock_mode:
1276
957
            self._note_lock('r')
1283
964
                repo.lock_read()
1284
965
        else:
1285
966
            self._lock_count += 1
1286
 
        return lock.LogicalLockResult(self.unlock)
1287
967
 
1288
968
    def _remote_lock_write(self, token):
1289
969
        path = self.bzrdir._path_for_remote_call(self._client)
1329
1009
            raise errors.ReadOnlyError(self)
1330
1010
        else:
1331
1011
            self._lock_count += 1
1332
 
        return RepositoryWriteLockResult(self.unlock, self._lock_token or None)
 
1012
        return self._lock_token or None
1333
1013
 
1334
1014
    def leave_lock_in_place(self):
1335
1015
        if not self._lock_token:
1489
1169
 
1490
1170
    def get_commit_builder(self, branch, parents, config, timestamp=None,
1491
1171
                           timezone=None, committer=None, revprops=None,
1492
 
                           revision_id=None, lossy=False):
 
1172
                           revision_id=None):
1493
1173
        # FIXME: It ought to be possible to call this without immediately
1494
1174
        # triggering _ensure_real.  For now it's the easiest thing to do.
1495
1175
        self._ensure_real()
1496
1176
        real_repo = self._real_repository
1497
1177
        builder = real_repo.get_commit_builder(branch, parents,
1498
1178
                config, timestamp=timestamp, timezone=timezone,
1499
 
                committer=committer, revprops=revprops,
1500
 
                revision_id=revision_id, lossy=lossy)
 
1179
                committer=committer, revprops=revprops, revision_id=revision_id)
1501
1180
        return builder
1502
1181
 
1503
1182
    def add_fallback_repository(self, repository):
1511
1190
        # We need to accumulate additional repositories here, to pass them in
1512
1191
        # on various RPC's.
1513
1192
        #
1514
 
        # Make the check before we lock: this raises an exception.
1515
 
        self._check_fallback_repository(repository)
1516
1193
        if self.is_locked():
1517
1194
            # We will call fallback.unlock() when we transition to the unlocked
1518
1195
            # state, so always add a lock here. If a caller passes us a locked
1523
1200
        # _real_branch had its get_stacked_on_url method called), then the
1524
1201
        # repository to be added may already be in the _real_repositories list.
1525
1202
        if self._real_repository is not None:
1526
 
            fallback_locations = [repo.user_url for repo in
 
1203
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
1527
1204
                self._real_repository._fallback_repositories]
1528
 
            if repository.user_url not in fallback_locations:
 
1205
            if repository.bzrdir.root_transport.base not in fallback_locations:
1529
1206
                self._real_repository.add_fallback_repository(repository)
1530
1207
 
1531
 
    def _check_fallback_repository(self, repository):
1532
 
        """Check that this repository can fallback to repository safely.
1533
 
 
1534
 
        Raise an error if not.
1535
 
 
1536
 
        :param repository: A repository to fallback to.
1537
 
        """
1538
 
        return _mod_repository.InterRepository._assert_same_model(
1539
 
            self, repository)
1540
 
 
1541
1208
    def add_inventory(self, revid, inv, parents):
1542
1209
        self._ensure_real()
1543
1210
        return self._real_repository.add_inventory(revid, inv, parents)
1544
1211
 
1545
1212
    def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
1546
 
            parents, basis_inv=None, propagate_caches=False):
 
1213
                               parents):
1547
1214
        self._ensure_real()
1548
1215
        return self._real_repository.add_inventory_by_delta(basis_revision_id,
1549
 
            delta, new_revision_id, parents, basis_inv=basis_inv,
1550
 
            propagate_caches=propagate_caches)
 
1216
            delta, new_revision_id, parents)
1551
1217
 
1552
1218
    def add_revision(self, rev_id, rev, inv=None, config=None):
1553
1219
        self._ensure_real()
1583
1249
        return self._real_repository.make_working_trees()
1584
1250
 
1585
1251
    def refresh_data(self):
1586
 
        """Re-read any data needed to synchronise with disk.
 
1252
        """Re-read any data needed to to synchronise with disk.
1587
1253
 
1588
1254
        This method is intended to be called after another repository instance
1589
1255
        (such as one used by a smart server) has inserted data into the
1590
 
        repository. On all repositories this will work outside of write groups.
1591
 
        Some repository formats (pack and newer for bzrlib native formats)
1592
 
        support refresh_data inside write groups. If called inside a write
1593
 
        group on a repository that does not support refreshing in a write group
1594
 
        IsInWriteGroupError will be raised.
 
1256
        repository. It may not be called during a write group, but may be
 
1257
        called at any other time.
1595
1258
        """
 
1259
        if self.is_in_write_group():
 
1260
            raise errors.InternalBzrError(
 
1261
                "May not refresh_data while in a write group.")
1596
1262
        if self._real_repository is not None:
1597
1263
            self._real_repository.refresh_data()
1598
1264
 
1610
1276
        return result
1611
1277
 
1612
1278
    @needs_read_lock
1613
 
    def search_missing_revision_ids(self, other,
1614
 
            revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1615
 
            find_ghosts=True, revision_ids=None, if_present_ids=None,
1616
 
            limit=None):
 
1279
    def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1617
1280
        """Return the revision ids that other has that this does not.
1618
1281
 
1619
1282
        These are returned in topological order.
1620
1283
 
1621
1284
        revision_id: only return revision ids included by revision_id.
1622
1285
        """
1623
 
        if symbol_versioning.deprecated_passed(revision_id):
1624
 
            symbol_versioning.warn(
1625
 
                'search_missing_revision_ids(revision_id=...) was '
1626
 
                'deprecated in 2.4.  Use revision_ids=[...] instead.',
1627
 
                DeprecationWarning, stacklevel=2)
1628
 
            if revision_ids is not None:
1629
 
                raise AssertionError(
1630
 
                    'revision_ids is mutually exclusive with revision_id')
1631
 
            if revision_id is not None:
1632
 
                revision_ids = [revision_id]
1633
 
        inter_repo = _mod_repository.InterRepository.get(other, self)
1634
 
        return inter_repo.search_missing_revision_ids(
1635
 
            find_ghosts=find_ghosts, revision_ids=revision_ids,
1636
 
            if_present_ids=if_present_ids, limit=limit)
 
1286
        return repository.InterRepository.get(
 
1287
            other, self).search_missing_revision_ids(revision_id, find_ghosts)
1637
1288
 
1638
 
    def fetch(self, source, revision_id=None, find_ghosts=False,
 
1289
    def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
1639
1290
            fetch_spec=None):
1640
1291
        # No base implementation to use as RemoteRepository is not a subclass
1641
1292
        # of Repository; so this is a copy of Repository.fetch().
1652
1303
            # check that last_revision is in 'from' and then return a
1653
1304
            # no-operation.
1654
1305
            if (revision_id is not None and
1655
 
                not _mod_revision.is_null(revision_id)):
 
1306
                not revision.is_null(revision_id)):
1656
1307
                self.get_revision(revision_id)
1657
1308
            return 0, []
1658
1309
        # if there is no specific appropriate InterRepository, this will get
1659
1310
        # the InterRepository base class, which raises an
1660
1311
        # IncompatibleRepositories when asked to fetch.
1661
 
        inter = _mod_repository.InterRepository.get(source, self)
1662
 
        return inter.fetch(revision_id=revision_id,
 
1312
        inter = repository.InterRepository.get(source, self)
 
1313
        return inter.fetch(revision_id=revision_id, pb=pb,
1663
1314
            find_ghosts=find_ghosts, fetch_spec=fetch_spec)
1664
1315
 
1665
1316
    def create_bundle(self, target, base, fileobj, format=None):
1667
1318
        self._real_repository.create_bundle(target, base, fileobj, format)
1668
1319
 
1669
1320
    @needs_read_lock
1670
 
    @symbol_versioning.deprecated_method(
1671
 
        symbol_versioning.deprecated_in((2, 4, 0)))
1672
1321
    def get_ancestry(self, revision_id, topo_sorted=True):
1673
1322
        self._ensure_real()
1674
1323
        return self._real_repository.get_ancestry(revision_id, topo_sorted)
1688
1337
        self._ensure_real()
1689
1338
        return self._real_repository.iter_files_bytes(desired_files)
1690
1339
 
1691
 
    def get_cached_parent_map(self, revision_ids):
1692
 
        """See bzrlib.CachingParentsProvider.get_cached_parent_map"""
1693
 
        return self._unstacked_provider.get_cached_parent_map(revision_ids)
1694
 
 
1695
1340
    def get_parent_map(self, revision_ids):
1696
1341
        """See bzrlib.Graph.get_parent_map()."""
1697
1342
        return self._make_parents_provider().get_parent_map(revision_ids)
1755
1400
        if parents_map is None:
1756
1401
            # Repository is not locked, so there's no cache.
1757
1402
            parents_map = {}
1758
 
        if _DEFAULT_SEARCH_DEPTH <= 0:
1759
 
            (start_set, stop_keys,
1760
 
             key_count) = graph.search_result_from_parent_map(
1761
 
                parents_map, self._unstacked_provider.missing_keys)
1762
 
        else:
1763
 
            (start_set, stop_keys,
1764
 
             key_count) = graph.limited_search_result_from_parent_map(
1765
 
                parents_map, self._unstacked_provider.missing_keys,
1766
 
                keys, depth=_DEFAULT_SEARCH_DEPTH)
 
1403
        # start_set is all the keys in the cache
 
1404
        start_set = set(parents_map)
 
1405
        # result set is all the references to keys in the cache
 
1406
        result_parents = set()
 
1407
        for parents in parents_map.itervalues():
 
1408
            result_parents.update(parents)
 
1409
        stop_keys = result_parents.difference(start_set)
 
1410
        # We don't need to send ghosts back to the server as a position to
 
1411
        # stop either.
 
1412
        stop_keys.difference_update(self._unstacked_provider.missing_keys)
 
1413
        key_count = len(parents_map)
 
1414
        if (NULL_REVISION in result_parents
 
1415
            and NULL_REVISION in self._unstacked_provider.missing_keys):
 
1416
            # If we pruned NULL_REVISION from the stop_keys because it's also
 
1417
            # in our cache of "missing" keys we need to increment our key count
 
1418
            # by 1, because the reconsitituted SearchResult on the server will
 
1419
            # still consider NULL_REVISION to be an included key.
 
1420
            key_count += 1
 
1421
        included_keys = start_set.intersection(result_parents)
 
1422
        start_set.difference_update(included_keys)
1767
1423
        recipe = ('manual', start_set, stop_keys, key_count)
1768
1424
        body = self._serialise_search_recipe(recipe)
1769
1425
        path = self.bzrdir._path_for_remote_call(self._client)
1822
1478
        return self._real_repository.get_signature_text(revision_id)
1823
1479
 
1824
1480
    @needs_read_lock
1825
 
    def _get_inventory_xml(self, revision_id):
1826
 
        self._ensure_real()
1827
 
        return self._real_repository._get_inventory_xml(revision_id)
 
1481
    def get_inventory_xml(self, revision_id):
 
1482
        self._ensure_real()
 
1483
        return self._real_repository.get_inventory_xml(revision_id)
 
1484
 
 
1485
    def deserialise_inventory(self, revision_id, xml):
 
1486
        self._ensure_real()
 
1487
        return self._real_repository.deserialise_inventory(revision_id, xml)
1828
1488
 
1829
1489
    def reconcile(self, other=None, thorough=False):
1830
1490
        self._ensure_real()
1884
1544
            tmpdir = osutils.mkdtemp()
1885
1545
            try:
1886
1546
                _extract_tar(tar, tmpdir)
1887
 
                tmp_bzrdir = _mod_bzrdir.BzrDir.open(tmpdir)
 
1547
                tmp_bzrdir = BzrDir.open(tmpdir)
1888
1548
                tmp_repo = tmp_bzrdir.open_repository()
1889
1549
                tmp_repo.copy_content_into(destination, revision_id)
1890
1550
            finally:
1906
1566
        return self._real_repository.inventories
1907
1567
 
1908
1568
    @needs_write_lock
1909
 
    def pack(self, hint=None, clean_obsolete_packs=False):
 
1569
    def pack(self, hint=None):
1910
1570
        """Compress the data within the repository.
1911
1571
 
1912
1572
        This is not currently implemented within the smart server.
1913
1573
        """
1914
1574
        self._ensure_real()
1915
 
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
 
1575
        return self._real_repository.pack(hint=hint)
1916
1576
 
1917
1577
    @property
1918
1578
    def revisions(self):
1975
1635
    def supports_rich_root(self):
1976
1636
        return self._format.rich_root_data
1977
1637
 
1978
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1979
1638
    def iter_reverse_revision_history(self, revision_id):
1980
1639
        self._ensure_real()
1981
1640
        return self._real_repository.iter_reverse_revision_history(revision_id)
2002
1661
        return self._real_repository.item_keys_introduced_by(revision_ids,
2003
1662
            _files_pb=_files_pb)
2004
1663
 
 
1664
    def revision_graph_can_have_wrong_parents(self):
 
1665
        # The answer depends on the remote repo format.
 
1666
        self._ensure_real()
 
1667
        return self._real_repository.revision_graph_can_have_wrong_parents()
 
1668
 
2005
1669
    def _find_inconsistent_revision_parents(self, revisions_iterator=None):
2006
1670
        self._ensure_real()
2007
1671
        return self._real_repository._find_inconsistent_revision_parents(
2015
1679
        providers = [self._unstacked_provider]
2016
1680
        if other is not None:
2017
1681
            providers.insert(0, other)
2018
 
        return graph.StackedParentsProvider(_LazyListJoin(
2019
 
            providers, self._fallback_repositories))
 
1682
        providers.extend(r._make_parents_provider() for r in
 
1683
                         self._fallback_repositories)
 
1684
        return graph.StackedParentsProvider(providers)
2020
1685
 
2021
1686
    def _serialise_search_recipe(self, recipe):
2022
1687
        """Serialise a graph search recipe.
2030
1695
        return '\n'.join((start_keys, stop_keys, count))
2031
1696
 
2032
1697
    def _serialise_search_result(self, search_result):
2033
 
        parts = search_result.get_network_struct()
 
1698
        if isinstance(search_result, graph.PendingAncestryResult):
 
1699
            parts = ['ancestry-of']
 
1700
            parts.extend(search_result.heads)
 
1701
        else:
 
1702
            recipe = search_result.get_recipe()
 
1703
            parts = [recipe[0], self._serialise_search_recipe(recipe)]
2034
1704
        return '\n'.join(parts)
2035
1705
 
2036
1706
    def autopack(self):
2046
1716
            raise errors.UnexpectedSmartServerResponse(response)
2047
1717
 
2048
1718
 
2049
 
class RemoteStreamSink(vf_repository.StreamSink):
 
1719
class RemoteStreamSink(repository.StreamSink):
2050
1720
 
2051
1721
    def _insert_real(self, stream, src_format, resume_tokens):
2052
1722
        self.target_repo._ensure_real()
2153
1823
        self._last_substream and self._last_stream so that the stream can be
2154
1824
        resumed by _resume_stream_with_vfs.
2155
1825
        """
2156
 
 
 
1826
                    
2157
1827
        stream_iter = iter(stream)
2158
1828
        for substream_kind, substream in stream_iter:
2159
1829
            if substream_kind == 'inventory-deltas':
2162
1832
                return
2163
1833
            else:
2164
1834
                yield substream_kind, substream
2165
 
 
2166
 
 
2167
 
class RemoteStreamSource(vf_repository.StreamSource):
 
1835
            
 
1836
 
 
1837
class RemoteStreamSource(repository.StreamSource):
2168
1838
    """Stream data from a remote server."""
2169
1839
 
2170
1840
    def get_stream(self, search):
2230
1900
        candidate_verbs = [
2231
1901
            ('Repository.get_stream_1.19', (1, 19)),
2232
1902
            ('Repository.get_stream', (1, 13))]
2233
 
 
2234
1903
        found_verb = False
2235
1904
        for verb, version in candidate_verbs:
2236
1905
            if medium._is_remote_before(version):
2240
1909
                    verb, args, search_bytes)
2241
1910
            except errors.UnknownSmartMethod:
2242
1911
                medium._remember_remote_is_before(version)
2243
 
            except errors.UnknownErrorFromSmartServer, e:
2244
 
                if isinstance(search, graph.EverythingResult):
2245
 
                    error_verb = e.error_from_smart_server.error_verb
2246
 
                    if error_verb == 'BadSearch':
2247
 
                        # Pre-2.4 servers don't support this sort of search.
2248
 
                        # XXX: perhaps falling back to VFS on BadSearch is a
2249
 
                        # good idea in general?  It might provide a little bit
2250
 
                        # of protection against client-side bugs.
2251
 
                        medium._remember_remote_is_before((2, 4))
2252
 
                        break
2253
 
                raise
2254
1912
            else:
2255
1913
                response_tuple, response_handler = response
2256
1914
                found_verb = True
2260
1918
        if response_tuple[0] != 'ok':
2261
1919
            raise errors.UnexpectedSmartServerResponse(response_tuple)
2262
1920
        byte_stream = response_handler.read_streamed_body()
2263
 
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream,
2264
 
            self._record_counter)
 
1921
        src_format, stream = smart_repo._byte_stream_to_stream(byte_stream)
2265
1922
        if src_format.network_name() != repo._format.network_name():
2266
1923
            raise AssertionError(
2267
1924
                "Mismatched RemoteRepository and stream src %r, %r" % (
2349
2006
    def network_name(self):
2350
2007
        return self._network_name
2351
2008
 
2352
 
    def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
2353
 
        return a_bzrdir.open_branch(name=name, 
2354
 
            ignore_fallbacks=ignore_fallbacks)
 
2009
    def open(self, a_bzrdir, ignore_fallbacks=False):
 
2010
        return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2355
2011
 
2356
 
    def _vfs_initialize(self, a_bzrdir, name, append_revisions_only):
 
2012
    def _vfs_initialize(self, a_bzrdir):
2357
2013
        # Initialisation when using a local bzrdir object, or a non-vfs init
2358
2014
        # method is not available on the server.
2359
2015
        # self._custom_format is always set - the start of initialize ensures
2360
2016
        # that.
2361
2017
        if isinstance(a_bzrdir, RemoteBzrDir):
2362
2018
            a_bzrdir._ensure_real()
2363
 
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2364
 
                name, append_revisions_only=append_revisions_only)
 
2019
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
2365
2020
        else:
2366
2021
            # We assume the bzrdir is parameterised; it may not be.
2367
 
            result = self._custom_format.initialize(a_bzrdir, name,
2368
 
                append_revisions_only=append_revisions_only)
 
2022
            result = self._custom_format.initialize(a_bzrdir)
2369
2023
        if (isinstance(a_bzrdir, RemoteBzrDir) and
2370
2024
            not isinstance(result, RemoteBranch)):
2371
 
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2372
 
                                  name=name)
 
2025
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
2373
2026
        return result
2374
2027
 
2375
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2376
 
                   append_revisions_only=None):
 
2028
    def initialize(self, a_bzrdir):
2377
2029
        # 1) get the network name to use.
2378
2030
        if self._custom_format:
2379
2031
            network_name = self._custom_format.network_name()
2380
2032
        else:
2381
2033
            # Select the current bzrlib default and ask for that.
2382
 
            reference_bzrdir_format = _mod_bzrdir.format_registry.get('default')()
 
2034
            reference_bzrdir_format = bzrdir.format_registry.get('default')()
2383
2035
            reference_format = reference_bzrdir_format.get_branch_format()
2384
2036
            self._custom_format = reference_format
2385
2037
            network_name = reference_format.network_name()
2386
2038
        # Being asked to create on a non RemoteBzrDir:
2387
2039
        if not isinstance(a_bzrdir, RemoteBzrDir):
2388
 
            return self._vfs_initialize(a_bzrdir, name=name,
2389
 
                append_revisions_only=append_revisions_only)
 
2040
            return self._vfs_initialize(a_bzrdir)
2390
2041
        medium = a_bzrdir._client._medium
2391
2042
        if medium._is_remote_before((1, 13)):
2392
 
            return self._vfs_initialize(a_bzrdir, name=name,
2393
 
                append_revisions_only=append_revisions_only)
 
2043
            return self._vfs_initialize(a_bzrdir)
2394
2044
        # Creating on a remote bzr dir.
2395
2045
        # 2) try direct creation via RPC
2396
2046
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2397
 
        if name is not None:
2398
 
            # XXX JRV20100304: Support creating colocated branches
2399
 
            raise errors.NoColocatedBranchSupport(self)
2400
2047
        verb = 'BzrDir.create_branch'
2401
2048
        try:
2402
2049
            response = a_bzrdir._call(verb, path, network_name)
2403
2050
        except errors.UnknownSmartMethod:
2404
2051
            # Fallback - use vfs methods
2405
2052
            medium._remember_remote_is_before((1, 13))
2406
 
            return self._vfs_initialize(a_bzrdir, name=name,
2407
 
                    append_revisions_only=append_revisions_only)
 
2053
            return self._vfs_initialize(a_bzrdir)
2408
2054
        if response[0] != 'ok':
2409
2055
            raise errors.UnexpectedSmartServerResponse(response)
2410
2056
        # Turn the response into a RemoteRepository object.
2411
2057
        format = RemoteBranchFormat(network_name=response[1])
2412
2058
        repo_format = response_tuple_to_repo_format(response[3:])
2413
 
        repo_path = response[2]
2414
 
        if repository is not None:
2415
 
            remote_repo_url = urlutils.join(a_bzrdir.user_url, repo_path)
2416
 
            url_diff = urlutils.relative_url(repository.user_url,
2417
 
                    remote_repo_url)
2418
 
            if url_diff != '.':
2419
 
                raise AssertionError(
2420
 
                    'repository.user_url %r does not match URL from server '
2421
 
                    'response (%r + %r)'
2422
 
                    % (repository.user_url, a_bzrdir.user_url, repo_path))
2423
 
            remote_repo = repository
 
2059
        if response[2] == '':
 
2060
            repo_bzrdir = a_bzrdir
2424
2061
        else:
2425
 
            if repo_path == '':
2426
 
                repo_bzrdir = a_bzrdir
2427
 
            else:
2428
 
                repo_bzrdir = RemoteBzrDir(
2429
 
                    a_bzrdir.root_transport.clone(repo_path), a_bzrdir._format,
2430
 
                    a_bzrdir._client)
2431
 
            remote_repo = RemoteRepository(repo_bzrdir, repo_format)
 
2062
            repo_bzrdir = RemoteBzrDir(
 
2063
                a_bzrdir.root_transport.clone(response[2]), a_bzrdir._format,
 
2064
                a_bzrdir._client)
 
2065
        remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2432
2066
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2433
 
            format=format, setup_stacking=False, name=name)
2434
 
        if append_revisions_only:
2435
 
            remote_branch.set_append_revisions_only(append_revisions_only)
 
2067
            format=format, setup_stacking=False)
2436
2068
        # XXX: We know this is a new branch, so it must have revno 0, revid
2437
2069
        # NULL_REVISION. Creating the branch locked would make this be unable
2438
2070
        # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2457
2089
        self._ensure_real()
2458
2090
        return self._custom_format.supports_set_append_revisions_only()
2459
2091
 
2460
 
    def _use_default_local_heads_to_fetch(self):
2461
 
        # If the branch format is a metadir format *and* its heads_to_fetch
2462
 
        # implementation is not overridden vs the base class, we can use the
2463
 
        # base class logic rather than use the heads_to_fetch RPC.  This is
2464
 
        # usually cheaper in terms of net round trips, as the last-revision and
2465
 
        # tags info fetched is cached and would be fetched anyway.
2466
 
        self._ensure_real()
2467
 
        if isinstance(self._custom_format, branch.BranchFormatMetadir):
2468
 
            branch_class = self._custom_format._branch_class()
2469
 
            heads_to_fetch_impl = branch_class.heads_to_fetch.im_func
2470
 
            if heads_to_fetch_impl is branch.Branch.heads_to_fetch.im_func:
2471
 
                return True
2472
 
        return False
2473
2092
 
2474
2093
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2475
2094
    """Branch stored on a server accessed by HPSS RPC.
2478
2097
    """
2479
2098
 
2480
2099
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2481
 
        _client=None, format=None, setup_stacking=True, name=None):
 
2100
        _client=None, format=None, setup_stacking=True):
2482
2101
        """Create a RemoteBranch instance.
2483
2102
 
2484
2103
        :param real_branch: An optional local implementation of the branch
2490
2109
        :param setup_stacking: If True make an RPC call to determine the
2491
2110
            stacked (or not) status of the branch. If False assume the branch
2492
2111
            is not stacked.
2493
 
        :param name: Colocated branch name
2494
2112
        """
2495
2113
        # We intentionally don't call the parent class's __init__, because it
2496
2114
        # will try to assign to self.tags, which is a property in this subclass.
2515
2133
            self._real_branch = None
2516
2134
        # Fill out expected attributes of branch for bzrlib API users.
2517
2135
        self._clear_cached_state()
2518
 
        # TODO: deprecate self.base in favor of user_url
2519
 
        self.base = self.bzrdir.user_url
2520
 
        self._name = name
 
2136
        self.base = self.bzrdir.root_transport.base
2521
2137
        self._control_files = None
2522
2138
        self._lock_mode = None
2523
2139
        self._lock_token = None
2588
2204
                    'to use vfs implementation')
2589
2205
            self.bzrdir._ensure_real()
2590
2206
            self._real_branch = self.bzrdir._real_bzrdir.open_branch(
2591
 
                ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
 
2207
                ignore_fallbacks=self._real_ignore_fallbacks)
2592
2208
            if self.repository._real_repository is None:
2593
2209
                # Give the remote repository the matching real repo.
2594
2210
                real_repo = self._real_branch.repository
2633
2249
                self.bzrdir, self._client)
2634
2250
        return self._control_files
2635
2251
 
2636
 
    def _get_checkout_format(self, lightweight=False):
 
2252
    def _get_checkout_format(self):
2637
2253
        self._ensure_real()
2638
 
        if lightweight:
2639
 
            format = RemoteBzrDirFormat()
2640
 
            self.bzrdir._format._supply_sub_formats_to(format)
2641
 
            format.workingtree_format = self._real_branch._get_checkout_format(
2642
 
                lightweight=lightweight).workingtree_format
2643
 
            return format
2644
 
        else:
2645
 
            return self._real_branch._get_checkout_format(lightweight=False)
 
2254
        return self._real_branch._get_checkout_format()
2646
2255
 
2647
2256
    def get_physical_lock_status(self):
2648
2257
        """See Branch.get_physical_lock_status()."""
2681
2290
            self._is_stacked = False
2682
2291
        else:
2683
2292
            self._is_stacked = True
2684
 
 
 
2293
        
2685
2294
    def _vfs_get_tags_bytes(self):
2686
2295
        self._ensure_real()
2687
2296
        return self._real_branch._get_tags_bytes()
2688
2297
 
2689
 
    @needs_read_lock
2690
2298
    def _get_tags_bytes(self):
2691
 
        if self._tags_bytes is None:
2692
 
            self._tags_bytes = self._get_tags_bytes_via_hpss()
2693
 
        return self._tags_bytes
2694
 
 
2695
 
    def _get_tags_bytes_via_hpss(self):
2696
2299
        medium = self._client._medium
2697
2300
        if medium._is_remote_before((1, 13)):
2698
2301
            return self._vfs_get_tags_bytes()
2708
2311
        return self._real_branch._set_tags_bytes(bytes)
2709
2312
 
2710
2313
    def _set_tags_bytes(self, bytes):
2711
 
        if self.is_locked():
2712
 
            self._tags_bytes = bytes
2713
2314
        medium = self._client._medium
2714
2315
        if medium._is_remote_before((1, 18)):
2715
2316
            self._vfs_set_tags_bytes(bytes)
2724
2325
            self._vfs_set_tags_bytes(bytes)
2725
2326
 
2726
2327
    def lock_read(self):
2727
 
        """Lock the branch for read operations.
2728
 
 
2729
 
        :return: A bzrlib.lock.LogicalLockResult.
2730
 
        """
2731
2328
        self.repository.lock_read()
2732
2329
        if not self._lock_mode:
2733
2330
            self._note_lock('r')
2737
2334
                self._real_branch.lock_read()
2738
2335
        else:
2739
2336
            self._lock_count += 1
2740
 
        return lock.LogicalLockResult(self.unlock)
2741
2337
 
2742
2338
    def _remote_lock_write(self, token):
2743
2339
        if token is None:
2744
2340
            branch_token = repo_token = ''
2745
2341
        else:
2746
2342
            branch_token = token
2747
 
            repo_token = self.repository.lock_write().repository_token
 
2343
            repo_token = self.repository.lock_write()
2748
2344
            self.repository.unlock()
2749
2345
        err_context = {'token': token}
2750
 
        try:
2751
 
            response = self._call(
2752
 
                'Branch.lock_write', self._remote_path(), branch_token,
2753
 
                repo_token or '', **err_context)
2754
 
        except errors.LockContention, e:
2755
 
            # The LockContention from the server doesn't have any
2756
 
            # information about the lock_url. We re-raise LockContention
2757
 
            # with valid lock_url.
2758
 
            raise errors.LockContention('(remote lock)',
2759
 
                self.repository.base.split('.bzr/')[0])
 
2346
        response = self._call(
 
2347
            'Branch.lock_write', self._remote_path(), branch_token,
 
2348
            repo_token or '', **err_context)
2760
2349
        if response[0] != 'ok':
2761
2350
            raise errors.UnexpectedSmartServerResponse(response)
2762
2351
        ok, branch_token, repo_token = response
2783
2372
            self._lock_mode = 'w'
2784
2373
            self._lock_count = 1
2785
2374
        elif self._lock_mode == 'r':
2786
 
            raise errors.ReadOnlyError(self)
 
2375
            raise errors.ReadOnlyTransaction
2787
2376
        else:
2788
2377
            if token is not None:
2789
2378
                # A token was given to lock_write, and we're relocking, so
2794
2383
            self._lock_count += 1
2795
2384
            # Re-lock the repository too.
2796
2385
            self.repository.lock_write(self._repo_lock_token)
2797
 
        return BranchWriteLockResult(self.unlock, self._lock_token or None)
 
2386
        return self._lock_token or None
2798
2387
 
2799
2388
    def _unlock(self, branch_token, repo_token):
2800
2389
        err_context = {'token': str((branch_token, repo_token))}
2869
2458
            missing_parent = parent_map[missing_parent]
2870
2459
        raise errors.RevisionNotPresent(missing_parent, self.repository)
2871
2460
 
2872
 
    def _read_last_revision_info(self):
 
2461
    def _last_revision_info(self):
2873
2462
        response = self._call('Branch.last_revision_info', self._remote_path())
2874
2463
        if response[0] != 'ok':
2875
2464
            raise SmartProtocolError('unexpected response code %s' % (response,))
2938
2527
            raise errors.UnexpectedSmartServerResponse(response)
2939
2528
        self._run_post_change_branch_tip_hooks(old_revno, old_revid)
2940
2529
 
2941
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
2942
2530
    @needs_write_lock
2943
2531
    def set_revision_history(self, rev_history):
2944
 
        """See Branch.set_revision_history."""
2945
 
        self._set_revision_history(rev_history)
2946
 
 
2947
 
    @needs_write_lock
2948
 
    def _set_revision_history(self, rev_history):
2949
2532
        # Send just the tip revision of the history; the server will generate
2950
2533
        # the full history from that.  If the revision doesn't exist in this
2951
2534
        # branch, NoSuchRevision will be raised.
3009
2592
            _override_hook_target=self, **kwargs)
3010
2593
 
3011
2594
    @needs_read_lock
3012
 
    def push(self, target, overwrite=False, stop_revision=None, lossy=False):
 
2595
    def push(self, target, overwrite=False, stop_revision=None):
3013
2596
        self._ensure_real()
3014
2597
        return self._real_branch.push(
3015
 
            target, overwrite=overwrite, stop_revision=stop_revision, lossy=lossy,
 
2598
            target, overwrite=overwrite, stop_revision=stop_revision,
3016
2599
            _override_hook_source_branch=self)
3017
2600
 
3018
2601
    def is_locked(self):
3028
2611
        # XXX: These should be returned by the set_last_revision_info verb
3029
2612
        old_revno, old_revid = self.last_revision_info()
3030
2613
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
3031
 
        if not revision_id or not isinstance(revision_id, basestring):
3032
 
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
 
2614
        revision_id = ensure_null(revision_id)
3033
2615
        try:
3034
2616
            response = self._call('Branch.set_last_revision_info',
3035
2617
                self._remote_path(), self._lock_token, self._repo_lock_token,
3064
2646
            except errors.UnknownSmartMethod:
3065
2647
                medium._remember_remote_is_before((1, 6))
3066
2648
        self._clear_cached_state_of_remote_branch_only()
3067
 
        self._set_revision_history(self._lefthand_history(revision_id,
 
2649
        self.set_revision_history(self._lefthand_history(revision_id,
3068
2650
            last_rev=last_rev,other_branch=other_branch))
3069
2651
 
3070
2652
    def set_push_location(self, location):
3071
2653
        self._ensure_real()
3072
2654
        return self._real_branch.set_push_location(location)
3073
2655
 
3074
 
    def heads_to_fetch(self):
3075
 
        if self._format._use_default_local_heads_to_fetch():
3076
 
            # We recognise this format, and its heads-to-fetch implementation
3077
 
            # is the default one (tip + tags).  In this case it's cheaper to
3078
 
            # just use the default implementation rather than a special RPC as
3079
 
            # the tip and tags data is cached.
3080
 
            return branch.Branch.heads_to_fetch(self)
3081
 
        medium = self._client._medium
3082
 
        if medium._is_remote_before((2, 4)):
3083
 
            return self._vfs_heads_to_fetch()
3084
 
        try:
3085
 
            return self._rpc_heads_to_fetch()
3086
 
        except errors.UnknownSmartMethod:
3087
 
            medium._remember_remote_is_before((2, 4))
3088
 
            return self._vfs_heads_to_fetch()
3089
 
 
3090
 
    def _rpc_heads_to_fetch(self):
3091
 
        response = self._call('Branch.heads_to_fetch', self._remote_path())
3092
 
        if len(response) != 2:
3093
 
            raise errors.UnexpectedSmartServerResponse(response)
3094
 
        must_fetch, if_present_fetch = response
3095
 
        return set(must_fetch), set(if_present_fetch)
3096
 
 
3097
 
    def _vfs_heads_to_fetch(self):
3098
 
        self._ensure_real()
3099
 
        return self._real_branch.heads_to_fetch()
3100
 
 
3101
2656
 
3102
2657
class RemoteConfig(object):
3103
2658
    """A Config that reads and writes from smart verbs.
3117
2672
        """
3118
2673
        try:
3119
2674
            configobj = self._get_configobj()
3120
 
            section_obj = None
3121
2675
            if section is None:
3122
2676
                section_obj = configobj
3123
2677
            else:
3124
2678
                try:
3125
2679
                    section_obj = configobj[section]
3126
2680
                except KeyError:
3127
 
                    pass
3128
 
            if section_obj is None:
3129
 
                value = default
3130
 
            else:
3131
 
                value = section_obj.get(name, default)
 
2681
                    return default
 
2682
            return section_obj.get(name, default)
3132
2683
        except errors.UnknownSmartMethod:
3133
 
            value = self._vfs_get_option(name, section, default)
3134
 
        for hook in config.OldConfigHooks['get']:
3135
 
            hook(self, name, value)
3136
 
        return value
 
2684
            return self._vfs_get_option(name, section, default)
3137
2685
 
3138
2686
    def _response_to_configobj(self, response):
3139
2687
        if len(response[0]) and response[0][0] != 'ok':
3140
2688
            raise errors.UnexpectedSmartServerResponse(response)
3141
2689
        lines = response[1].read_body_bytes().splitlines()
3142
 
        conf = config.ConfigObj(lines, encoding='utf-8')
3143
 
        for hook in config.OldConfigHooks['load']:
3144
 
            hook(self)
3145
 
        return conf
 
2690
        return config.ConfigObj(lines, encoding='utf-8')
3146
2691
 
3147
2692
 
3148
2693
class RemoteBranchConfig(RemoteConfig):
3167
2712
        medium = self._branch._client._medium
3168
2713
        if medium._is_remote_before((1, 14)):
3169
2714
            return self._vfs_set_option(value, name, section)
3170
 
        if isinstance(value, dict):
3171
 
            if medium._is_remote_before((2, 2)):
3172
 
                return self._vfs_set_option(value, name, section)
3173
 
            return self._set_config_option_dict(value, name, section)
3174
 
        else:
3175
 
            return self._set_config_option(value, name, section)
3176
 
 
3177
 
    def _set_config_option(self, value, name, section):
3178
2715
        try:
3179
2716
            path = self._branch._remote_path()
3180
2717
            response = self._branch._client.call('Branch.set_config_option',
3181
2718
                path, self._branch._lock_token, self._branch._repo_lock_token,
3182
2719
                value.encode('utf8'), name, section or '')
3183
2720
        except errors.UnknownSmartMethod:
3184
 
            medium = self._branch._client._medium
3185
2721
            medium._remember_remote_is_before((1, 14))
3186
2722
            return self._vfs_set_option(value, name, section)
3187
2723
        if response != ():
3188
2724
            raise errors.UnexpectedSmartServerResponse(response)
3189
2725
 
3190
 
    def _serialize_option_dict(self, option_dict):
3191
 
        utf8_dict = {}
3192
 
        for key, value in option_dict.items():
3193
 
            if isinstance(key, unicode):
3194
 
                key = key.encode('utf8')
3195
 
            if isinstance(value, unicode):
3196
 
                value = value.encode('utf8')
3197
 
            utf8_dict[key] = value
3198
 
        return bencode.bencode(utf8_dict)
3199
 
 
3200
 
    def _set_config_option_dict(self, value, name, section):
3201
 
        try:
3202
 
            path = self._branch._remote_path()
3203
 
            serialised_dict = self._serialize_option_dict(value)
3204
 
            response = self._branch._client.call(
3205
 
                'Branch.set_config_option_dict',
3206
 
                path, self._branch._lock_token, self._branch._repo_lock_token,
3207
 
                serialised_dict, name, section or '')
3208
 
        except errors.UnknownSmartMethod:
3209
 
            medium = self._branch._client._medium
3210
 
            medium._remember_remote_is_before((2, 2))
3211
 
            return self._vfs_set_option(value, name, section)
3212
 
        if response != ():
3213
 
            raise errors.UnexpectedSmartServerResponse(response)
3214
 
 
3215
2726
    def _real_object(self):
3216
2727
        self._branch._ensure_real()
3217
2728
        return self._branch._real_branch
3300
2811
                    'Missing key %r in context %r', key_err.args[0], context)
3301
2812
                raise err
3302
2813
 
3303
 
    if err.error_verb == 'NoSuchRevision':
 
2814
    if err.error_verb == 'IncompatibleRepositories':
 
2815
        raise errors.IncompatibleRepositories(err.error_args[0],
 
2816
            err.error_args[1], err.error_args[2])
 
2817
    elif err.error_verb == 'NoSuchRevision':
3304
2818
        raise NoSuchRevision(find('branch'), err.error_args[0])
3305
2819
    elif err.error_verb == 'nosuchrevision':
3306
2820
        raise NoSuchRevision(find('repository'), err.error_args[0])
3307
 
    elif err.error_verb == 'nobranch':
3308
 
        if len(err.error_args) >= 1:
3309
 
            extra = err.error_args[0]
3310
 
        else:
3311
 
            extra = None
3312
 
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
3313
 
            detail=extra)
 
2821
    elif err.error_tuple == ('nobranch',):
 
2822
        raise errors.NotBranchError(path=find('bzrdir').root_transport.base)
3314
2823
    elif err.error_verb == 'norepository':
3315
2824
        raise errors.NoRepositoryPresent(find('bzrdir'))
 
2825
    elif err.error_verb == 'LockContention':
 
2826
        raise errors.LockContention('(remote lock)')
3316
2827
    elif err.error_verb == 'UnlockableTransport':
3317
2828
        raise errors.UnlockableTransport(find('bzrdir').root_transport)
 
2829
    elif err.error_verb == 'LockFailed':
 
2830
        raise errors.LockFailed(err.error_args[0], err.error_args[1])
3318
2831
    elif err.error_verb == 'TokenMismatch':
3319
2832
        raise errors.TokenMismatch(find('token'), '(remote token)')
3320
2833
    elif err.error_verb == 'Diverged':
3321
2834
        raise errors.DivergedBranches(find('branch'), find('other_branch'))
 
2835
    elif err.error_verb == 'TipChangeRejected':
 
2836
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
 
2837
    elif err.error_verb == 'UnstackableBranchFormat':
 
2838
        raise errors.UnstackableBranchFormat(*err.error_args)
 
2839
    elif err.error_verb == 'UnstackableRepositoryFormat':
 
2840
        raise errors.UnstackableRepositoryFormat(*err.error_args)
3322
2841
    elif err.error_verb == 'NotStacked':
3323
2842
        raise errors.NotStacked(branch=find('branch'))
3324
2843
    elif err.error_verb == 'PermissionDenied':
3334
2853
    elif err.error_verb == 'NoSuchFile':
3335
2854
        path = get_path()
3336
2855
        raise errors.NoSuchFile(path)
3337
 
    _translate_error_without_context(err)
3338
 
 
3339
 
 
3340
 
def _translate_error_without_context(err):
3341
 
    """Translate any ErrorFromSmartServer values that don't require context"""
3342
 
    if err.error_verb == 'IncompatibleRepositories':
3343
 
        raise errors.IncompatibleRepositories(err.error_args[0],
3344
 
            err.error_args[1], err.error_args[2])
3345
 
    elif err.error_verb == 'LockContention':
3346
 
        raise errors.LockContention('(remote lock)')
3347
 
    elif err.error_verb == 'LockFailed':
3348
 
        raise errors.LockFailed(err.error_args[0], err.error_args[1])
3349
 
    elif err.error_verb == 'TipChangeRejected':
3350
 
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
3351
 
    elif err.error_verb == 'UnstackableBranchFormat':
3352
 
        raise errors.UnstackableBranchFormat(*err.error_args)
3353
 
    elif err.error_verb == 'UnstackableRepositoryFormat':
3354
 
        raise errors.UnstackableRepositoryFormat(*err.error_args)
3355
2856
    elif err.error_verb == 'FileExists':
3356
2857
        raise errors.FileExists(err.error_args[0])
3357
2858
    elif err.error_verb == 'DirectoryNotEmpty':
3376
2877
            raise UnicodeEncodeError(encoding, val, start, end, reason)
3377
2878
    elif err.error_verb == 'ReadOnlyError':
3378
2879
        raise errors.TransportNotPossible('readonly transport')
3379
 
    elif err.error_verb == 'MemoryError':
3380
 
        raise errors.BzrError("remote server out of memory\n"
3381
 
            "Retry non-remotely, or contact the server admin for details.")
3382
2880
    raise errors.UnknownErrorFromSmartServer(err)