~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

  • Committer: Martin
  • Date: 2010-05-03 20:57:39 UTC
  • mto: This revision was merged to the branch mainline in revision 5204.
  • Revision ID: gzlist@googlemail.com-20100503205739-n326zdvevv0rmruh
Retain original stack and error message when translating to ValueError in bencode

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
270
281
                    buffered = buffered[buffered_offset:]
271
282
                    buffered_data = [buffered]
272
283
                    buffered_len = len(buffered)
273
 
        # now that the data stream is done, close the handle
274
 
        fp.close()
275
284
        if buffered_len:
276
285
            buffered = ''.join(buffered_data)
277
286
            del buffered_data[:]
332
341
    # up the request itself, rather than us having to worry about it
333
342
    _max_request_size = 32768
334
343
 
 
344
    def __init__(self, base, _from_transport=None):
 
345
        super(SFTPTransport, self).__init__(base,
 
346
                                            _from_transport=_from_transport)
 
347
 
335
348
    def _remote_path(self, relpath):
336
349
        """Return the path to be passed along the sftp protocol for relpath.
337
350
 
338
351
        :param relpath: is a urlencoded string.
339
352
        """
340
 
        remote_path = self._parsed_url.clone(relpath).path
 
353
        relative = urlutils.unescape(relpath).encode('utf-8')
 
354
        remote_path = self._combine_paths(self._path, relative)
341
355
        # the initial slash should be removed from the path, and treated as a
342
356
        # homedir relative path (the path begins with a double slash if it is
343
357
        # absolute).  see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
362
376
        in base url at transport creation time.
363
377
        """
364
378
        if credentials is None:
365
 
            password = self._parsed_url.password
 
379
            password = self._password
366
380
        else:
367
381
            password = credentials
368
382
 
369
383
        vendor = ssh._get_ssh_vendor()
370
 
        user = self._parsed_url.user
 
384
        user = self._user
371
385
        if user is None:
372
386
            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)
 
387
            user = auth.get_user('ssh', self._host, self._port)
 
388
        connection = vendor.connect_sftp(self._user, password,
 
389
                                         self._host, self._port)
377
390
        return connection, (user, password)
378
391
 
379
 
    def disconnect(self):
380
 
        connection = self._get_connection()
381
 
        if connection is not None:
382
 
            connection.close()
383
 
 
384
392
    def _get_sftp(self):
385
393
        """Ensures that a connection is established"""
386
394
        connection = self._get_connection()
408
416
        :param relpath: The relative path to the file
409
417
        """
410
418
        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
411
424
            path = self._remote_path(relpath)
412
425
            f = self._get_sftp().file(path, mode='rb')
413
426
            if self._do_prefetch and (getattr(f, 'prefetch', None) is not None):
702
715
            if (e.args[0].startswith('Directory not empty: ')
703
716
                or getattr(e, 'errno', None) == errno.ENOTEMPTY):
704
717
                raise errors.DirectoryNotEmpty(path, str(e))
705
 
            if e.args == ('Operation unsupported',):
706
 
                raise errors.TransportNotPossible()
707
718
            mutter('Raising exception with args %s', e.args)
708
719
        if getattr(e, 'errno', None) is not None:
709
720
            mutter('Raising exception with errno %s', e.errno)