blob: 265133c93e3f3134d7a7f5d324527f1410e91da5 [file] [log] [blame]
koder aka kdanilov80cb6192015-02-02 03:06:08 +02001import os.path
2
3
4def normalize_dirpath(dirpath):
5 while dirpath.endswith("/"):
6 dirpath = dirpath[:-1]
7 return dirpath
8
9
10def ssh_mkdir(sftp, remotepath, mode=0777, intermediate=False):
11 remotepath = normalize_dirpath(remotepath)
12 if intermediate:
13 try:
14 sftp.mkdir(remotepath, mode=mode)
15 except IOError:
16 ssh_mkdir(sftp, remotepath.rsplit("/", 1)[0], mode=mode,
17 intermediate=True)
18 return sftp.mkdir(remotepath, mode=mode)
19 else:
20 sftp.mkdir(remotepath, mode=mode)
21
22
23def ssh_copy_file(sftp, localfile, remfile, preserve_perm=True):
24 sftp.put(localfile, remfile)
25 if preserve_perm:
26 sftp.chmod(remfile, os.stat(localfile).st_mode & 0777)
27
28
29def put_dir_recursively(sftp, localpath, remotepath, preserve_perm=True):
30 "upload local directory to remote recursively"
31
koder aka kdanilov4ec0f712015-02-19 19:19:27 -080032 # hack for localhost connection
33 if hasattr(sftp, "copytree"):
34 sftp.copytree(localpath, remotepath)
35 return
36
koder aka kdanilov80cb6192015-02-02 03:06:08 +020037 assert remotepath.startswith("/"), "%s must be absolute path" % remotepath
38
39 # normalize
40 localpath = normalize_dirpath(localpath)
41 remotepath = normalize_dirpath(remotepath)
42
43 try:
44 sftp.chdir(remotepath)
45 localsuffix = localpath.rsplit("/", 1)[1]
46 remotesuffix = remotepath.rsplit("/", 1)[1]
47 if localsuffix != remotesuffix:
48 remotepath = os.path.join(remotepath, localsuffix)
49 except IOError:
50 pass
51
52 for root, dirs, fls in os.walk(localpath):
53 prefix = os.path.commonprefix([localpath, root])
54 suffix = root.split(prefix, 1)[1]
55 if suffix.startswith("/"):
56 suffix = suffix[1:]
57
58 remroot = os.path.join(remotepath, suffix)
59
60 try:
61 sftp.chdir(remroot)
62 except IOError:
63 if preserve_perm:
64 mode = os.stat(root).st_mode & 0777
65 else:
66 mode = 0777
67 ssh_mkdir(sftp, remroot, mode=mode, intermediate=True)
68 sftp.chdir(remroot)
69
70 for f in fls:
71 remfile = os.path.join(remroot, f)
72 localfile = os.path.join(root, f)
73 ssh_copy_file(sftp, localfile, remfile, preserve_perm)
koder aka kdanilov4643fd62015-02-10 16:20:13 -080074
75
76def copy_paths(conn, paths):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080077 sftp = conn.open_sftp()
koder aka kdanilov4643fd62015-02-10 16:20:13 -080078 try:
79 for src, dst in paths.items():
80 try:
81 if os.path.isfile(src):
82 ssh_copy_file(sftp, src, dst)
83 elif os.path.isdir(src):
84 put_dir_recursively(sftp, src, dst)
85 else:
86 templ = "Can't copy {0!r} - " + \
87 "it neither a file not a directory"
88 msg = templ.format(src)
89 raise OSError(msg)
90 except Exception as exc:
91 tmpl = "Scp {0!r} => {1!r} failed - {2!r}"
92 msg = tmpl.format(src, dst, exc)
93 raise OSError(msg)
94 finally:
95 sftp.close()