/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/transport/sftp.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011, 2016, 2017 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
16
16
 
17
17
"""Implementation of Transport over SFTP, using paramiko."""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
# TODO: Remove the transport-based lock_read and lock_write methods.  They'll
20
22
# then raise TransportNotPossible, which will break remote access to any
21
23
# formats which rely on OS-level locks.  That should be fine as those formats
31
33
import stat
32
34
import sys
33
35
import time
34
 
import urllib
35
 
import urlparse
36
36
import warnings
37
37
 
38
 
from bzrlib import (
 
38
from brzlib import (
39
39
    config,
40
40
    debug,
41
41
    errors,
42
42
    urlutils,
43
43
    )
44
 
from bzrlib.errors import (FileExists,
45
 
                           NoSuchFile, PathNotChild,
 
44
from brzlib.errors import (FileExists,
 
45
                           NoSuchFile,
46
46
                           TransportError,
47
47
                           LockError,
48
48
                           PathError,
49
49
                           ParamikoNotPresent,
50
50
                           )
51
 
from bzrlib.osutils import pathjoin, fancy_rename, getcwd
52
 
from bzrlib.symbol_versioning import (
53
 
        deprecated_function,
54
 
        )
55
 
from bzrlib.trace import mutter, warning
56
 
from bzrlib.transport import (
 
51
from brzlib.osutils import fancy_rename
 
52
from brzlib.trace import mutter, warning
 
53
from brzlib.transport import (
57
54
    FileFileStream,
58
55
    _file_streams,
59
 
    local,
60
 
    Server,
61
56
    ssh,
62
57
    ConnectedTransport,
63
58
    )
114
109
        except FileExists:
115
110
            raise LockError('File %r already locked' % (self.path,))
116
111
 
117
 
    def __del__(self):
118
 
        """Should this warn, or actually try to cleanup?"""
119
 
        if self.lock_file:
120
 
            warning("SFTPLock %r not explicitly unlocked" % (self.path,))
121
 
            self.unlock()
122
 
 
123
112
    def unlock(self):
124
113
        if not self.lock_file:
125
114
            return
281
270
                    buffered = buffered[buffered_offset:]
282
271
                    buffered_data = [buffered]
283
272
                    buffered_len = len(buffered)
 
273
        # now that the data stream is done, close the handle
 
274
        fp.close()
284
275
        if buffered_len:
285
276
            buffered = ''.join(buffered_data)
286
277
            del buffered_data[:]
341
332
    # up the request itself, rather than us having to worry about it
342
333
    _max_request_size = 32768
343
334
 
344
 
    def __init__(self, base, _from_transport=None):
345
 
        super(SFTPTransport, self).__init__(base,
346
 
                                            _from_transport=_from_transport)
347
 
 
348
335
    def _remote_path(self, relpath):
349
336
        """Return the path to be passed along the sftp protocol for relpath.
350
337
 
351
338
        :param relpath: is a urlencoded string.
352
339
        """
353
 
        relative = urlutils.unescape(relpath).encode('utf-8')
354
 
        remote_path = self._combine_paths(self._path, relative)
 
340
        remote_path = self._parsed_url.clone(relpath).path
355
341
        # the initial slash should be removed from the path, and treated as a
356
342
        # homedir relative path (the path begins with a double slash if it is
357
343
        # absolute).  see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
376
362
        in base url at transport creation time.
377
363
        """
378
364
        if credentials is None:
379
 
            password = self._password
 
365
            password = self._parsed_url.password
380
366
        else:
381
367
            password = credentials
382
368
 
383
369
        vendor = ssh._get_ssh_vendor()
384
 
        user = self._user
 
370
        user = self._parsed_url.user
385
371
        if user is None:
386
372
            auth = config.AuthenticationConfig()
387
 
            user = auth.get_user('ssh', self._host, self._port)
388
 
        connection = vendor.connect_sftp(self._user, password,
389
 
                                         self._host, self._port)
 
373
            user = auth.get_user('ssh', self._parsed_url.host,
 
374
                self._parsed_url.port)
 
375
        connection = vendor.connect_sftp(self._parsed_url.user, password,
 
376
            self._parsed_url.host, self._parsed_url.port)
390
377
        return connection, (user, password)
391
378
 
 
379
    def disconnect(self):
 
380
        connection = self._get_connection()
 
381
        if connection is not None:
 
382
            connection.close()
 
383
 
392
384
    def _get_sftp(self):
393
385
        """Ensures that a connection is established"""
394
386
        connection = self._get_connection()
416
408
        :param relpath: The relative path to the file
417
409
        """
418
410
        try:
419
 
            # FIXME: by returning the file directly, we don't pass this
420
 
            # through to report_activity.  We could try wrapping the object
421
 
            # before it's returned.  For readv and get_bytes it's handled in
422
 
            # the higher-level function.
423
 
            # -- mbp 20090126
424
411
            path = self._remote_path(relpath)
425
412
            f = self._get_sftp().file(path, mode='rb')
 
413
            size = f.stat().st_size
426
414
            if self._do_prefetch and (getattr(f, 'prefetch', None) is not None):
427
 
                f.prefetch()
 
415
                f.prefetch(size)
428
416
            return f
429
417
        except (IOError, paramiko.SSHException), e:
430
418
            self._translate_io_exception(e, path, ': error retrieving',
606
594
                                    create_parent_dir=create_parent_dir,
607
595
                                    dir_mode=dir_mode)
608
596
 
609
 
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
 
597
    def put_bytes_non_atomic(self, relpath, raw_bytes, mode=None,
610
598
                             create_parent_dir=False,
611
599
                             dir_mode=None):
 
600
        if not isinstance(raw_bytes, str):
 
601
            raise TypeError(
 
602
                'raw_bytes must be a plain string, not %s' % type(raw_bytes))
 
603
 
612
604
        def writer(fout):
613
 
            fout.write(bytes)
 
605
            fout.write(raw_bytes)
614
606
        self._put_non_atomic_helper(relpath, writer, mode=mode,
615
607
                                    create_parent_dir=create_parent_dir,
616
608
                                    dir_mode=dir_mode)
715
707
            if (e.args[0].startswith('Directory not empty: ')
716
708
                or getattr(e, 'errno', None) == errno.ENOTEMPTY):
717
709
                raise errors.DirectoryNotEmpty(path, str(e))
 
710
            if e.args == ('Operation unsupported',):
 
711
                raise errors.TransportNotPossible()
718
712
            mutter('Raising exception with args %s', e.args)
719
713
        if getattr(e, 'errno', None) is not None:
720
714
            mutter('Raising exception with errno %s', e.errno)
774
768
            self._translate_io_exception(e, path, ': unable to delete')
775
769
 
776
770
    def external_url(self):
777
 
        """See bzrlib.transport.Transport.external_url."""
 
771
        """See brzlib.transport.Transport.external_url."""
778
772
        # the external path for SFTP is the base
779
773
        return self.base
780
774
 
907
901
 
908
902
def get_test_permutations():
909
903
    """Return the permutations to be used in testing."""
910
 
    from bzrlib.tests import stub_sftp
 
904
    from brzlib.tests import stub_sftp
911
905
    return [(SFTPTransport, stub_sftp.SFTPAbsoluteServer),
912
906
            (SFTPTransport, stub_sftp.SFTPHomeDirServer),
913
907
            (SFTPTransport, stub_sftp.SFTPSiblingAbsoluteServer),