~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/smart.py

  • Committer: Robert Collins
  • Date: 2006-09-15 12:31:16 UTC
  • mto: (1752.2.84 remote bzrdir)
  • mto: This revision was merged to the branch mainline in revision 2015.
  • Revision ID: robertc@robertcollins.net-20060915123116-2151853564521d8f
Fix up all tests to pass, remove a couple more deprecated function calls, and break the dependency on sftp for the smart transport.

Show diffs side-by-side

added added

removed removed

Lines of Context:
150
150
    trace,
151
151
    urlutils,
152
152
    )
153
 
# XXX: The smart server should not depend on the SFTP code being importable.
154
153
from bzrlib.bundle.serializer import write_bundle
155
154
from bzrlib.trace import mutter
156
 
from bzrlib.transport import local, sftp
 
155
from bzrlib.transport import local
157
156
 
158
157
# must do this otherwise urllib can't parse the urls properly :(
159
158
for scheme in ['ssh', 'bzr', 'bzr+loopback', 'bzr+ssh']:
334
333
            return int(mode)
335
334
 
336
335
    def do_append(self, relpath, mode):
337
 
        old_length = self._backing_transport.append(relpath, StringIO(self._recv_body()),
338
 
                self._deserialise_optional_mode(mode))
 
336
        old_length = self._backing_transport.append_bytes(
 
337
            relpath, self._recv_body(), self._deserialise_optional_mode(mode))
339
338
        return SmartServerResponse(('appended', '%d' % old_length))
340
339
 
341
340
    def do_delete(self, relpath):
360
359
        self._backing_transport.move(rel_from, rel_to)
361
360
 
362
361
    def do_put(self, relpath, mode):
363
 
        self._backing_transport.put(relpath, 
364
 
                StringIO(self._recv_body()), 
 
362
        self._backing_transport.put_bytes(relpath,
 
363
                self._recv_body(),
365
364
                self._deserialise_optional_mode(mode))
366
365
 
367
366
    def do_rename(self, rel_from, rel_to):
512
511
        self.st_mode = mode
513
512
 
514
513
 
515
 
class SmartTransport(sftp.SFTPUrlHandling):
 
514
class SmartTransport(transport.Transport):
516
515
    """Connection to a smart server.
517
516
 
518
517
    The connection holds references to pipes that can be used to send requests
529
528
    type: SmartTCPTransport, etc.
530
529
    """
531
530
 
532
 
    def __init__(self, server_url, clone_from=None, client=None):
 
531
    def __init__(self, url, clone_from=None, client=None):
533
532
        """Constructor.
534
533
 
535
534
        :param client: ignored when clone_from is not None.
537
536
        ### Technically super() here is faulty because Transport's __init__
538
537
        ### fails to take 2 parameters, and if super were to choose a silly
539
538
        ### initialisation order things would blow up. 
540
 
        super(SmartTransport, self).__init__(server_url)
 
539
        if not url.endswith('/'):
 
540
            url += '/'
 
541
        super(SmartTransport, self).__init__(url)
 
542
        self._scheme, self._username, self._password, self._host, self._port, self._path = \
 
543
                transport.split_url(url)
541
544
        if clone_from is None:
542
545
            if client is None:
543
546
                self._client = SmartStreamClient(self._connect_to_server)
550
553
            # reuse same connection
551
554
            self._client = clone_from._client
552
555
 
 
556
    def abspath(self, relpath):
 
557
        """Return the full url to the given relative path.
 
558
        
 
559
        @param relpath: the relative path or path components
 
560
        @type relpath: str or list
 
561
        """
 
562
        return self._unparse_url(self._remote_path(relpath))
 
563
    
553
564
    def clone(self, relative_url):
554
565
        """Make a new SmartTransport related to me, sharing the same connection.
555
566
 
585
596
        return urlparse.urlunparse((self._scheme, netloc, path, '', '', ''))
586
597
 
587
598
    def _remote_path(self, relpath):
 
599
        """Returns the Unicode version of the absolute path for relpath."""
588
600
        return self._combine_paths(self._path, relpath)
589
601
 
590
602
    def has(self, relpath):
624
636
        self._translate_error(resp)
625
637
 
626
638
    def put_file(self, relpath, upload_file, mode=None):
627
 
        self.put_bytes(relpath, upload_file.read(), mode)
 
639
        # its not ideal to seek back, but currently put_non_atomic_file depends
 
640
        # on transports not reading before failing - which is a faulty
 
641
        # assumption I think - RBC 20060915
 
642
        pos = upload_file.tell()
 
643
        try:
 
644
            return self.put_bytes(relpath, upload_file.read(), mode)
 
645
        except:
 
646
            upload_file.seek(pos)
 
647
            raise
628
648
 
629
649
    def put_bytes(self, relpath, upload_contents, mode=None):
630
650
        # FIXME: upload_file is probably not safe for non-ascii characters -
637
657
        self._translate_error(resp)
638
658
 
639
659
    def append_file(self, relpath, from_file, mode=None):
640
 
        self.append_bytes(relpath, from_file.read(), mode)
 
660
        return self.append_bytes(relpath, from_file.read(), mode)
641
661
        
642
662
    def append_bytes(self, relpath, bytes, mode=None):
643
663
        resp = self._client._call_with_upload(
813
833
 
814
834
    def __init__(self, url, clone_from=None):
815
835
        super(SmartTCPTransport, self).__init__(url, clone_from)
816
 
        self._scheme, self._username, self._password, self._host, self._port, self._path = \
817
 
                transport.split_url(url)
818
836
        try:
819
837
            self._port = int(self._port)
820
838
        except (ValueError, TypeError), e:
841
859
        if self._socket is not None:
842
860
            self._socket.close()
843
861
 
844
 
 
845
 
class SmartSSHTransport(SmartTransport):
846
 
    """Connection to smart server over SSH."""
847
 
 
848
 
    def __init__(self, url, clone_from=None):
849
 
        # TODO: all this probably belongs in the parent class.
850
 
        super(SmartSSHTransport, self).__init__(url, clone_from)
851
 
        self._scheme, self._username, self._password, self._host, self._port, self._path = \
852
 
                transport.split_url(url)
853
 
        try:
854
 
            if self._port is not None:
855
 
                self._port = int(self._port)
856
 
        except (ValueError, TypeError), e:
857
 
            raise errors.InvalidURL(path=url, extra="invalid port %s" % self._port)
858
 
 
859
 
    def _connect_to_server(self):
860
 
        # XXX: don't hardcode vendor
861
 
        # XXX: cannot pass password to SSHSubprocess yet
862
 
        if self._password is not None:
863
 
            raise errors.InvalidURL("SSH smart transport doesn't handle passwords")
864
 
        self._ssh_connection = sftp.SSHSubprocess(self._host, 'openssh',
865
 
                port=self._port, user=self._username,
866
 
                command=['bzr', 'serve', '--inet'])
867
 
        return self._ssh_connection.get_filelike_channels()
868
 
 
869
 
    def disconnect(self):
870
 
        super(SmartSSHTransport, self).disconnect()
871
 
        self._ssh_connection.close()
 
862
try:
 
863
    from bzrlib.transport import sftp
 
864
except errors.ParamikoNotPresent:
 
865
    # no paramiko, no SSHTransport.
 
866
    pass
 
867
else:
 
868
    class SmartSSHTransport(SmartTransport):
 
869
        """Connection to smart server over SSH."""
 
870
 
 
871
        def __init__(self, url, clone_from=None):
 
872
            # TODO: all this probably belongs in the parent class.
 
873
            super(SmartSSHTransport, self).__init__(url, clone_from)
 
874
            try:
 
875
                if self._port is not None:
 
876
                    self._port = int(self._port)
 
877
            except (ValueError, TypeError), e:
 
878
                raise errors.InvalidURL(path=url, extra="invalid port %s" % self._port)
 
879
 
 
880
        def _connect_to_server(self):
 
881
            # XXX: don't hardcode vendor
 
882
            # XXX: cannot pass password to SSHSubprocess yet
 
883
            if self._password is not None:
 
884
                raise errors.InvalidURL("SSH smart transport doesn't handle passwords")
 
885
            self._ssh_connection = sftp.SSHSubprocess(self._host, 'openssh',
 
886
                    port=self._port, user=self._username,
 
887
                    command=['bzr', 'serve', '--inet'])
 
888
            return self._ssh_connection.get_filelike_channels()
 
889
 
 
890
        def disconnect(self):
 
891
            super(SmartSSHTransport, self).disconnect()
 
892
            self._ssh_connection.close()
872
893
 
873
894
 
874
895
def get_test_permutations():