~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

  • Committer: Patch Queue Manager
  • Date: 2016-02-01 19:56:05 UTC
  • mfrom: (6615.1.1 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20160201195605-o7rl92wf6uyum3fk
(vila) Open trunk again as 2.8b1 (Vincent Ladeuil)

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 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
38
from bzrlib import (
42
42
    urlutils,
43
43
    )
44
44
from bzrlib.errors import (FileExists,
45
 
                           NoSuchFile, PathNotChild,
 
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
 
        )
 
51
from bzrlib.osutils import fancy_rename
55
52
from bzrlib.trace import mutter, warning
56
53
from bzrlib.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
 
392
379
    def disconnect(self):
421
408
        :param relpath: The relative path to the file
422
409
        """
423
410
        try:
424
 
            # FIXME: by returning the file directly, we don't pass this
425
 
            # through to report_activity.  We could try wrapping the object
426
 
            # before it's returned.  For readv and get_bytes it's handled in
427
 
            # the higher-level function.
428
 
            # -- mbp 20090126
429
411
            path = self._remote_path(relpath)
430
412
            f = self._get_sftp().file(path, mode='rb')
431
413
            if self._do_prefetch and (getattr(f, 'prefetch', None) is not None):
611
593
                                    create_parent_dir=create_parent_dir,
612
594
                                    dir_mode=dir_mode)
613
595
 
614
 
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
 
596
    def put_bytes_non_atomic(self, relpath, raw_bytes, mode=None,
615
597
                             create_parent_dir=False,
616
598
                             dir_mode=None):
 
599
        if not isinstance(raw_bytes, str):
 
600
            raise TypeError(
 
601
                'raw_bytes must be a plain string, not %s' % type(raw_bytes))
 
602
 
617
603
        def writer(fout):
618
 
            fout.write(bytes)
 
604
            fout.write(raw_bytes)
619
605
        self._put_non_atomic_helper(relpath, writer, mode=mode,
620
606
                                    create_parent_dir=create_parent_dir,
621
607
                                    dir_mode=dir_mode)