~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

[merge] bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
321
321
            if self._do_prefetch and hasattr(f, 'prefetch'):
322
322
                f.prefetch()
323
323
            return f
324
 
        except (IOError, paramiko.SSHException), x:
325
 
            raise NoSuchFile('Error retrieving %s: %s' % (path, str(x)), x)
 
324
        except (IOError, paramiko.SSHException), e:
 
325
            self._translate_io_exception(e, path, ': error retrieving')
326
326
 
327
327
    def get_partial(self, relpath, start, length=None):
328
328
        """
395
395
            path = self._abspath(relpath)
396
396
            self._sftp.mkdir(path)
397
397
        except (paramiko.SSHException, IOError), e:
398
 
            self._translate_io_exception(e, relpath, ': unable to mkdir')
399
 
 
400
 
    def _translate_io_exception(self, e, relpath, more_info=''):
 
398
            self._translate_io_exception(e, relpath, ': unable to mkdir',
 
399
                failure_exc=FileExists)
 
400
 
 
401
    def _translate_io_exception(self, e, path, more_info='', failure_exc=NoSuchFile):
 
402
        """Translate a paramiko or IOError into a friendlier exception.
 
403
 
 
404
        :param e: The original exception
 
405
        :param path: The path in question when the error is raised
 
406
        :param more_info: Extra information that can be included,
 
407
                          such as what was going on
 
408
        :param failure_exc: Paramiko has the super fun ability to raise completely
 
409
                           opaque errors that just set "e.args = ('Failure',)" with
 
410
                           no more information.
 
411
                           This sometimes means FileExists, but it also sometimes
 
412
                           means NoSuchFile
 
413
        """
401
414
        # paramiko seems to generate detailless errors.
402
 
        self._translate_error(e, relpath, raise_generic=False)
 
415
        self._translate_error(e, path, raise_generic=False)
403
416
        if hasattr(e, 'args'):
404
417
            if (e.args == ('No such file or directory',) or
405
418
                e.args == ('No such file',)):
406
 
                raise NoSuchFile(relpath, str(e) + more_info)
 
419
                raise NoSuchFile(path, str(e) + more_info)
407
420
            if (e.args == ('mkdir failed',)):
408
 
                raise FileExists(relpath, str(e) + more_info)
 
421
                raise FileExists(path, str(e) + more_info)
409
422
            # strange but true, for the paramiko server.
410
423
            if (e.args == ('Failure',)):
411
 
                raise FileExists(relpath, str(e) + more_info)
 
424
                raise failure_exc(path, str(e) + more_info)
412
425
        raise e
413
426
 
414
427
    def append(self, relpath, f):
420
433
            path = self._abspath(relpath)
421
434
            fout = self._sftp.file(path, 'ab')
422
435
            self._pump(f, fout)
423
 
        except (IOError, paramiko.SSHException), x:
424
 
            raise TransportError('Unable to append file %r' % (path,), x)
 
436
        except (IOError, paramiko.SSHException), e:
 
437
            self._translate_io_exception(e, relpath, ': unable to append')
425
438
 
426
439
    def copy(self, rel_from, rel_to):
427
440
        """Copy the item at rel_from to the location at rel_to"""
452
465
                    fout.close()
453
466
            finally:
454
467
                fin.close()
455
 
        except (IOError, paramiko.SSHException), x:
456
 
            raise TransportError('Unable to copy %r to %r' % (path_from, path_to), x)
 
468
        except (IOError, paramiko.SSHException), e:
 
469
            self._translate_io_exception(e, path_from, ': unable copy to: %r' % path_to)
457
470
 
458
471
    def copy_to(self, relpaths, other, pb=None):
459
472
        """Copy a set of entries from self into another Transport.
505
518
        path = self._abspath(relpath)
506
519
        try:
507
520
            self._sftp.remove(path)
508
 
        except (IOError, paramiko.SSHException), x:
509
 
            raise TransportError('Unable to delete %r' % (path,), x)
 
521
        except (IOError, paramiko.SSHException), e:
 
522
            self._translate_io_exception(e, path, ': unable to delete')
510
523
            
511
524
    def listable(self):
512
525
        """Return True if this store supports listing."""
520
533
        path = self._abspath(relpath)
521
534
        try:
522
535
            return self._sftp.listdir(path)
523
 
        except (IOError, paramiko.SSHException), x:
524
 
            raise TransportError('Unable to list folder %r' % (path,), x)
 
536
        except (IOError, paramiko.SSHException), e:
 
537
            self._translate_io_exception(e, path, ': failed to list_dir')
525
538
 
526
539
    def stat(self, relpath):
527
540
        """Return the stat information for a file."""
528
541
        path = self._abspath(relpath)
529
542
        try:
530
543
            return self._sftp.stat(path)
531
 
        except (IOError, paramiko.SSHException), x:
532
 
            raise TransportError('Unable to stat %r' % (path,), x)
 
544
        except (IOError, paramiko.SSHException), e:
 
545
            self._translate_io_exception(e, path, ': unable to stat')
533
546
 
534
547
    def lock_read(self, relpath):
535
548
        """
595
608
            try:
596
609
                port = int(port)
597
610
            except ValueError:
 
611
                # TODO: Should this be ConnectionError?
598
612
                raise TransportError('%s: invalid port number' % port)
599
613
        host = urllib.unquote(host)
600
614
 
644
658
        load_host_keys()
645
659
 
646
660
        try:
647
 
            t = paramiko.Transport((self._host, self._port))
 
661
            t = paramiko.Transport((self._host, self._port or 22))
648
662
            t.start_client()
649
 
        except paramiko.SSHException:
650
 
            raise TransportError('Unable to reach SSH host %s:%d' % (self._host, self._port))
 
663
        except paramiko.SSHException, e:
 
664
            raise ConnectionError('Unable to reach SSH host %s:%d' %
 
665
                                  (self._host, self._port), e)
651
666
            
652
667
        server_key = t.get_remote_server_key()
653
668
        server_key_hex = paramiko.util.hexify(server_key.get_fingerprint())
677
692
        
678
693
        try:
679
694
            self._sftp = t.open_sftp_client()
680
 
        except paramiko.SSHException:
681
 
            raise BzrError('Unable to find path %s on SFTP server %s' % \
682
 
                (self._path, self._host))
 
695
        except paramiko.SSHException, e:
 
696
            raise ConnectionError('Unable to start sftp client %s:%d' %
 
697
                                  (self._host, self._port), e)
683
698
 
684
699
    def _sftp_auth(self, transport):
685
700
        # paramiko requires a username, but it might be none if nothing was supplied
727
742
                user=username, host=self._host)
728
743
        try:
729
744
            transport.auth_password(username, password)
730
 
        except paramiko.SSHException:
731
 
            raise TransportError('Unable to authenticate to SSH host as %s@%s' % \
732
 
                (username, self._host))
 
745
        except paramiko.SSHException, e:
 
746
            raise ConnectionError('Unable to authenticate to SSH host as %s@%s' %
 
747
                                  (username, self._host), e)
733
748
 
734
749
    def _try_pkey_auth(self, transport, pkey_class, username, filename):
735
750
        filename = os.path.expanduser('~/.ssh/' + filename)
777
792
            handle = msg.get_string()
778
793
            return SFTPFile(self._sftp, handle, 'wb', -1)
779
794
        except (paramiko.SSHException, IOError), e:
780
 
            self._translate_io_exception(e, relpath, ': unable to open')
 
795
            self._translate_io_exception(e, relpath, ': unable to open',
 
796
                failure_exc=FileExists)
781
797