~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-11-05 07:50:16 UTC
  • mto: (1185.50.1 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1518.
  • Revision ID: john@arbash-meinel.com-20051105075016-c11d132cd87c5a6a
Adding a open_exclusive function since paramiko supports it, but doesn't expose it

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
except ImportError:
39
39
    error('The SFTP transport requires paramiko.')
40
40
    raise
 
41
else:
 
42
    from paramiko.sftp import (SFTP_FLAG_WRITE, SFTP_FLAG_CREATE,
 
43
                               SFTP_FLAG_EXCL, SFTP_FLAG_TRUNC,
 
44
                               CMD_HANDLE, CMD_OPEN)
 
45
    from paramiko.sftp_attr import SFTPAttributes
 
46
    from paramiko.sftp_file import SFTPFile
41
47
 
42
48
 
43
49
SYSTEM_HOSTKEYS = {}
196
202
                 Some implementations may return objects which can be read
197
203
                 past this length, but this is not guaranteed.
198
204
        """
 
205
        # TODO: implement get_partial_multi to help with knit support
199
206
        f = self.get(relpath)
200
207
        f.seek(start)
201
208
        return f
207
214
        :param relpath: Location to put the contents, relative to base.
208
215
        :param f:       File-like or string object.
209
216
        """
210
 
        try:
211
 
            finalpath = self._abspath(relpath)
212
 
            tmp_path = '%s.tmp.%.9f.%d.%d' % (finalpath, time.time(),
213
 
                       os.getpid(), random.randint(0,0x7FFFFFFF))
214
 
            # I would *really* like to pass in the SFTP_FLAG_EXCL,
215
 
            # but there doesn't seem to be a way to do it in the
216
 
            # self._sftp.file() interface.
217
 
            fout = self._sftp.file(tmp_path, 'wb')
218
 
        except IOError, e:
219
 
            # Maybe this should actually be using the relative form of tmp_path
220
 
            self._translate_io_exception(e, relpath)
221
 
        except (IOError, paramiko.SSHException), x:
222
 
            raise SFTPTransportError('Unable to open file %r' % (tmp_path,), x)
 
217
        finalpath = self._abspath(relpath)
 
218
        tmp_path = '%s.tmp.%.9f.%d.%d' % (finalpath, time.time(),
 
219
                   os.getpid(), random.randint(0,0x7FFFFFFF))
 
220
        fout = self._sftp_open_exclusive(tmp_path, relpath)
223
221
 
224
222
        try:
225
223
            try:
239
237
                pass
240
238
            raise e
241
239
        else:
242
 
            fout.close()
243
240
            try:
244
241
                self._sftp.rename(tmp_path, finalpath)
245
242
            except IOError, e:
373
370
 
374
371
        :return: A lock object, which should be passed to Transport.unlock()
375
372
        """
376
 
        # FIXME: there should be something clever i can do here...
 
373
        # This is a little bit bogus, but basically, we create a file
 
374
        # which should not already exist, and if it does, we assume
 
375
        # that there is a lock, and if it doesn't, the we assume
 
376
        # that we have taken the lock.
377
377
        class BogusLock(object):
378
378
            def __init__(self, path):
379
379
                self.path = path
502
502
        except IOError:
503
503
            pass
504
504
        return False
 
505
 
 
506
    def _sftp_open_exclusive(self, path, relpath=None):
 
507
        """Open a remote path exclusively.
 
508
 
 
509
        SFTP supports O_EXCL (SFTP_FLAG_EXCL), which fails if
 
510
        the file already exists. However it does not expose this
 
511
        at the higher level of SFTPClient.open(), so we have to
 
512
        sneak away with it.
 
513
 
 
514
        WARNING: This breaks the SFTPClient abstraction, so it
 
515
        could easily break against an updated version of paramiko.
 
516
 
 
517
        :param path: This should be an absolute remote path.
 
518
        :param relpath: Just a parameter so we can throw better exceptions.
 
519
        """
 
520
        if relpath is None:
 
521
            relpath = path
 
522
        attr = SFTPAttributes()
 
523
        mode = (SFTP_FLAG_WRITE | SFTP_FLAG_CREATE 
 
524
                | SFTP_FLAG_TRUNC | SFTP_FLAG_EXCL)
 
525
        try:
 
526
            t, msg = self._sftp._request(CMD_OPEN, path, mode, attr)
 
527
            if t != CMD_HANDLE:
 
528
                raise SFTPTransportError('Expected an SFTP handle')
 
529
            handle = msg.get_string()
 
530
            return SFTPFile(self._sftp, handle, 'w', -1)
 
531
        except IOError, e:
 
532
            self._translate_io_exception(e, relpath)
 
533
        except paramiko.SSHException, x:
 
534
            raise SFTPTransportError('Unable to open file %r' % (path,), x)
 
535