/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 breezy/transport/sftp.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-06 11:48:54 UTC
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@jelmer.uk-20180506114854-h4qd9ojaqy8wxjsd
Move .mailmap to root.

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
    urlutils,
43
43
    )
44
44
from ..errors import (FileExists,
45
 
                      NoSuchFile,
46
 
                      TransportError,
47
 
                      LockError,
48
 
                      PathError,
49
 
                      ParamikoNotPresent,
50
 
                      )
 
45
                           NoSuchFile,
 
46
                           TransportError,
 
47
                           LockError,
 
48
                           PathError,
 
49
                           ParamikoNotPresent,
 
50
                           )
51
51
from ..osutils import fancy_rename
52
52
from ..sixish import (
53
53
    zip,
69
69
# /var/lib/python-support/python2.5/paramiko/message.py:226: DeprecationWarning: integer argument expected, got float
70
70
#  self.packet.write(struct.pack('>I', n))
71
71
warnings.filterwarnings('ignore',
72
 
                        'integer argument expected, got float',
73
 
                        category=DeprecationWarning,
74
 
                        module='paramiko.message')
 
72
        'integer argument expected, got float',
 
73
        category=DeprecationWarning,
 
74
        module='paramiko.message')
75
75
 
76
76
try:
77
77
    import paramiko
80
80
else:
81
81
    from paramiko.sftp import (SFTP_FLAG_WRITE, SFTP_FLAG_CREATE,
82
82
                               SFTP_FLAG_EXCL, SFTP_FLAG_TRUNC,
83
 
                               CMD_HANDLE, CMD_OPEN)
 
83
                               SFTP_OK, CMD_HANDLE, CMD_OPEN)
84
84
    from paramiko.sftp_attr import SFTPAttributes
85
85
    from paramiko.sftp_file import SFTPFile
86
86
 
193
193
        # as possible, so we don't issues requests <32kB
194
194
        sorted_offsets = sorted(self.original_offsets)
195
195
        coalesced = list(ConnectedTransport._coalesce_offsets(sorted_offsets,
196
 
                                                              limit=0, fudge_factor=0))
 
196
                                                        limit=0, fudge_factor=0))
197
197
        requests = []
198
198
        for c_offset in coalesced:
199
199
            start = c_offset.start
207
207
                start += next_size
208
208
        if 'sftp' in debug.debug_flags:
209
209
            mutter('SFTP.readv(%s) %s offsets => %s coalesced => %s requests',
210
 
                   self.relpath, len(sorted_offsets), len(coalesced),
211
 
                   len(requests))
 
210
                self.relpath, len(sorted_offsets), len(coalesced),
 
211
                len(requests))
212
212
        return requests
213
213
 
214
214
    def request_and_yield_offsets(self, fp):
241
241
            if data is None:
242
242
                if cur_coalesced is not None:
243
243
                    raise errors.ShortReadvError(self.relpath,
244
 
                                                 start, length, len(data))
 
244
                        start, length, len(data))
245
245
            if len(data) != length:
246
246
                raise errors.ShortReadvError(self.relpath,
247
 
                                             start, length, len(data))
 
247
                    start, length, len(data))
248
248
            self._report_activity(length, 'read')
249
249
            if last_end is None:
250
250
                # This is the first request, just buffer it
262
262
                if buffered_len > 0:
263
263
                    # We haven't consumed the buffer so far, so put it into
264
264
                    # data_chunks, and continue.
265
 
                    buffered = b''.join(buffered_data)
 
265
                    buffered = ''.join(buffered_data)
266
266
                    data_chunks.append((input_start, buffered))
267
267
                input_start = start
268
268
                buffered_data = [data]
273
273
                # into a single string. We also have the nice property that
274
274
                # when there is only one string ''.join([x]) == x, so there is
275
275
                # no data copying.
276
 
                buffered = b''.join(buffered_data)
 
276
                buffered = ''.join(buffered_data)
277
277
                # Clean out buffered data so that we keep memory
278
278
                # consumption low
279
279
                del buffered_data[:]
294
294
                    input_start += cur_size
295
295
                    # Yield the requested data
296
296
                    yield cur_offset, cur_data
297
 
                    try:
298
 
                        cur_offset, cur_size = next(offset_iter)
299
 
                    except StopIteration:
300
 
                        return
 
297
                    cur_offset, cur_size = next(offset_iter)
301
298
                # at this point, we've consumed as much of buffered as we can,
302
299
                # so break off the portion that we consumed
303
300
                if buffered_offset == len(buffered_data):
311
308
        # now that the data stream is done, close the handle
312
309
        fp.close()
313
310
        if buffered_len:
314
 
            buffered = b''.join(buffered_data)
 
311
            buffered = ''.join(buffered_data)
315
312
            del buffered_data[:]
316
313
            data_chunks.append((input_start, buffered))
317
314
        if data_chunks:
318
315
            if 'sftp' in debug.debug_flags:
319
316
                mutter('SFTP readv left with %d out-of-order bytes',
320
 
                       sum(len(x[1]) for x in data_chunks))
 
317
                    sum(len(x[1]) for x in data_chunks))
321
318
            # We've processed all the readv data, at this point, anything we
322
319
            # couldn't process is in data_chunks. This doesn't happen often, so
323
320
            # this code path isn't optimized
343
340
                    data = ''
344
341
                if len(data) != cur_size:
345
342
                    raise AssertionError('We must have miscalulated.'
346
 
                                         ' We expected %d bytes, but only found %d'
347
 
                                         % (cur_size, len(data)))
 
343
                        ' We expected %d bytes, but only found %d'
 
344
                        % (cur_size, len(data)))
348
345
                yield cur_offset, data
349
 
                try:
350
 
                    cur_offset, cur_size = next(offset_iter)
351
 
                except StopIteration:
352
 
                    return
 
346
                cur_offset, cur_size = next(offset_iter)
353
347
 
354
348
 
355
349
class SFTPTransport(ConnectedTransport):
411
405
        if user is None:
412
406
            auth = config.AuthenticationConfig()
413
407
            user = auth.get_user('ssh', self._parsed_url.host,
414
 
                                 self._parsed_url.port)
 
408
                self._parsed_url.port)
415
409
        connection = vendor.connect_sftp(self._parsed_url.user, password,
416
 
                                         self._parsed_url.host, self._parsed_url.port)
 
410
            self._parsed_url.host, self._parsed_url.port)
417
411
        return connection, (user, password)
418
412
 
419
413
    def disconnect(self):
456
450
            return f
457
451
        except (IOError, paramiko.SSHException) as e:
458
452
            self._translate_io_exception(e, path, ': error retrieving',
459
 
                                         failure_exc=errors.ReadError)
 
453
                failure_exc=errors.ReadError)
460
454
 
461
455
    def get_bytes(self, relpath):
462
456
        # reimplement this here so that we can report how many bytes came back
517
511
    def _put(self, abspath, f, mode=None):
518
512
        """Helper function so both put() and copy_abspaths can reuse the code"""
519
513
        tmp_abspath = '%s.tmp.%.9f.%d.%d' % (abspath, time.time(),
520
 
                                             os.getpid(), random.randint(0, 0x7FFFFFFF))
 
514
                        os.getpid(), random.randint(0, 0x7FFFFFFF))
521
515
        fout = self._sftp_open_exclusive(tmp_abspath, mode=mode)
522
516
        closed = False
523
517
        try:
634
628
    def put_bytes_non_atomic(self, relpath, raw_bytes, mode=None,
635
629
                             create_parent_dir=False,
636
630
                             dir_mode=None):
637
 
        if not isinstance(raw_bytes, bytes):
 
631
        if not isinstance(raw_bytes, str):
638
632
            raise TypeError(
639
633
                'raw_bytes must be a plain string, not %s' % type(raw_bytes))
640
634
 
653
647
            st = self.stat(relpath)
654
648
            if stat.S_ISDIR(st.st_mode):
655
649
                for i, basename in enumerate(self.list_dir(relpath)):
656
 
                    queue.insert(i, relpath + '/' + basename)
 
650
                    queue.insert(i, relpath+'/'+basename)
657
651
            else:
658
652
                yield relpath
659
653
 
673
667
                # the sgid bit is set, report a warning to the user
674
668
                # with the umask fix.
675
669
                stat = self._get_sftp().lstat(abspath)
676
 
                mode = mode & 0o777  # can't set special bits anyway
 
670
                mode = mode & 0o777 # can't set special bits anyway
677
671
                if mode != stat.st_mode & 0o777:
678
672
                    if stat.st_mode & 0o6000:
679
673
                        warning('About to chmod %s over sftp, which will result'
684
678
                    self._get_sftp().chmod(abspath, mode=mode)
685
679
        except (paramiko.SSHException, IOError) as e:
686
680
            self._translate_io_exception(e, abspath, ': unable to mkdir',
687
 
                                         failure_exc=FileExists)
 
681
                failure_exc=FileExists)
688
682
 
689
683
    def mkdir(self, relpath, mode=None):
690
684
        """Create a directory at the given path."""
697
691
        # api more than once per write_group at the moment so
698
692
        # it is a tolerable overhead. Better would be to truncate
699
693
        # the file after opening. RBC 20070805
700
 
        self.put_bytes_non_atomic(relpath, b"", mode)
 
694
        self.put_bytes_non_atomic(relpath, "", mode)
701
695
        abspath = self._remote_path(relpath)
702
696
        # TODO: jam 20060816 paramiko doesn't publicly expose a way to
703
697
        #       set the file mode at create time. If it does, use it.
730
724
        self._translate_error(e, path, raise_generic=False)
731
725
        if getattr(e, 'args', None) is not None:
732
726
            if (e.args == ('No such file or directory',) or
733
 
                    e.args == ('No such file',)):
 
727
                e.args == ('No such file',)):
734
728
                raise NoSuchFile(path, str(e) + more_info)
735
729
            if (e.args == ('mkdir failed',) or
736
 
                    e.args[0].startswith('syserr: File exists')):
 
730
                e.args[0].startswith('syserr: File exists')):
737
731
                raise FileExists(path, str(e) + more_info)
738
732
            # strange but true, for the paramiko server.
739
733
            if (e.args == ('Failure',)):
742
736
            # '/srv/bazaar.launchpad.net/blah...: '
743
737
            # [Errno 39] Directory not empty',)
744
738
            if (e.args[0].startswith('Directory not empty: ')
745
 
                    or getattr(e, 'errno', None) == errno.ENOTEMPTY):
 
739
                or getattr(e, 'errno', None) == errno.ENOTEMPTY):
746
740
                raise errors.DirectoryNotEmpty(path, str(e))
747
741
            if e.args == ('Operation unsupported',):
748
742
                raise errors.TransportNotPossible()
771
765
        """Rename without special overwriting"""
772
766
        try:
773
767
            self._get_sftp().rename(self._remote_path(rel_from),
774
 
                                    self._remote_path(rel_to))
 
768
                              self._remote_path(rel_to))
775
769
        except (IOError, paramiko.SSHException) as e:
776
770
            self._translate_io_exception(e, rel_from,
777
 
                                         ': unable to rename to %r' % (rel_to))
 
771
                    ': unable to rename to %r' % (rel_to))
778
772
 
779
773
    def _rename_and_overwrite(self, abs_from, abs_to):
780
774
        """Do a fancy rename on the remote server.
849
843
        """See Transport.readlink."""
850
844
        path = self._remote_path(relpath)
851
845
        try:
852
 
            return self._get_sftp().readlink(self._remote_path(path))
 
846
            return self._get_sftp().readlink(path)
853
847
        except (IOError, paramiko.SSHException) as e:
854
848
            self._translate_io_exception(e, path, ': unable to readlink')
855
849
 
857
851
        """See Transport.symlink."""
858
852
        try:
859
853
            conn = self._get_sftp()
860
 
            sftp_retval = conn.symlink(source, self._remote_path(link_name))
 
854
            sftp_retval = conn.symlink(source, link_name)
 
855
            if SFTP_OK != sftp_retval:
 
856
                raise TransportError(
 
857
                    '%r: unable to create symlink to %r' % (link_name, source),
 
858
                    sftp_retval
 
859
                )
861
860
        except (IOError, paramiko.SSHException) as e:
862
861
            self._translate_io_exception(e, link_name,
863
862
                                         ': unable to create symlink to %r' % (source))
871
870
        class BogusLock(object):
872
871
            def __init__(self, path):
873
872
                self.path = path
874
 
 
875
873
            def unlock(self):
876
874
                pass
877
 
 
878
875
            def __exit__(self, exc_type, exc_val, exc_tb):
879
876
                return False
880
 
 
881
877
            def __enter__(self):
882
878
                pass
883
879
        return BogusLock(relpath)
919
915
        if mode is not None:
920
916
            attr.st_mode = mode
921
917
        omode = (SFTP_FLAG_WRITE | SFTP_FLAG_CREATE
922
 
                 | SFTP_FLAG_TRUNC | SFTP_FLAG_EXCL)
 
918
                | SFTP_FLAG_TRUNC | SFTP_FLAG_EXCL)
923
919
        try:
924
920
            t, msg = self._get_sftp()._request(CMD_OPEN, path, omode, attr)
925
921
            if t != CMD_HANDLE:
928
924
            return SFTPFile(self._get_sftp(), handle, 'wb', -1)
929
925
        except (paramiko.SSHException, IOError) as e:
930
926
            self._translate_io_exception(e, abspath, ': unable to open',
931
 
                                         failure_exc=FileExists)
 
927
                failure_exc=FileExists)
932
928
 
933
929
    def _can_roundtrip_unix_modebits(self):
934
930
        if sys.platform == 'win32':