-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpsync.py
More file actions
executable file
·150 lines (120 loc) · 4.5 KB
/
psync.py
File metadata and controls
executable file
·150 lines (120 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python3
__author__ = 'Ray, github.com/ryt'
__version__ = 'psync version 1.1.6.dev0'
__license__ = 'MIT'
import sys
from argparse import ArgumentParser
from configparser import ConfigParser
from collections import OrderedDict
from subprocess import call
parser = ArgumentParser(description='A simple python wrapper to manage rsync.')
parser.add_argument('-a', '--app', help='start syncing with app name', metavar='appname', default=False, nargs='?', const='empty')
parser.add_argument('-l', '--list', help='list all apps and directories', action='store_true')
parser.add_argument('-o', help='override new files on the reciever, rsync !u', action='store_true')
parser.add_argument('-d', help='delete extra files on destination, rsync --delete', action='store_true')
parser.add_argument('-z', help='fuz[z]y option: rsync fuzzy option with delays, rsync --fuzzy --delay-updates --delete-delay', action='store_true')
parser.add_argument('-s', help='show the rsync command used and exit', action='store_true')
parser.add_argument('-c', help='show the rsync command used and exit', action='store_true')
parser.add_argument('-v', '--version', action='store_true')
parser.add_argument('aname', nargs='?', metavar='appname', help='start syncing with app name (-a)')
parser.add_argument('-f', '--conf', help='set the path of the config file with list of apps')
args = parser.parse_args()
# default path of the conf file
conf = 'psync.ini'
# if a custom path is set (-f, --conf), use that path instead
if args.conf:
conf = args.conf
def main():
if args.list:
if any(apps):
print('')
app_list()
print('')
else:
print('No apps yet, go add some!')
elif args.app or args.aname:
app_run(args)
elif args.version:
print(__version__)
else:
print('Specify an app name, or to get a list use -l or --list')
def app_run(args):
name = args.app or args.aname
if name in apps:
dir1 = apps[name][0]
dir2 = samef(apps[name])
opt = '-rtpvu' if sys.platform == 'darwin' else '-rtpvus'
if args.o:
opt = '-rtpv' if sys.platform == 'darwin' else '-rtpvs'
cmd = ['rsync', opt, eopt, dir1, dir2]
if args.d:
cmd = ['rsync', opt, '--delete', eopt, dir1, dir2]
if args.z:
cmd = ['rsync', opt, '--fuzzy', '--delay-updates', eopt, dir1, dir2]
# flatten the cmd (list) / after adding --exclude (eopt)
cmd = [i for s in cmd for i in (s if isinstance(s, list) else [s])]
if args.s or args.c:
print(' '.join(cmd))
print(cmd)
exit()
call(cmd)
else:
print("App (%s) dun't exist!" % name)
def app_list():
len1, len2, len3 = [], [], []
for app, fol in apps.items():
len1.append(len(app))
len2.append(len(fol[0]))
len3.append(len(samef(fol)))
max1, max2, max3 = max(len1), max(len2), max(len3)
for app, fol in apps.items():
sp1 = max1-len(app)
sp2 = max2-len(fol[0])
sp3 = max3-len(samef(fol))
print(' %s%s %s%s %s%s' % (app, spc(sp1), fol[0], spc(sp2), samef(fol), spc(sp3) ))
def samef(l):
return l[1].replace(':same', ':' + l[0])
def spc(num):
return ''.join([' ']*num) if num else ''
def err_nolist():
print("App list not found in '%s'. Add a valid list or specify config file (-f, --conf) " % (conf))
# parse config file
plist = ConfigParser()
plist.read(conf)
# check the [replace] section & prepare it
rep_sec = False
if plist.has_section('replace'):
rep_sec = True
# check the [list] section
if plist.has_section('list'):
a = {}
for key, val in plist.items('list'):
vals = val.replace("\\ ", "%20")
vals = ' '.join(vals.split()).split(' ')
vals = [v.replace("%20", ' ') for v in vals]
# [replace] section: if there are a list of replacements -> make substitutions
if rep_sec:
rvals0 = vals[0]
rvals1 = vals[1]
for rk, rv in plist.items('replace'):
rvals0 = rvals0.replace(rk, rv)
rvals1 = rvals1.replace(rk, rv)
a[key] = [rvals0, rvals1]
else:
a[key] = [vals[0], vals[1]]
else:
err_nolist()
exit()
apps = OrderedDict(sorted(a.items()))
# global additional rsync options
# - excludes .git/ & .DS_Store by default, add more to the conf file
# - to override, edit the conf file, or use the (-s) or (-c) option and run rsync directly
eopt = []
setexcl = plist.get('settings', 'exclude')
if setexcl:
paths = setexcl.replace("\\ ", "%20")
paths = ' '.join(paths.split()).split(' ')
paths = [p.replace("%20", ' ') for p in paths]
eopt = ['--exclude=' + p for p in paths]
if __name__ == '__main__':
main()