blob: 265133c93e3f3134d7a7f5d324527f1410e91da5 [file] [log] [blame]
import os.path
def normalize_dirpath(dirpath):
while dirpath.endswith("/"):
dirpath = dirpath[:-1]
return dirpath
def ssh_mkdir(sftp, remotepath, mode=0777, intermediate=False):
remotepath = normalize_dirpath(remotepath)
if intermediate:
try:
sftp.mkdir(remotepath, mode=mode)
except IOError:
ssh_mkdir(sftp, remotepath.rsplit("/", 1)[0], mode=mode,
intermediate=True)
return sftp.mkdir(remotepath, mode=mode)
else:
sftp.mkdir(remotepath, mode=mode)
def ssh_copy_file(sftp, localfile, remfile, preserve_perm=True):
sftp.put(localfile, remfile)
if preserve_perm:
sftp.chmod(remfile, os.stat(localfile).st_mode & 0777)
def put_dir_recursively(sftp, localpath, remotepath, preserve_perm=True):
"upload local directory to remote recursively"
# hack for localhost connection
if hasattr(sftp, "copytree"):
sftp.copytree(localpath, remotepath)
return
assert remotepath.startswith("/"), "%s must be absolute path" % remotepath
# normalize
localpath = normalize_dirpath(localpath)
remotepath = normalize_dirpath(remotepath)
try:
sftp.chdir(remotepath)
localsuffix = localpath.rsplit("/", 1)[1]
remotesuffix = remotepath.rsplit("/", 1)[1]
if localsuffix != remotesuffix:
remotepath = os.path.join(remotepath, localsuffix)
except IOError:
pass
for root, dirs, fls in os.walk(localpath):
prefix = os.path.commonprefix([localpath, root])
suffix = root.split(prefix, 1)[1]
if suffix.startswith("/"):
suffix = suffix[1:]
remroot = os.path.join(remotepath, suffix)
try:
sftp.chdir(remroot)
except IOError:
if preserve_perm:
mode = os.stat(root).st_mode & 0777
else:
mode = 0777
ssh_mkdir(sftp, remroot, mode=mode, intermediate=True)
sftp.chdir(remroot)
for f in fls:
remfile = os.path.join(remroot, f)
localfile = os.path.join(root, f)
ssh_copy_file(sftp, localfile, remfile, preserve_perm)
def copy_paths(conn, paths):
sftp = conn.open_sftp()
try:
for src, dst in paths.items():
try:
if os.path.isfile(src):
ssh_copy_file(sftp, src, dst)
elif os.path.isdir(src):
put_dir_recursively(sftp, src, dst)
else:
templ = "Can't copy {0!r} - " + \
"it neither a file not a directory"
msg = templ.format(src)
raise OSError(msg)
except Exception as exc:
tmpl = "Scp {0!r} => {1!r} failed - {2!r}"
msg = tmpl.format(src, dst, exc)
raise OSError(msg)
finally:
sftp.close()