-
Notifications
You must be signed in to change notification settings - Fork 0
/
cfg-sync
executable file
·105 lines (74 loc) · 2.68 KB
/
cfg-sync
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
#!/usr/bin/env python3
import os,shutil
from datetime import datetime
def process_file(paths_file):
pairs = []
with open(paths_file, 'r') as f:
for (ix, line) in enumerate(f.readlines()):
if ix == 0 or line.startswith('!'):
continue
source,dest = line.split()
assert source.startswith("./"), "source path must start with ./"
pairs.append((source, os.path.expanduser(dest)))
return pairs
def make_backup(path):
path = path.rstrip('/')
now = datetime.now()
time_suffix = now.strftime("%Y%m%d_%H%M%S")
name = f"{path}_{time_suffix}backup"
return shutil.make_archive(name, "gztar", base_dir=path)
def validate_path(*paths):
for path in paths:
if not os.path.exists(path):
raise Exception(f"Path {path} doesn't exist")
def rm(path):
if os.path.isfile(path):
os.remove(path)
else:
shutil.rmtree(path)
def cp(source, dest):
if os.path.isfile(source):
shutil.copy2(source, dest)
else:
shutil.copytree(source, dest)
def collect(paths_file):
paths = process_file(paths_file)
do(map(lambda x: (x[1], x[0]), paths))
def distribute(paths_file, risky=False):
answer = input('Are you sure that you want to distribute? This will overwrite existing configuration on the system.\nType "YES!" to confirm: ')
if answer == "YES!":
paths = process_file(paths_file)
do(paths, keep_backup=not risky)
else:
print("Aborted")
def do(paths, keep_backup=False):
for source,dest in paths:
backup_path = None
validate_path(source)
if os.path.exists(dest):
backup_path = make_backup(dest)
rm(dest)
cp(source, dest)
if backup_path and not keep_backup:
rm(backup_path)
print("Done!")
def check_git():
ret = os.system("git branch")
if ret != 0:
raise Exception("This tool is unsafe, make sure you're in the GIT repo")
import argparse
parser = argparse.ArgumentParser(prog="cfg-sync", description='Syncrhonize config files', usage='%(prog)s {collect | distribute} <paths_file>')
parser.add_argument('operation', type=str, help='collect | distribute')
parser.add_argument('paths_file', type=str, help='file with paths')
parser.add_argument('--risky', action='store_true', help='Do not keep backups for changed configs on the system')
args = parser.parse_args()
try:
check_git()
if args.operation == "collect":
collect(args.paths_file)
elif args.operation == "distribute":
distribute(args.paths_file, args.risky)
else:
parser.print_help()
except Exception as e:
print(f"Error: {e}")