~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

[merge] win32

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
                           TransportNotPossible, NoSuchFile, PathNotChild,
34
34
                           TransportError,
35
35
                           LockError)
36
 
from bzrlib.config import config_dir
 
36
from bzrlib.config import config_dir, ensure_config_dir_exists
37
37
from bzrlib.trace import mutter, warning, error
38
38
from bzrlib.transport import Transport, register_transport
 
39
from bzrlib.osutils import pathjoin, fancy_rename
39
40
import bzrlib.ui
40
41
 
41
42
try:
154
155
        SYSTEM_HOSTKEYS = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
155
156
    except Exception, e:
156
157
        mutter('failed to load system host keys: ' + str(e))
157
 
    bzr_hostkey_path = os.path.join(config_dir(), 'ssh_host_keys')
 
158
    bzr_hostkey_path = pathjoin(config_dir(), 'ssh_host_keys')
158
159
    try:
159
160
        BZR_HOSTKEYS = paramiko.util.load_host_keys(bzr_hostkey_path)
160
161
    except Exception, e:
166
167
    Save "discovered" host keys in $(config)/ssh_host_keys/.
167
168
    """
168
169
    global SYSTEM_HOSTKEYS, BZR_HOSTKEYS
169
 
    bzr_hostkey_path = os.path.join(config_dir(), 'ssh_host_keys')
170
 
    if not os.path.isdir(config_dir()):
171
 
        os.mkdir(config_dir())
 
170
    bzr_hostkey_path = pathjoin(config_dir(), 'ssh_host_keys')
 
171
    ensure_config_dir_exists()
 
172
 
172
173
    try:
173
174
        f = open(bzr_hostkey_path, 'w')
174
175
        f.write('# SSH host keys collected by bzr\n')
316
317
        """
317
318
        try:
318
319
            path = self._abspath(relpath)
319
 
            f = self._sftp.file(path)
 
320
            f = self._sftp.file(path, mode='rb')
320
321
            if self._do_prefetch and hasattr(f, 'prefetch'):
321
322
                f.prefetch()
322
323
            return f
355
356
        tmp_abspath = self._abspath(tmp_relpath)
356
357
        fout = self._sftp_open_exclusive(tmp_relpath)
357
358
 
 
359
        closed = False
358
360
        try:
359
361
            try:
360
362
                self._pump(f, fout)
361
 
            except (paramiko.SSHException, IOError), e:
362
 
                self._translate_io_exception(e, relpath, ': unable to write')
 
363
            except (IOError, paramiko.SSHException), e:
 
364
                self._translate_io_exception(e, tmp_abspath)
 
365
            fout.close()
 
366
            closed = True
 
367
            self._rename(tmp_abspath, final_path)
363
368
        except Exception, e:
364
369
            # If we fail, try to clean up the temporary file
365
370
            # before we throw the exception
366
371
            # but don't let another exception mess things up
367
372
            try:
368
 
                fout.close()
 
373
                if not closed:
 
374
                    fout.close()
369
375
                self._sftp.remove(tmp_abspath)
370
376
            except:
371
377
                pass
372
378
            raise e
373
 
        else:
374
 
            # sftp rename doesn't allow overwriting, so play tricks:
375
 
            tmp_safety = 'bzr.tmp.%.9f.%d.%d' % (time.time(), os.getpid(), random.randint(0, 0x7FFFFFFF))
376
 
            tmp_safety = self._abspath(tmp_safety)
377
 
            try:
378
 
                self._sftp.rename(final_path, tmp_safety)
379
 
                file_existed = True
380
 
            except:
381
 
                file_existed = False
382
 
            success = False
383
 
            try:
384
 
                try:
385
 
                    self._sftp.rename(tmp_abspath, final_path)
386
 
                except (paramiko.SSHException, IOError), e:
387
 
                    self._translate_io_exception(e, relpath, ': unable to rename')
388
 
                else:
389
 
                    success = True
390
 
            finally:
391
 
                if file_existed:
392
 
                    if success:
393
 
                        self._sftp.unlink(tmp_safety)
394
 
                    else:
395
 
                        self._sftp.rename(tmp_safety, final_path)
396
379
 
397
380
    def iter_files_recursive(self):
398
381
        """Walk the relative paths of all files in this transport."""
512
495
 
513
496
        return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
514
497
 
 
498
    def _rename(self, abs_from, abs_to):
 
499
        """Do a fancy rename on the remote server.
 
500
        
 
501
        Using the implementation provided by osutils.
 
502
        """
 
503
        try:
 
504
            fancy_rename(abs_from, abs_to,
 
505
                    rename_func=self._sftp.rename,
 
506
                    unlink_func=self._sftp.remove)
 
507
        except (IOError, paramiko.SSHException), e:
 
508
            self._translate_io_exception(e, abs_from, ': unable to rename to %r' % (abs_to))
 
509
 
515
510
    def move(self, rel_from, rel_to):
516
511
        """Move the item at rel_from to the location at rel_to"""
517
512
        path_from = self._abspath(rel_from)
518
513
        path_to = self._abspath(rel_to)
519
 
        try:
520
 
            self._sftp.rename(path_from, path_to)
521
 
        except (IOError, paramiko.SSHException), e:
522
 
            self._translate_io_exception(e, path_from, ': unable to move to: %r' % path_to)
 
514
        self._rename(path_from, path_to)
523
515
 
524
516
    def delete(self, relpath):
525
517
        """Delete the item at relpath"""
691
683
            save_host_keys()
692
684
        if server_key != our_server_key:
693
685
            filename1 = os.path.expanduser('~/.ssh/known_hosts')
694
 
            filename2 = os.path.join(config_dir(), 'ssh_host_keys')
 
686
            filename2 = pathjoin(config_dir(), 'ssh_host_keys')
695
687
            raise TransportError('Host keys for %s do not match!  %s != %s' % \
696
688
                (self._host, our_server_key_hex, server_key_hex),
697
689
                ['Try editing %s or %s' % (filename1, filename2)])
798
790
            if t != CMD_HANDLE:
799
791
                raise TransportError('Expected an SFTP handle')
800
792
            handle = msg.get_string()
801
 
            return SFTPFile(self._sftp, handle, 'w', -1)
 
793
            return SFTPFile(self._sftp, handle, 'wb', -1)
802
794
        except (paramiko.SSHException, IOError), e:
803
795
            self._translate_io_exception(e, relpath, ': unable to open',
804
796
                failure_exc=FileExists)