~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

Merge pt1 hooks branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
from bzrlib import (
20
20
    bencode,
21
21
    branch,
22
 
    bzrdir as _mod_bzrdir,
 
22
    bzrdir,
23
23
    config,
24
24
    controldir,
25
25
    debug,
27
27
    graph,
28
28
    lock,
29
29
    lockdir,
 
30
    repository,
30
31
    repository as _mod_repository,
 
32
    revision,
31
33
    revision as _mod_revision,
32
34
    static_tuple,
33
35
    symbol_versioning,
34
36
    urlutils,
35
 
    vf_repository,
36
 
    )
 
37
)
37
38
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
 
39
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
38
40
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
39
41
from bzrlib.errors import (
40
42
    NoSuchRevision,
41
43
    SmartProtocolError,
42
44
    )
43
 
from bzrlib.i18n import gettext
44
45
from bzrlib.lockable_files import LockableFiles
45
46
from bzrlib.smart import client, vfs, repository as smart_repo
46
 
from bzrlib.smart.client import _SmartClient
47
 
from bzrlib.revision import NULL_REVISION
48
 
from bzrlib.repository import RepositoryWriteLockResult, _LazyListJoin
 
47
from bzrlib.revision import ensure_null, NULL_REVISION
 
48
from bzrlib.repository import RepositoryWriteLockResult
49
49
from bzrlib.trace import mutter, note, warning
50
50
 
51
51
 
52
 
_DEFAULT_SEARCH_DEPTH = 100
53
 
 
54
 
 
55
52
class _RpcHelper(object):
56
53
    """Mixin class that helps with issuing RPCs."""
57
54
 
92
89
    return format
93
90
 
94
91
 
95
 
# Note that RemoteBzrDirProber lives in bzrlib.bzrdir so bzrlib.remote
96
 
# does not have to be imported unless a remote format is involved.
97
 
 
98
 
class RemoteBzrDirFormat(_mod_bzrdir.BzrDirMetaFormat1):
99
 
    """Format representing bzrdirs accessed via a smart server"""
100
 
 
101
 
    supports_workingtrees = False
102
 
 
103
 
    def __init__(self):
104
 
        _mod_bzrdir.BzrDirMetaFormat1.__init__(self)
105
 
        # XXX: It's a bit ugly that the network name is here, because we'd
106
 
        # like to believe that format objects are stateless or at least
107
 
        # immutable,  However, we do at least avoid mutating the name after
108
 
        # it's returned.  See <https://bugs.launchpad.net/bzr/+bug/504102>
109
 
        self._network_name = None
110
 
 
111
 
    def __repr__(self):
112
 
        return "%s(_network_name=%r)" % (self.__class__.__name__,
113
 
            self._network_name)
114
 
 
115
 
    def get_format_description(self):
116
 
        if self._network_name:
117
 
            real_format = controldir.network_format_registry.get(self._network_name)
118
 
            return 'Remote: ' + real_format.get_format_description()
119
 
        return 'bzr remote bzrdir'
120
 
 
121
 
    def get_format_string(self):
122
 
        raise NotImplementedError(self.get_format_string)
123
 
 
124
 
    def network_name(self):
125
 
        if self._network_name:
126
 
            return self._network_name
127
 
        else:
128
 
            raise AssertionError("No network name set.")
129
 
 
130
 
    def initialize_on_transport(self, transport):
131
 
        try:
132
 
            # hand off the request to the smart server
133
 
            client_medium = transport.get_smart_medium()
134
 
        except errors.NoSmartMedium:
135
 
            # TODO: lookup the local format from a server hint.
136
 
            local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
137
 
            return local_dir_format.initialize_on_transport(transport)
138
 
        client = _SmartClient(client_medium)
139
 
        path = client.remote_path_from_transport(transport)
140
 
        try:
141
 
            response = client.call('BzrDirFormat.initialize', path)
142
 
        except errors.ErrorFromSmartServer, err:
143
 
            _translate_error(err, path=path)
144
 
        if response[0] != 'ok':
145
 
            raise errors.SmartProtocolError('unexpected response code %s' % (response,))
146
 
        format = RemoteBzrDirFormat()
147
 
        self._supply_sub_formats_to(format)
148
 
        return RemoteBzrDir(transport, format)
149
 
 
150
 
    def parse_NoneTrueFalse(self, arg):
151
 
        if not arg:
152
 
            return None
153
 
        if arg == 'False':
154
 
            return False
155
 
        if arg == 'True':
156
 
            return True
157
 
        raise AssertionError("invalid arg %r" % arg)
158
 
 
159
 
    def _serialize_NoneTrueFalse(self, arg):
160
 
        if arg is False:
161
 
            return 'False'
162
 
        if arg:
163
 
            return 'True'
164
 
        return ''
165
 
 
166
 
    def _serialize_NoneString(self, arg):
167
 
        return arg or ''
168
 
 
169
 
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
170
 
        create_prefix=False, force_new_repo=False, stacked_on=None,
171
 
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
172
 
        shared_repo=False):
173
 
        try:
174
 
            # hand off the request to the smart server
175
 
            client_medium = transport.get_smart_medium()
176
 
        except errors.NoSmartMedium:
177
 
            do_vfs = True
178
 
        else:
179
 
            # Decline to open it if the server doesn't support our required
180
 
            # version (3) so that the VFS-based transport will do it.
181
 
            if client_medium.should_probe():
182
 
                try:
183
 
                    server_version = client_medium.protocol_version()
184
 
                    if server_version != '2':
185
 
                        do_vfs = True
186
 
                    else:
187
 
                        do_vfs = False
188
 
                except errors.SmartProtocolError:
189
 
                    # Apparently there's no usable smart server there, even though
190
 
                    # the medium supports the smart protocol.
191
 
                    do_vfs = True
192
 
            else:
193
 
                do_vfs = False
194
 
        if not do_vfs:
195
 
            client = _SmartClient(client_medium)
196
 
            path = client.remote_path_from_transport(transport)
197
 
            if client_medium._is_remote_before((1, 16)):
198
 
                do_vfs = True
199
 
        if do_vfs:
200
 
            # TODO: lookup the local format from a server hint.
201
 
            local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
202
 
            self._supply_sub_formats_to(local_dir_format)
203
 
            return local_dir_format.initialize_on_transport_ex(transport,
204
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
205
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
206
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
207
 
                make_working_trees=make_working_trees, shared_repo=shared_repo,
208
 
                vfs_only=True)
209
 
        return self._initialize_on_transport_ex_rpc(client, path, transport,
210
 
            use_existing_dir, create_prefix, force_new_repo, stacked_on,
211
 
            stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
212
 
 
213
 
    def _initialize_on_transport_ex_rpc(self, client, path, transport,
214
 
        use_existing_dir, create_prefix, force_new_repo, stacked_on,
215
 
        stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
216
 
        args = []
217
 
        args.append(self._serialize_NoneTrueFalse(use_existing_dir))
218
 
        args.append(self._serialize_NoneTrueFalse(create_prefix))
219
 
        args.append(self._serialize_NoneTrueFalse(force_new_repo))
220
 
        args.append(self._serialize_NoneString(stacked_on))
221
 
        # stack_on_pwd is often/usually our transport
222
 
        if stack_on_pwd:
223
 
            try:
224
 
                stack_on_pwd = transport.relpath(stack_on_pwd)
225
 
                if not stack_on_pwd:
226
 
                    stack_on_pwd = '.'
227
 
            except errors.PathNotChild:
228
 
                pass
229
 
        args.append(self._serialize_NoneString(stack_on_pwd))
230
 
        args.append(self._serialize_NoneString(repo_format_name))
231
 
        args.append(self._serialize_NoneTrueFalse(make_working_trees))
232
 
        args.append(self._serialize_NoneTrueFalse(shared_repo))
233
 
        request_network_name = self._network_name or \
234
 
            _mod_bzrdir.BzrDirFormat.get_default_format().network_name()
235
 
        try:
236
 
            response = client.call('BzrDirFormat.initialize_ex_1.16',
237
 
                request_network_name, path, *args)
238
 
        except errors.UnknownSmartMethod:
239
 
            client._medium._remember_remote_is_before((1,16))
240
 
            local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
241
 
            self._supply_sub_formats_to(local_dir_format)
242
 
            return local_dir_format.initialize_on_transport_ex(transport,
243
 
                use_existing_dir=use_existing_dir, create_prefix=create_prefix,
244
 
                force_new_repo=force_new_repo, stacked_on=stacked_on,
245
 
                stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
246
 
                make_working_trees=make_working_trees, shared_repo=shared_repo,
247
 
                vfs_only=True)
248
 
        except errors.ErrorFromSmartServer, err:
249
 
            _translate_error(err, path=path)
250
 
        repo_path = response[0]
251
 
        bzrdir_name = response[6]
252
 
        require_stacking = response[7]
253
 
        require_stacking = self.parse_NoneTrueFalse(require_stacking)
254
 
        format = RemoteBzrDirFormat()
255
 
        format._network_name = bzrdir_name
256
 
        self._supply_sub_formats_to(format)
257
 
        bzrdir = RemoteBzrDir(transport, format, _client=client)
258
 
        if repo_path:
259
 
            repo_format = response_tuple_to_repo_format(response[1:])
260
 
            if repo_path == '.':
261
 
                repo_path = ''
262
 
            if repo_path:
263
 
                repo_bzrdir_format = RemoteBzrDirFormat()
264
 
                repo_bzrdir_format._network_name = response[5]
265
 
                repo_bzr = RemoteBzrDir(transport.clone(repo_path),
266
 
                    repo_bzrdir_format)
267
 
            else:
268
 
                repo_bzr = bzrdir
269
 
            final_stack = response[8] or None
270
 
            final_stack_pwd = response[9] or None
271
 
            if final_stack_pwd:
272
 
                final_stack_pwd = urlutils.join(
273
 
                    transport.base, final_stack_pwd)
274
 
            remote_repo = RemoteRepository(repo_bzr, repo_format)
275
 
            if len(response) > 10:
276
 
                # Updated server verb that locks remotely.
277
 
                repo_lock_token = response[10] or None
278
 
                remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
279
 
                if repo_lock_token:
280
 
                    remote_repo.dont_leave_lock_in_place()
281
 
            else:
282
 
                remote_repo.lock_write()
283
 
            policy = _mod_bzrdir.UseExistingRepository(remote_repo, final_stack,
284
 
                final_stack_pwd, require_stacking)
285
 
            policy.acquire_repository()
286
 
        else:
287
 
            remote_repo = None
288
 
            policy = None
289
 
        bzrdir._format.set_branch_format(self.get_branch_format())
290
 
        if require_stacking:
291
 
            # The repo has already been created, but we need to make sure that
292
 
            # we'll make a stackable branch.
293
 
            bzrdir._format.require_stacking(_skip_repo=True)
294
 
        return remote_repo, bzrdir, require_stacking, policy
295
 
 
296
 
    def _open(self, transport):
297
 
        return RemoteBzrDir(transport, self)
298
 
 
299
 
    def __eq__(self, other):
300
 
        if not isinstance(other, RemoteBzrDirFormat):
301
 
            return False
302
 
        return self.get_format_description() == other.get_format_description()
303
 
 
304
 
    def __return_repository_format(self):
305
 
        # Always return a RemoteRepositoryFormat object, but if a specific bzr
306
 
        # repository format has been asked for, tell the RemoteRepositoryFormat
307
 
        # that it should use that for init() etc.
308
 
        result = RemoteRepositoryFormat()
309
 
        custom_format = getattr(self, '_repository_format', None)
310
 
        if custom_format:
311
 
            if isinstance(custom_format, RemoteRepositoryFormat):
312
 
                return custom_format
313
 
            else:
314
 
                # We will use the custom format to create repositories over the
315
 
                # wire; expose its details like rich_root_data for code to
316
 
                # query
317
 
                result._custom_format = custom_format
318
 
        return result
319
 
 
320
 
    def get_branch_format(self):
321
 
        result = _mod_bzrdir.BzrDirMetaFormat1.get_branch_format(self)
322
 
        if not isinstance(result, RemoteBranchFormat):
323
 
            new_result = RemoteBranchFormat()
324
 
            new_result._custom_format = result
325
 
            # cache the result
326
 
            self.set_branch_format(new_result)
327
 
            result = new_result
328
 
        return result
329
 
 
330
 
    repository_format = property(__return_repository_format,
331
 
        _mod_bzrdir.BzrDirMetaFormat1._set_repository_format) #.im_func)
332
 
 
333
 
 
334
 
class RemoteBzrDir(_mod_bzrdir.BzrDir, _RpcHelper):
 
92
# Note: RemoteBzrDirFormat is in bzrdir.py
 
93
 
 
94
class RemoteBzrDir(BzrDir, _RpcHelper):
335
95
    """Control directory on a remote server, accessed via bzr:// or similar."""
336
96
 
337
97
    def __init__(self, transport, format, _client=None, _force_probe=False):
340
100
        :param _client: Private parameter for testing. Disables probing and the
341
101
            use of a real bzrdir.
342
102
        """
343
 
        _mod_bzrdir.BzrDir.__init__(self, transport, format)
 
103
        BzrDir.__init__(self, transport, format)
344
104
        # this object holds a delegated bzrdir that uses file-level operations
345
105
        # to talk to the other side
346
106
        self._real_bzrdir = None
406
166
                import traceback
407
167
                warning('VFS BzrDir access triggered\n%s',
408
168
                    ''.join(traceback.format_stack()))
409
 
            self._real_bzrdir = _mod_bzrdir.BzrDir.open_from_transport(
 
169
            self._real_bzrdir = BzrDir.open_from_transport(
410
170
                self.root_transport, _server_formats=False)
411
171
            self._format._network_name = \
412
172
                self._real_bzrdir._format.network_name()
418
178
        # Prevent aliasing problems in the next_open_branch_result cache.
419
179
        # See create_branch for rationale.
420
180
        self._next_open_branch_result = None
421
 
        return _mod_bzrdir.BzrDir.break_lock(self)
 
181
        return BzrDir.break_lock(self)
422
182
 
423
183
    def _vfs_cloning_metadir(self, require_stacking=False):
424
184
        self._ensure_real()
457
217
        branch_ref, branch_name = branch_info
458
218
        format = controldir.network_format_registry.get(control_name)
459
219
        if repo_name:
460
 
            format.repository_format = _mod_repository.network_format_registry.get(
 
220
            format.repository_format = repository.network_format_registry.get(
461
221
                repo_name)
462
222
        if branch_ref == 'ref':
463
223
            # XXX: we need possible_transports here to avoid reopening the
464
224
            # connection to the referenced location
465
 
            ref_bzrdir = _mod_bzrdir.BzrDir.open(branch_name)
 
225
            ref_bzrdir = BzrDir.open(branch_name)
466
226
            branch_format = ref_bzrdir.cloning_metadir().get_branch_format()
467
227
            format.set_branch_format(branch_format)
468
228
        elif branch_ref == 'branch':
487
247
        self._ensure_real()
488
248
        self._real_bzrdir.destroy_repository()
489
249
 
490
 
    def create_branch(self, name=None, repository=None,
491
 
                      append_revisions_only=None):
 
250
    def create_branch(self, name=None, repository=None):
492
251
        # as per meta1 formats - just delegate to the format object which may
493
252
        # be parameterised.
494
253
        real_branch = self._format.get_branch_format().initialize(self,
495
 
            name=name, repository=repository,
496
 
            append_revisions_only=append_revisions_only)
 
254
            name=name, repository=repository)
497
255
        if not isinstance(real_branch, RemoteBranch):
498
256
            if not isinstance(repository, RemoteRepository):
499
257
                raise AssertionError(
675
433
 
676
434
    def _path_for_remote_call(self, client):
677
435
        """Return the path to be used for this bzrdir in a remote call."""
678
 
        return urlutils.split_segment_parameters_raw(
679
 
            client.remote_path_from_transport(self.root_transport))[0]
 
436
        return client.remote_path_from_transport(self.root_transport)
680
437
 
681
438
    def get_branch_transport(self, branch_format, name=None):
682
439
        self._ensure_real()
694
451
        """Upgrading of remote bzrdirs is not supported yet."""
695
452
        return False
696
453
 
697
 
    def needs_format_conversion(self, format):
 
454
    def needs_format_conversion(self, format=None):
698
455
        """Upgrading of remote bzrdirs is not supported yet."""
 
456
        if format is None:
 
457
            symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
 
458
                % 'needs_format_conversion(format=None)')
699
459
        return False
700
460
 
701
461
    def clone(self, url, revision_id=None, force_new_repo=False,
708
468
        return RemoteBzrDirConfig(self)
709
469
 
710
470
 
711
 
class RemoteRepositoryFormat(vf_repository.VersionedFileRepositoryFormat):
 
471
class RemoteRepositoryFormat(repository.RepositoryFormat):
712
472
    """Format for repositories accessed over a _SmartClient.
713
473
 
714
474
    Instances of this repository are represented by RemoteRepository
729
489
    """
730
490
 
731
491
    _matchingbzrdir = RemoteBzrDirFormat()
732
 
    supports_full_versioned_files = True
733
 
    supports_leaving_lock = True
734
492
 
735
493
    def __init__(self):
736
 
        _mod_repository.RepositoryFormat.__init__(self)
 
494
        repository.RepositoryFormat.__init__(self)
737
495
        self._custom_format = None
738
496
        self._network_name = None
739
497
        self._creating_bzrdir = None
740
 
        self._revision_graph_can_have_wrong_parents = None
741
498
        self._supports_chks = None
742
499
        self._supports_external_lookups = None
743
500
        self._supports_tree_reference = None
744
 
        self._supports_funky_characters = None
745
 
        self._supports_nesting_repositories = None
746
501
        self._rich_root_data = None
747
502
 
748
503
    def __repr__(self):
777
532
        return self._supports_external_lookups
778
533
 
779
534
    @property
780
 
    def supports_funky_characters(self):
781
 
        if self._supports_funky_characters is None:
782
 
            self._ensure_real()
783
 
            self._supports_funky_characters = \
784
 
                self._custom_format.supports_funky_characters
785
 
        return self._supports_funky_characters
786
 
 
787
 
    @property
788
 
    def supports_nesting_repositories(self):
789
 
        if self._supports_nesting_repositories is None:
790
 
            self._ensure_real()
791
 
            self._supports_nesting_repositories = \
792
 
                self._custom_format.supports_nesting_repositories
793
 
        return self._supports_nesting_repositories
794
 
 
795
 
    @property
796
535
    def supports_tree_reference(self):
797
536
        if self._supports_tree_reference is None:
798
537
            self._ensure_real()
800
539
                self._custom_format.supports_tree_reference
801
540
        return self._supports_tree_reference
802
541
 
803
 
    @property
804
 
    def revision_graph_can_have_wrong_parents(self):
805
 
        if self._revision_graph_can_have_wrong_parents is None:
806
 
            self._ensure_real()
807
 
            self._revision_graph_can_have_wrong_parents = \
808
 
                self._custom_format.revision_graph_can_have_wrong_parents
809
 
        return self._revision_graph_can_have_wrong_parents
810
 
 
811
542
    def _vfs_initialize(self, a_bzrdir, shared):
812
543
        """Helper for common code in initialize."""
813
544
        if self._custom_format:
848
579
            network_name = self._network_name
849
580
        else:
850
581
            # Select the current bzrlib default and ask for that.
851
 
            reference_bzrdir_format = _mod_bzrdir.format_registry.get('default')()
 
582
            reference_bzrdir_format = bzrdir.format_registry.get('default')()
852
583
            reference_format = reference_bzrdir_format.repository_format
853
584
            network_name = reference_format.network_name()
854
585
        # 2) try direct creation via RPC
880
611
 
881
612
    def _ensure_real(self):
882
613
        if self._custom_format is None:
883
 
            self._custom_format = _mod_repository.network_format_registry.get(
 
614
            self._custom_format = repository.network_format_registry.get(
884
615
                self._network_name)
885
616
 
886
617
    @property
982
713
        # transport, but I'm not sure it's worth making this method
983
714
        # optional -- mbp 2010-04-21
984
715
        return self.bzrdir.get_repository_transport(None)
985
 
 
 
716
        
986
717
    def __str__(self):
987
718
        return "%s(%s)" % (self.__class__.__name__, self.base)
988
719
 
1096
827
    def find_text_key_references(self):
1097
828
        """Find the text key references within the repository.
1098
829
 
 
830
        :return: a dictionary mapping (file_id, revision_id) tuples to altered file-ids to an iterable of
 
831
        revision_ids. Each altered file-ids has the exact revision_ids that
 
832
        altered it listed explicitly.
1099
833
        :return: A dictionary mapping text keys ((fileid, revision_id) tuples)
1100
834
            to whether they were referred to by the inventory of the
1101
835
            revision_id that they contain. The inventory texts from all present
1119
853
        """Private method for using with old (< 1.2) servers to fallback."""
1120
854
        if revision_id is None:
1121
855
            revision_id = ''
1122
 
        elif _mod_revision.is_null(revision_id):
 
856
        elif revision.is_null(revision_id):
1123
857
            return {}
1124
858
 
1125
859
        path = self.bzrdir._path_for_remote_call(self._client)
1149
883
        return RemoteStreamSource(self, to_format)
1150
884
 
1151
885
    @needs_read_lock
1152
 
    def get_file_graph(self):
1153
 
        return graph.Graph(self.texts)
1154
 
 
1155
 
    @needs_read_lock
1156
886
    def has_revision(self, revision_id):
1157
887
        """True if this repository has a copy of the revision."""
1158
888
        # Copy of bzrlib.repository.Repository.has_revision
1210
940
        """See Repository.gather_stats()."""
1211
941
        path = self.bzrdir._path_for_remote_call(self._client)
1212
942
        # revid can be None to indicate no revisions, not just NULL_REVISION
1213
 
        if revid is None or _mod_revision.is_null(revid):
 
943
        if revid is None or revision.is_null(revid):
1214
944
            fmt_revid = ''
1215
945
        else:
1216
946
            fmt_revid = revid
1499
1229
 
1500
1230
    def get_commit_builder(self, branch, parents, config, timestamp=None,
1501
1231
                           timezone=None, committer=None, revprops=None,
1502
 
                           revision_id=None, lossy=False):
 
1232
                           revision_id=None):
1503
1233
        # FIXME: It ought to be possible to call this without immediately
1504
1234
        # triggering _ensure_real.  For now it's the easiest thing to do.
1505
1235
        self._ensure_real()
1506
1236
        real_repo = self._real_repository
1507
1237
        builder = real_repo.get_commit_builder(branch, parents,
1508
1238
                config, timestamp=timestamp, timezone=timezone,
1509
 
                committer=committer, revprops=revprops,
1510
 
                revision_id=revision_id, lossy=lossy)
 
1239
                committer=committer, revprops=revprops, revision_id=revision_id)
1511
1240
        return builder
1512
1241
 
1513
1242
    def add_fallback_repository(self, repository):
1521
1250
        # We need to accumulate additional repositories here, to pass them in
1522
1251
        # on various RPC's.
1523
1252
        #
1524
 
        # Make the check before we lock: this raises an exception.
1525
 
        self._check_fallback_repository(repository)
1526
1253
        if self.is_locked():
1527
1254
            # We will call fallback.unlock() when we transition to the unlocked
1528
1255
            # state, so always add a lock here. If a caller passes us a locked
1529
1256
            # repository, they are responsible for unlocking it later.
1530
1257
            repository.lock_read()
 
1258
        self._check_fallback_repository(repository)
1531
1259
        self._fallback_repositories.append(repository)
1532
1260
        # If self._real_repository was parameterised already (e.g. because a
1533
1261
        # _real_branch had its get_stacked_on_url method called), then the
1622
1350
    @needs_read_lock
1623
1351
    def search_missing_revision_ids(self, other,
1624
1352
            revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1625
 
            find_ghosts=True, revision_ids=None, if_present_ids=None,
1626
 
            limit=None):
 
1353
            find_ghosts=True, revision_ids=None, if_present_ids=None):
1627
1354
        """Return the revision ids that other has that this does not.
1628
1355
 
1629
1356
        These are returned in topological order.
1640
1367
                    'revision_ids is mutually exclusive with revision_id')
1641
1368
            if revision_id is not None:
1642
1369
                revision_ids = [revision_id]
1643
 
        inter_repo = _mod_repository.InterRepository.get(other, self)
 
1370
        inter_repo = repository.InterRepository.get(other, self)
1644
1371
        return inter_repo.search_missing_revision_ids(
1645
1372
            find_ghosts=find_ghosts, revision_ids=revision_ids,
1646
 
            if_present_ids=if_present_ids, limit=limit)
 
1373
            if_present_ids=if_present_ids)
1647
1374
 
1648
 
    def fetch(self, source, revision_id=None, find_ghosts=False,
 
1375
    def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
1649
1376
            fetch_spec=None):
1650
1377
        # No base implementation to use as RemoteRepository is not a subclass
1651
1378
        # of Repository; so this is a copy of Repository.fetch().
1662
1389
            # check that last_revision is in 'from' and then return a
1663
1390
            # no-operation.
1664
1391
            if (revision_id is not None and
1665
 
                not _mod_revision.is_null(revision_id)):
 
1392
                not revision.is_null(revision_id)):
1666
1393
                self.get_revision(revision_id)
1667
1394
            return 0, []
1668
1395
        # if there is no specific appropriate InterRepository, this will get
1669
1396
        # the InterRepository base class, which raises an
1670
1397
        # IncompatibleRepositories when asked to fetch.
1671
 
        inter = _mod_repository.InterRepository.get(source, self)
1672
 
        return inter.fetch(revision_id=revision_id,
 
1398
        inter = repository.InterRepository.get(source, self)
 
1399
        return inter.fetch(revision_id=revision_id, pb=pb,
1673
1400
            find_ghosts=find_ghosts, fetch_spec=fetch_spec)
1674
1401
 
1675
1402
    def create_bundle(self, target, base, fileobj, format=None):
1677
1404
        self._real_repository.create_bundle(target, base, fileobj, format)
1678
1405
 
1679
1406
    @needs_read_lock
1680
 
    @symbol_versioning.deprecated_method(
1681
 
        symbol_versioning.deprecated_in((2, 4, 0)))
1682
1407
    def get_ancestry(self, revision_id, topo_sorted=True):
1683
1408
        self._ensure_real()
1684
1409
        return self._real_repository.get_ancestry(revision_id, topo_sorted)
1698
1423
        self._ensure_real()
1699
1424
        return self._real_repository.iter_files_bytes(desired_files)
1700
1425
 
1701
 
    def get_cached_parent_map(self, revision_ids):
1702
 
        """See bzrlib.CachingParentsProvider.get_cached_parent_map"""
1703
 
        return self._unstacked_provider.get_cached_parent_map(revision_ids)
1704
 
 
1705
1426
    def get_parent_map(self, revision_ids):
1706
1427
        """See bzrlib.Graph.get_parent_map()."""
1707
1428
        return self._make_parents_provider().get_parent_map(revision_ids)
1765
1486
        if parents_map is None:
1766
1487
            # Repository is not locked, so there's no cache.
1767
1488
            parents_map = {}
1768
 
        if _DEFAULT_SEARCH_DEPTH <= 0:
1769
 
            (start_set, stop_keys,
1770
 
             key_count) = graph.search_result_from_parent_map(
1771
 
                parents_map, self._unstacked_provider.missing_keys)
1772
 
        else:
1773
 
            (start_set, stop_keys,
1774
 
             key_count) = graph.limited_search_result_from_parent_map(
1775
 
                parents_map, self._unstacked_provider.missing_keys,
1776
 
                keys, depth=_DEFAULT_SEARCH_DEPTH)
 
1489
        # start_set is all the keys in the cache
 
1490
        start_set = set(parents_map)
 
1491
        # result set is all the references to keys in the cache
 
1492
        result_parents = set()
 
1493
        for parents in parents_map.itervalues():
 
1494
            result_parents.update(parents)
 
1495
        stop_keys = result_parents.difference(start_set)
 
1496
        # We don't need to send ghosts back to the server as a position to
 
1497
        # stop either.
 
1498
        stop_keys.difference_update(self._unstacked_provider.missing_keys)
 
1499
        key_count = len(parents_map)
 
1500
        if (NULL_REVISION in result_parents
 
1501
            and NULL_REVISION in self._unstacked_provider.missing_keys):
 
1502
            # If we pruned NULL_REVISION from the stop_keys because it's also
 
1503
            # in our cache of "missing" keys we need to increment our key count
 
1504
            # by 1, because the reconsitituted SearchResult on the server will
 
1505
            # still consider NULL_REVISION to be an included key.
 
1506
            key_count += 1
 
1507
        included_keys = start_set.intersection(result_parents)
 
1508
        start_set.difference_update(included_keys)
1777
1509
        recipe = ('manual', start_set, stop_keys, key_count)
1778
1510
        body = self._serialise_search_recipe(recipe)
1779
1511
        path = self.bzrdir._path_for_remote_call(self._client)
1883
1615
        from bzrlib import osutils
1884
1616
        import tarfile
1885
1617
        # TODO: Maybe a progress bar while streaming the tarball?
1886
 
        note(gettext("Copying repository content as tarball..."))
 
1618
        note("Copying repository content as tarball...")
1887
1619
        tar_file = self._get_tarball('bz2')
1888
1620
        if tar_file is None:
1889
1621
            return None
1894
1626
            tmpdir = osutils.mkdtemp()
1895
1627
            try:
1896
1628
                _extract_tar(tar, tmpdir)
1897
 
                tmp_bzrdir = _mod_bzrdir.BzrDir.open(tmpdir)
 
1629
                tmp_bzrdir = BzrDir.open(tmpdir)
1898
1630
                tmp_repo = tmp_bzrdir.open_repository()
1899
1631
                tmp_repo.copy_content_into(destination, revision_id)
1900
1632
            finally:
1985
1717
    def supports_rich_root(self):
1986
1718
        return self._format.rich_root_data
1987
1719
 
1988
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1989
1720
    def iter_reverse_revision_history(self, revision_id):
1990
1721
        self._ensure_real()
1991
1722
        return self._real_repository.iter_reverse_revision_history(revision_id)
2012
1743
        return self._real_repository.item_keys_introduced_by(revision_ids,
2013
1744
            _files_pb=_files_pb)
2014
1745
 
 
1746
    def revision_graph_can_have_wrong_parents(self):
 
1747
        # The answer depends on the remote repo format.
 
1748
        self._ensure_real()
 
1749
        return self._real_repository.revision_graph_can_have_wrong_parents()
 
1750
 
2015
1751
    def _find_inconsistent_revision_parents(self, revisions_iterator=None):
2016
1752
        self._ensure_real()
2017
1753
        return self._real_repository._find_inconsistent_revision_parents(
2025
1761
        providers = [self._unstacked_provider]
2026
1762
        if other is not None:
2027
1763
            providers.insert(0, other)
2028
 
        return graph.StackedParentsProvider(_LazyListJoin(
2029
 
            providers, self._fallback_repositories))
 
1764
        providers.extend(r._make_parents_provider() for r in
 
1765
                         self._fallback_repositories)
 
1766
        return graph.StackedParentsProvider(providers)
2030
1767
 
2031
1768
    def _serialise_search_recipe(self, recipe):
2032
1769
        """Serialise a graph search recipe.
2056
1793
            raise errors.UnexpectedSmartServerResponse(response)
2057
1794
 
2058
1795
 
2059
 
class RemoteStreamSink(vf_repository.StreamSink):
 
1796
class RemoteStreamSink(repository.StreamSink):
2060
1797
 
2061
1798
    def _insert_real(self, stream, src_format, resume_tokens):
2062
1799
        self.target_repo._ensure_real()
2163
1900
        self._last_substream and self._last_stream so that the stream can be
2164
1901
        resumed by _resume_stream_with_vfs.
2165
1902
        """
2166
 
 
 
1903
                    
2167
1904
        stream_iter = iter(stream)
2168
1905
        for substream_kind, substream in stream_iter:
2169
1906
            if substream_kind == 'inventory-deltas':
2172
1909
                return
2173
1910
            else:
2174
1911
                yield substream_kind, substream
2175
 
 
2176
 
 
2177
 
class RemoteStreamSource(vf_repository.StreamSource):
 
1912
            
 
1913
 
 
1914
class RemoteStreamSource(repository.StreamSource):
2178
1915
    """Stream data from a remote server."""
2179
1916
 
2180
1917
    def get_stream(self, search):
2363
2100
        return a_bzrdir.open_branch(name=name, 
2364
2101
            ignore_fallbacks=ignore_fallbacks)
2365
2102
 
2366
 
    def _vfs_initialize(self, a_bzrdir, name, append_revisions_only):
 
2103
    def _vfs_initialize(self, a_bzrdir, name):
2367
2104
        # Initialisation when using a local bzrdir object, or a non-vfs init
2368
2105
        # method is not available on the server.
2369
2106
        # self._custom_format is always set - the start of initialize ensures
2371
2108
        if isinstance(a_bzrdir, RemoteBzrDir):
2372
2109
            a_bzrdir._ensure_real()
2373
2110
            result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
2374
 
                name, append_revisions_only=append_revisions_only)
 
2111
                name)
2375
2112
        else:
2376
2113
            # We assume the bzrdir is parameterised; it may not be.
2377
 
            result = self._custom_format.initialize(a_bzrdir, name,
2378
 
                append_revisions_only=append_revisions_only)
 
2114
            result = self._custom_format.initialize(a_bzrdir, name)
2379
2115
        if (isinstance(a_bzrdir, RemoteBzrDir) and
2380
2116
            not isinstance(result, RemoteBranch)):
2381
2117
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
2382
2118
                                  name=name)
2383
2119
        return result
2384
2120
 
2385
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2386
 
                   append_revisions_only=None):
 
2121
    def initialize(self, a_bzrdir, name=None, repository=None):
2387
2122
        # 1) get the network name to use.
2388
2123
        if self._custom_format:
2389
2124
            network_name = self._custom_format.network_name()
2390
2125
        else:
2391
2126
            # Select the current bzrlib default and ask for that.
2392
 
            reference_bzrdir_format = _mod_bzrdir.format_registry.get('default')()
 
2127
            reference_bzrdir_format = bzrdir.format_registry.get('default')()
2393
2128
            reference_format = reference_bzrdir_format.get_branch_format()
2394
2129
            self._custom_format = reference_format
2395
2130
            network_name = reference_format.network_name()
2396
2131
        # Being asked to create on a non RemoteBzrDir:
2397
2132
        if not isinstance(a_bzrdir, RemoteBzrDir):
2398
 
            return self._vfs_initialize(a_bzrdir, name=name,
2399
 
                append_revisions_only=append_revisions_only)
 
2133
            return self._vfs_initialize(a_bzrdir, name=name)
2400
2134
        medium = a_bzrdir._client._medium
2401
2135
        if medium._is_remote_before((1, 13)):
2402
 
            return self._vfs_initialize(a_bzrdir, name=name,
2403
 
                append_revisions_only=append_revisions_only)
 
2136
            return self._vfs_initialize(a_bzrdir, name=name)
2404
2137
        # Creating on a remote bzr dir.
2405
2138
        # 2) try direct creation via RPC
2406
2139
        path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
2413
2146
        except errors.UnknownSmartMethod:
2414
2147
            # Fallback - use vfs methods
2415
2148
            medium._remember_remote_is_before((1, 13))
2416
 
            return self._vfs_initialize(a_bzrdir, name=name,
2417
 
                    append_revisions_only=append_revisions_only)
 
2149
            return self._vfs_initialize(a_bzrdir, name=name)
2418
2150
        if response[0] != 'ok':
2419
2151
            raise errors.UnexpectedSmartServerResponse(response)
2420
2152
        # Turn the response into a RemoteRepository object.
2422
2154
        repo_format = response_tuple_to_repo_format(response[3:])
2423
2155
        repo_path = response[2]
2424
2156
        if repository is not None:
2425
 
            remote_repo_url = urlutils.join(a_bzrdir.user_url, repo_path)
 
2157
            remote_repo_url = urlutils.join(medium.base, repo_path)
2426
2158
            url_diff = urlutils.relative_url(repository.user_url,
2427
2159
                    remote_repo_url)
2428
2160
            if url_diff != '.':
2429
2161
                raise AssertionError(
2430
2162
                    'repository.user_url %r does not match URL from server '
2431
2163
                    'response (%r + %r)'
2432
 
                    % (repository.user_url, a_bzrdir.user_url, repo_path))
 
2164
                    % (repository.user_url, medium.base, repo_path))
2433
2165
            remote_repo = repository
2434
2166
        else:
2435
2167
            if repo_path == '':
2441
2173
            remote_repo = RemoteRepository(repo_bzrdir, repo_format)
2442
2174
        remote_branch = RemoteBranch(a_bzrdir, remote_repo,
2443
2175
            format=format, setup_stacking=False, name=name)
2444
 
        if append_revisions_only:
2445
 
            remote_branch.set_append_revisions_only(append_revisions_only)
2446
2176
        # XXX: We know this is a new branch, so it must have revno 0, revid
2447
2177
        # NULL_REVISION. Creating the branch locked would make this be unable
2448
2178
        # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
2467
2197
        self._ensure_real()
2468
2198
        return self._custom_format.supports_set_append_revisions_only()
2469
2199
 
2470
 
    def _use_default_local_heads_to_fetch(self):
2471
 
        # If the branch format is a metadir format *and* its heads_to_fetch
2472
 
        # implementation is not overridden vs the base class, we can use the
2473
 
        # base class logic rather than use the heads_to_fetch RPC.  This is
2474
 
        # usually cheaper in terms of net round trips, as the last-revision and
2475
 
        # tags info fetched is cached and would be fetched anyway.
2476
 
        self._ensure_real()
2477
 
        if isinstance(self._custom_format, branch.BranchFormatMetadir):
2478
 
            branch_class = self._custom_format._branch_class()
2479
 
            heads_to_fetch_impl = branch_class.heads_to_fetch.im_func
2480
 
            if heads_to_fetch_impl is branch.Branch.heads_to_fetch.im_func:
2481
 
                return True
2482
 
        return False
2483
2200
 
2484
2201
class RemoteBranch(branch.Branch, _RpcHelper, lock._RelockDebugMixin):
2485
2202
    """Branch stored on a server accessed by HPSS RPC.
2643
2360
                self.bzrdir, self._client)
2644
2361
        return self._control_files
2645
2362
 
2646
 
    def _get_checkout_format(self, lightweight=False):
 
2363
    def _get_checkout_format(self):
2647
2364
        self._ensure_real()
2648
 
        if lightweight:
2649
 
            format = RemoteBzrDirFormat()
2650
 
            self.bzrdir._format._supply_sub_formats_to(format)
2651
 
            format.workingtree_format = self._real_branch._get_checkout_format(
2652
 
                lightweight=lightweight).workingtree_format
2653
 
            return format
2654
 
        else:
2655
 
            return self._real_branch._get_checkout_format(lightweight=False)
 
2365
        return self._real_branch._get_checkout_format()
2656
2366
 
2657
2367
    def get_physical_lock_status(self):
2658
2368
        """See Branch.get_physical_lock_status()."""
2691
2401
            self._is_stacked = False
2692
2402
        else:
2693
2403
            self._is_stacked = True
2694
 
 
 
2404
        
2695
2405
    def _vfs_get_tags_bytes(self):
2696
2406
        self._ensure_real()
2697
2407
        return self._real_branch._get_tags_bytes()
2879
2589
            missing_parent = parent_map[missing_parent]
2880
2590
        raise errors.RevisionNotPresent(missing_parent, self.repository)
2881
2591
 
2882
 
    def _read_last_revision_info(self):
 
2592
    def _last_revision_info(self):
2883
2593
        response = self._call('Branch.last_revision_info', self._remote_path())
2884
2594
        if response[0] != 'ok':
2885
2595
            raise SmartProtocolError('unexpected response code %s' % (response,))
2948
2658
            raise errors.UnexpectedSmartServerResponse(response)
2949
2659
        self._run_post_change_branch_tip_hooks(old_revno, old_revid)
2950
2660
 
2951
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
2952
2661
    @needs_write_lock
2953
2662
    def set_revision_history(self, rev_history):
2954
 
        """See Branch.set_revision_history."""
2955
 
        self._set_revision_history(rev_history)
2956
 
 
2957
 
    @needs_write_lock
2958
 
    def _set_revision_history(self, rev_history):
2959
2663
        # Send just the tip revision of the history; the server will generate
2960
2664
        # the full history from that.  If the revision doesn't exist in this
2961
2665
        # branch, NoSuchRevision will be raised.
3019
2723
            _override_hook_target=self, **kwargs)
3020
2724
 
3021
2725
    @needs_read_lock
3022
 
    def push(self, target, overwrite=False, stop_revision=None, lossy=False):
 
2726
    def push(self, target, overwrite=False, stop_revision=None):
3023
2727
        self._ensure_real()
3024
2728
        return self._real_branch.push(
3025
 
            target, overwrite=overwrite, stop_revision=stop_revision, lossy=lossy,
 
2729
            target, overwrite=overwrite, stop_revision=stop_revision,
3026
2730
            _override_hook_source_branch=self)
3027
2731
 
3028
2732
    def is_locked(self):
3038
2742
        # XXX: These should be returned by the set_last_revision_info verb
3039
2743
        old_revno, old_revid = self.last_revision_info()
3040
2744
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
3041
 
        if not revision_id or not isinstance(revision_id, basestring):
3042
 
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
 
2745
        revision_id = ensure_null(revision_id)
3043
2746
        try:
3044
2747
            response = self._call('Branch.set_last_revision_info',
3045
2748
                self._remote_path(), self._lock_token, self._repo_lock_token,
3074
2777
            except errors.UnknownSmartMethod:
3075
2778
                medium._remember_remote_is_before((1, 6))
3076
2779
        self._clear_cached_state_of_remote_branch_only()
3077
 
        self._set_revision_history(self._lefthand_history(revision_id,
 
2780
        self.set_revision_history(self._lefthand_history(revision_id,
3078
2781
            last_rev=last_rev,other_branch=other_branch))
3079
2782
 
3080
2783
    def set_push_location(self, location):
3081
2784
        self._ensure_real()
3082
2785
        return self._real_branch.set_push_location(location)
3083
2786
 
3084
 
    def heads_to_fetch(self):
3085
 
        if self._format._use_default_local_heads_to_fetch():
3086
 
            # We recognise this format, and its heads-to-fetch implementation
3087
 
            # is the default one (tip + tags).  In this case it's cheaper to
3088
 
            # just use the default implementation rather than a special RPC as
3089
 
            # the tip and tags data is cached.
3090
 
            return branch.Branch.heads_to_fetch(self)
3091
 
        medium = self._client._medium
3092
 
        if medium._is_remote_before((2, 4)):
3093
 
            return self._vfs_heads_to_fetch()
3094
 
        try:
3095
 
            return self._rpc_heads_to_fetch()
3096
 
        except errors.UnknownSmartMethod:
3097
 
            medium._remember_remote_is_before((2, 4))
3098
 
            return self._vfs_heads_to_fetch()
3099
 
 
3100
 
    def _rpc_heads_to_fetch(self):
3101
 
        response = self._call('Branch.heads_to_fetch', self._remote_path())
3102
 
        if len(response) != 2:
3103
 
            raise errors.UnexpectedSmartServerResponse(response)
3104
 
        must_fetch, if_present_fetch = response
3105
 
        return set(must_fetch), set(if_present_fetch)
3106
 
 
3107
 
    def _vfs_heads_to_fetch(self):
3108
 
        self._ensure_real()
3109
 
        return self._real_branch.heads_to_fetch()
3110
 
 
3111
2787
 
3112
2788
class RemoteConfig(object):
3113
2789
    """A Config that reads and writes from smart verbs.
3127
2803
        """
3128
2804
        try:
3129
2805
            configobj = self._get_configobj()
3130
 
            section_obj = None
3131
2806
            if section is None:
3132
2807
                section_obj = configobj
3133
2808
            else:
3134
2809
                try:
3135
2810
                    section_obj = configobj[section]
3136
2811
                except KeyError:
3137
 
                    pass
3138
 
            if section_obj is None:
3139
 
                value = default
3140
 
            else:
3141
 
                value = section_obj.get(name, default)
 
2812
                    return default
 
2813
            return section_obj.get(name, default)
3142
2814
        except errors.UnknownSmartMethod:
3143
 
            value = self._vfs_get_option(name, section, default)
3144
 
        for hook in config.OldConfigHooks['get']:
3145
 
            hook(self, name, value)
3146
 
        return value
 
2815
            return self._vfs_get_option(name, section, default)
3147
2816
 
3148
2817
    def _response_to_configobj(self, response):
3149
2818
        if len(response[0]) and response[0][0] != 'ok':
3150
2819
            raise errors.UnexpectedSmartServerResponse(response)
3151
2820
        lines = response[1].read_body_bytes().splitlines()
3152
 
        conf = config.ConfigObj(lines, encoding='utf-8')
3153
 
        for hook in config.OldConfigHooks['load']:
3154
 
            hook(self)
3155
 
        return conf
 
2821
        return config.ConfigObj(lines, encoding='utf-8')
3156
2822
 
3157
2823
 
3158
2824
class RemoteBranchConfig(RemoteConfig):
3310
2976
                    'Missing key %r in context %r', key_err.args[0], context)
3311
2977
                raise err
3312
2978
 
3313
 
    if err.error_verb == 'NoSuchRevision':
 
2979
    if err.error_verb == 'IncompatibleRepositories':
 
2980
        raise errors.IncompatibleRepositories(err.error_args[0],
 
2981
            err.error_args[1], err.error_args[2])
 
2982
    elif err.error_verb == 'NoSuchRevision':
3314
2983
        raise NoSuchRevision(find('branch'), err.error_args[0])
3315
2984
    elif err.error_verb == 'nosuchrevision':
3316
2985
        raise NoSuchRevision(find('repository'), err.error_args[0])
3323
2992
            detail=extra)
3324
2993
    elif err.error_verb == 'norepository':
3325
2994
        raise errors.NoRepositoryPresent(find('bzrdir'))
 
2995
    elif err.error_verb == 'LockContention':
 
2996
        raise errors.LockContention('(remote lock)')
3326
2997
    elif err.error_verb == 'UnlockableTransport':
3327
2998
        raise errors.UnlockableTransport(find('bzrdir').root_transport)
 
2999
    elif err.error_verb == 'LockFailed':
 
3000
        raise errors.LockFailed(err.error_args[0], err.error_args[1])
3328
3001
    elif err.error_verb == 'TokenMismatch':
3329
3002
        raise errors.TokenMismatch(find('token'), '(remote token)')
3330
3003
    elif err.error_verb == 'Diverged':
3331
3004
        raise errors.DivergedBranches(find('branch'), find('other_branch'))
 
3005
    elif err.error_verb == 'TipChangeRejected':
 
3006
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
 
3007
    elif err.error_verb == 'UnstackableBranchFormat':
 
3008
        raise errors.UnstackableBranchFormat(*err.error_args)
 
3009
    elif err.error_verb == 'UnstackableRepositoryFormat':
 
3010
        raise errors.UnstackableRepositoryFormat(*err.error_args)
3332
3011
    elif err.error_verb == 'NotStacked':
3333
3012
        raise errors.NotStacked(branch=find('branch'))
3334
3013
    elif err.error_verb == 'PermissionDenied':
3344
3023
    elif err.error_verb == 'NoSuchFile':
3345
3024
        path = get_path()
3346
3025
        raise errors.NoSuchFile(path)
3347
 
    _translate_error_without_context(err)
3348
 
 
3349
 
 
3350
 
def _translate_error_without_context(err):
3351
 
    """Translate any ErrorFromSmartServer values that don't require context"""
3352
 
    if err.error_verb == 'IncompatibleRepositories':
3353
 
        raise errors.IncompatibleRepositories(err.error_args[0],
3354
 
            err.error_args[1], err.error_args[2])
3355
 
    elif err.error_verb == 'LockContention':
3356
 
        raise errors.LockContention('(remote lock)')
3357
 
    elif err.error_verb == 'LockFailed':
3358
 
        raise errors.LockFailed(err.error_args[0], err.error_args[1])
3359
 
    elif err.error_verb == 'TipChangeRejected':
3360
 
        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
3361
 
    elif err.error_verb == 'UnstackableBranchFormat':
3362
 
        raise errors.UnstackableBranchFormat(*err.error_args)
3363
 
    elif err.error_verb == 'UnstackableRepositoryFormat':
3364
 
        raise errors.UnstackableRepositoryFormat(*err.error_args)
3365
3026
    elif err.error_verb == 'FileExists':
3366
3027
        raise errors.FileExists(err.error_args[0])
3367
3028
    elif err.error_verb == 'DirectoryNotEmpty':
3386
3047
            raise UnicodeEncodeError(encoding, val, start, end, reason)
3387
3048
    elif err.error_verb == 'ReadOnlyError':
3388
3049
        raise errors.TransportNotPossible('readonly transport')
3389
 
    elif err.error_verb == 'MemoryError':
3390
 
        raise errors.BzrError("remote server out of memory\n"
3391
 
            "Retry non-remotely, or contact the server admin for details.")
3392
3050
    raise errors.UnknownErrorFromSmartServer(err)