~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

  • Committer: John Arbash Meinel
  • Date: 2005-12-01 22:50:26 UTC
  • mto: (1185.50.19 bzr-jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1532.
  • Revision ID: john@arbash-meinel.com-20051201225026-142c9a5a04bb38ba
Added a fancy footwork rename to osutils, made SftpTransport use it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
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
 
39
from bzrlib.osutils import pathjoin, fancy_rename
40
40
import bzrlib.ui
41
41
 
42
42
try:
356
356
        tmp_abspath = self._abspath(tmp_relpath)
357
357
        fout = self._sftp_open_exclusive(tmp_relpath)
358
358
 
 
359
        closed = False
359
360
        try:
360
361
            try:
361
362
                self._pump(f, fout)
362
 
            except (paramiko.SSHException, IOError), e:
363
 
                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)
364
368
        except Exception, e:
365
369
            # If we fail, try to clean up the temporary file
366
370
            # before we throw the exception
367
371
            # but don't let another exception mess things up
368
372
            try:
369
 
                fout.close()
 
373
                if not closed:
 
374
                    fout.close()
370
375
                self._sftp.remove(tmp_abspath)
371
376
            except:
372
377
                pass
373
378
            raise e
374
 
        else:
375
 
            # sftp rename doesn't allow overwriting, so play tricks:
376
 
            tmp_safety = 'bzr.tmp.%.9f.%d.%d' % (time.time(), os.getpid(), random.randint(0, 0x7FFFFFFF))
377
 
            tmp_safety = self._abspath(tmp_safety)
378
 
            try:
379
 
                self._sftp.rename(final_path, tmp_safety)
380
 
                file_existed = True
381
 
            except:
382
 
                file_existed = False
383
 
            success = False
384
 
            try:
385
 
                try:
386
 
                    self._sftp.rename(tmp_abspath, final_path)
387
 
                except (paramiko.SSHException, IOError), e:
388
 
                    self._translate_io_exception(e, relpath, ': unable to rename')
389
 
                else:
390
 
                    success = True
391
 
            finally:
392
 
                if file_existed:
393
 
                    if success:
394
 
                        self._sftp.unlink(tmp_safety)
395
 
                    else:
396
 
                        self._sftp.rename(tmp_safety, final_path)
397
379
 
398
380
    def iter_files_recursive(self):
399
381
        """Walk the relative paths of all files in this transport."""
500
482
 
501
483
        return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
502
484
 
 
485
    def _rename(self, abs_from, abs_to):
 
486
        """Do a fancy rename on the remote server.
 
487
        
 
488
        Using the implementation provided by osutils.
 
489
        """
 
490
        try:
 
491
            fancy_rename(abs_from, abs_to,
 
492
                    rename_func=self._sftp.rename,
 
493
                    unlink_func=self._sftp.remove)
 
494
        except (IOError, paramiko.SSHException), e:
 
495
            self._translate_io_exception(e, abs_from, ': unable to rename to %r' % (abs_to))
 
496
 
503
497
    def move(self, rel_from, rel_to):
504
498
        """Move the item at rel_from to the location at rel_to"""
505
499
        path_from = self._abspath(rel_from)
506
500
        path_to = self._abspath(rel_to)
507
 
        try:
508
 
            self._sftp.rename(path_from, path_to)
509
 
        except (IOError, paramiko.SSHException), x:
510
 
            raise TransportError('Unable to move %r to %r' % (path_from, path_to), x)
 
501
        self._rename(path_from, path_to)
511
502
 
512
503
    def delete(self, relpath):
513
504
        """Delete the item at relpath"""