~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

Use tweaks for subunit protocol client with --parallel=fork as well as --subunit

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011, 2016 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
 
 
21
19
# TODO: Remove the transport-based lock_read and lock_write methods.  They'll
22
20
# then raise TransportNotPossible, which will break remote access to any
23
21
# formats which rely on OS-level locks.  That should be fine as those formats
33
31
import stat
34
32
import sys
35
33
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,
 
45
                           NoSuchFile, PathNotChild,
46
46
                           TransportError,
47
47
                           LockError,
48
48
                           PathError,
49
49
                           ParamikoNotPresent,
50
50
                           )
51
 
from bzrlib.osutils import fancy_rename
 
51
from bzrlib.osutils import pathjoin, fancy_rename, getcwd
 
52
from bzrlib.symbol_versioning import (
 
53
        deprecated_function,
 
54
        )
52
55
from bzrlib.trace import mutter, warning
53
56
from bzrlib.transport import (
54
57
    FileFileStream,
55
58
    _file_streams,
 
59
    local,
 
60
    Server,
56
61
    ssh,
57
62
    ConnectedTransport,
58
63
    )
109
114
        except FileExists:
110
115
            raise LockError('File %r already locked' % (self.path,))
111
116
 
 
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
 
112
123
    def unlock(self):
113
124
        if not self.lock_file:
114
125
            return
332
343
    # up the request itself, rather than us having to worry about it
333
344
    _max_request_size = 32768
334
345
 
 
346
    def __init__(self, base, _from_transport=None):
 
347
        super(SFTPTransport, self).__init__(base,
 
348
                                            _from_transport=_from_transport)
 
349
 
335
350
    def _remote_path(self, relpath):
336
351
        """Return the path to be passed along the sftp protocol for relpath.
337
352
 
338
353
        :param relpath: is a urlencoded string.
339
354
        """
340
 
        remote_path = self._parsed_url.clone(relpath).path
 
355
        relative = urlutils.unescape(relpath).encode('utf-8')
 
356
        remote_path = self._combine_paths(self._path, relative)
341
357
        # the initial slash should be removed from the path, and treated as a
342
358
        # homedir relative path (the path begins with a double slash if it is
343
359
        # absolute).  see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
362
378
        in base url at transport creation time.
363
379
        """
364
380
        if credentials is None:
365
 
            password = self._parsed_url.password
 
381
            password = self._password
366
382
        else:
367
383
            password = credentials
368
384
 
369
385
        vendor = ssh._get_ssh_vendor()
370
 
        user = self._parsed_url.user
 
386
        user = self._user
371
387
        if user is None:
372
388
            auth = config.AuthenticationConfig()
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)
 
389
            user = auth.get_user('ssh', self._host, self._port)
 
390
        connection = vendor.connect_sftp(self._user, password,
 
391
                                         self._host, self._port)
377
392
        return connection, (user, password)
378
393
 
379
394
    def disconnect(self):
593
608
                                    create_parent_dir=create_parent_dir,
594
609
                                    dir_mode=dir_mode)
595
610
 
596
 
    def put_bytes_non_atomic(self, relpath, raw_bytes, mode=None,
 
611
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
597
612
                             create_parent_dir=False,
598
613
                             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
 
 
603
614
        def writer(fout):
604
 
            fout.write(raw_bytes)
 
615
            fout.write(bytes)
605
616
        self._put_non_atomic_helper(relpath, writer, mode=mode,
606
617
                                    create_parent_dir=create_parent_dir,
607
618
                                    dir_mode=dir_mode)