~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/remote.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-01-13 05:14:24 UTC
  • mfrom: (3936.1.3 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090113051424-nrk3zkfe09h46i9y
(mbp) merge 1.11 and advance to 1.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""RemoteTransport client for the smart-server.
18
18
 
34
34
    urlutils,
35
35
    )
36
36
from bzrlib.smart import client, medium
37
 
from bzrlib.symbol_versioning import (
38
 
    deprecated_method,
39
 
    )
 
37
from bzrlib.symbol_versioning import (deprecated_method, one_four)
40
38
 
41
39
 
42
40
class _SmartStat(object):
54
52
 
55
53
    The connection has a notion of the current directory to which it's
56
54
    connected; this is incorporated in filenames passed to the server.
57
 
 
58
 
    This supports some higher-level RPC operations and can also be treated
 
55
    
 
56
    This supports some higher-level RPC operations and can also be treated 
59
57
    like a Transport to do file-like operations.
60
58
 
61
59
    The connection can be made over a tcp socket, an ssh pipe or a series of
69
67
    # IMPORTANT FOR IMPLEMENTORS: RemoteTransport MUST NOT be given encoding
70
68
    # responsibilities: Put those on SmartClient or similar. This is vital for
71
69
    # the ability to support multiple versions of the smart protocol over time:
72
 
    # RemoteTransport is an adapter from the Transport object model to the
 
70
    # RemoteTransport is an adapter from the Transport object model to the 
73
71
    # SmartClient model, not an encoder.
74
72
 
75
73
    # FIXME: the medium parameter should be private, only the tests requires
92
90
            should only be used for testing purposes; normally this is
93
91
            determined from the medium.
94
92
        """
95
 
        super(RemoteTransport, self).__init__(
96
 
            url, _from_transport=_from_transport)
 
93
        super(RemoteTransport, self).__init__(url,
 
94
                                              _from_transport=_from_transport)
97
95
 
98
96
        # The medium is the connection, except when we need to share it with
99
97
        # other objects (RemoteBzrDir, RemoteRepository etc). In these cases
100
98
        # what we want to share is really the shared connection.
101
99
 
102
 
        if (_from_transport is not None
103
 
            and isinstance(_from_transport, RemoteTransport)):
104
 
            _client = _from_transport._client
105
 
        elif _from_transport is None:
 
100
        if _from_transport is None:
106
101
            # If no _from_transport is specified, we need to intialize the
107
102
            # shared medium.
108
103
            credentials = None
138
133
        # No credentials
139
134
        return None, None
140
135
 
141
 
    def _report_activity(self, bytes, direction):
142
 
        """See Transport._report_activity.
143
 
 
144
 
        Does nothing; the smart medium will report activity triggered by a
145
 
        RemoteTransport.
146
 
        """
147
 
        pass
148
 
 
149
136
    def is_readonly(self):
150
137
        """Smart server transport can do read/write file operations."""
151
138
        try:
168
155
    def get_smart_medium(self):
169
156
        return self._get_connection()
170
157
 
 
158
    @deprecated_method(one_four)
 
159
    def get_shared_medium(self):
 
160
        return self._get_shared_connection()
 
161
 
171
162
    def _remote_path(self, relpath):
172
163
        """Returns the Unicode version of the absolute path for relpath."""
173
 
        return urlutils.URL._combine_paths(self._parsed_url.path, relpath)
 
164
        return self._combine_paths(self._path, relpath)
174
165
 
175
166
    def _call(self, method, *args):
176
167
        resp = self._call2(method, *args)
215
206
 
216
207
    def get(self, relpath):
217
208
        """Return file-like object reading the contents of a remote file.
218
 
 
 
209
        
219
210
        :see: Transport.get_bytes()/get_file()
220
211
        """
221
212
        return StringIO(self.get_bytes(relpath))
300
291
 
301
292
    def append_file(self, relpath, from_file, mode=None):
302
293
        return self.append_bytes(relpath, from_file.read(), mode)
303
 
 
 
294
        
304
295
    def append_bytes(self, relpath, bytes, mode=None):
305
296
        resp = self._call_with_body_bytes(
306
297
            'append',
322
313
    def recommended_page_size(self):
323
314
        """Return the recommended page size for this transport."""
324
315
        return 64 * 1024
325
 
 
 
316
        
326
317
    def _readv(self, relpath, offsets):
327
318
        if not offsets:
328
319
            return
430
421
    def _ensure_ok(self, resp):
431
422
        if resp[0] != 'ok':
432
423
            raise errors.UnexpectedSmartServerResponse(resp)
433
 
 
 
424
        
434
425
    def _translate_error(self, err, relpath=None):
435
426
        remote._translate_error(err, path=relpath)
436
427
 
437
428
    def disconnect(self):
438
 
        m = self.get_smart_medium()
439
 
        if m is not None:
440
 
            m.disconnect()
 
429
        self.get_smart_medium().disconnect()
441
430
 
442
431
    def stat(self, relpath):
443
432
        resp = self._call2('stat', self._remote_path(relpath))
476
465
 
477
466
class RemoteTCPTransport(RemoteTransport):
478
467
    """Connection to smart server over plain tcp.
479
 
 
 
468
    
480
469
    This is essentially just a factory to get 'RemoteTransport(url,
481
470
        SmartTCPClientMedium).
482
471
    """
483
472
 
484
473
    def _build_medium(self):
485
474
        client_medium = medium.SmartTCPClientMedium(
486
 
            self._parsed_url.host, self._parsed_url.port, self.base)
 
475
            self._host, self._port, self.base)
487
476
        return client_medium, None
488
477
 
489
478
 
496
485
 
497
486
    def _build_medium(self):
498
487
        client_medium = medium.SmartTCPClientMedium(
499
 
            self._parsed_url.host, self._parsed_url.port, self.base)
 
488
            self._host, self._port, self.base)
500
489
        client_medium._protocol_version = 2
501
490
        client_medium._remember_remote_is_before((1, 6))
502
491
        return client_medium, None
512
501
    def _build_medium(self):
513
502
        location_config = config.LocationConfig(self.base)
514
503
        bzr_remote_path = location_config.get_bzr_remote_path()
515
 
        user = self._parsed_url.user
 
504
        user = self._user
516
505
        if user is None:
517
506
            auth = config.AuthenticationConfig()
518
 
            user = auth.get_user('ssh', self._parsed_url.host,
519
 
                self._parsed_url.port)
520
 
        ssh_params = medium.SSHParams(self._parsed_url.host,
521
 
                self._parsed_url.port, user, self._parsed_url.password,
522
 
                bzr_remote_path)
523
 
        client_medium = medium.SmartSSHClientMedium(self.base, ssh_params)
524
 
        return client_medium, (user, self._parsed_url.password)
 
507
            user = auth.get_user('ssh', self._host, self._port)
 
508
        client_medium = medium.SmartSSHClientMedium(self._host, self._port,
 
509
            user, self._password, self.base,
 
510
            bzr_remote_path=bzr_remote_path)
 
511
        return client_medium, (user, self._password)
525
512
 
526
513
 
527
514
class RemoteHTTPTransport(RemoteTransport):
528
515
    """Just a way to connect between a bzr+http:// url and http://.
529
 
 
 
516
    
530
517
    This connection operates slightly differently than the RemoteSSHTransport.
531
518
    It uses a plain http:// transport underneath, which defines what remote
532
519
    .bzr/smart URL we are connected to. From there, all paths that are sent are
541
528
            # url only for an intial construction (when the url came from the
542
529
            # command-line).
543
530
            http_url = base[len('bzr+'):]
544
 
            self._http_transport = transport.get_transport_from_url(http_url)
 
531
            self._http_transport = transport.get_transport(http_url)
545
532
        else:
546
533
            self._http_transport = http_transport
547
534
        super(RemoteHTTPTransport, self).__init__(
593
580
            return redirected
594
581
 
595
582
 
596
 
class HintingSSHTransport(transport.Transport):
597
 
    """Simple transport that handles ssh:// and points out bzr+ssh://."""
598
 
 
599
 
    def __init__(self, url):
600
 
        raise errors.UnsupportedProtocol(url,
601
 
            'bzr supports bzr+ssh to operate over ssh, use "bzr+%s".' % url)
602
 
 
603
 
 
604
583
def get_test_permutations():
605
584
    """Return (transport, server) permutations for testing."""
606
585
    ### We may need a little more test framework support to construct an
607
586
    ### appropriate RemoteTransport in the future.
608
 
    from bzrlib.tests import test_server
609
 
    return [(RemoteTCPTransport, test_server.SmartTCPServer_for_testing)]
 
587
    from bzrlib.smart import server
 
588
    return [(RemoteTCPTransport, server.SmartTCPServer_for_testing)]