33
33
TransportNotPossible, NoSuchFile, PathNotChild,
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
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')
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/.
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()
173
174
f = open(bzr_hostkey_path, 'w')
174
175
f.write('# SSH host keys collected by bzr\n')
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'):
355
356
tmp_abspath = self._abspath(tmp_relpath)
356
357
fout = self._sftp_open_exclusive(tmp_relpath)
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)
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
369
375
self._sftp.remove(tmp_abspath)
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)
378
self._sftp.rename(final_path, tmp_safety)
385
self._sftp.rename(tmp_abspath, final_path)
386
except (paramiko.SSHException, IOError), e:
387
self._translate_io_exception(e, relpath, ': unable to rename')
393
self._sftp.unlink(tmp_safety)
395
self._sftp.rename(tmp_safety, final_path)
397
380
def iter_files_recursive(self):
398
381
"""Walk the relative paths of all files in this transport."""
513
496
return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
498
def _rename(self, abs_from, abs_to):
499
"""Do a fancy rename on the remote server.
501
Using the implementation provided by osutils.
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))
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)
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)
524
516
def delete(self, relpath):
525
517
"""Delete the item at relpath"""
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)