-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsetup.py
executable file
·134 lines (109 loc) · 3.78 KB
/
setup.py
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
#!/usr/bin/python3
# -*- encoding: utf8 -*-
"""
Update the user shell configuration to include the Github-based config.
"""
import os
import re
import sys
USER_HOME=os.path.realpath(os.path.expanduser('~'))
GITHUB_SHELL_PATH=os.path.dirname(os.path.realpath(__file__))
# Create a HOME-relative (or absolute) version of GITHUB_SHELL_PATH
if os.path.relpath(GITHUB_SHELL_PATH, USER_HOME).startswith('..'):
GITHUB_SHELL_RELPATH=GITHUB_SHELL_PATH
else:
GITHUB_SHELL_RELPATH=os.path.join(
'${HOME}',
os.path.relpath(GITHUB_SHELL_PATH, USER_HOME))
def ExpandAll(path):
return os.path.expanduser(os.path.expandvars(path))
def ParseConfig(path):
var_re = re.compile(r'%%(\w+)%%')
vardict = dict()
vardict['CONFIG_ROOT'] = GITHUB_SHELL_PATH
vardict['CONFIG_ROOT_RELATIVE'] = GITHUB_SHELL_RELPATH
vardict['CONFIG_ABSPATH'] = os.path.dirname(os.path.realpath(path))
vardict['CONFIG_RELPATH'] = os.path.relpath(
os.path.dirname(os.path.realpath(path)),
GITHUB_SHELL_PATH)
marker = None
files = []
contents = []
with open(path) as fp:
for line in fp:
if line.startswith("%% marker:"):
marker = re.match(r'^%% marker:\s+(.*)', line).group(1)
if not marker.endswith('\n'):
marker += '\n'
elif line.startswith("%% file:"):
files.append(re.match(r'^%% file:\s+(.*)', line).group(1))
else:
for key, value in vardict.items():
line = line.replace('%%{0}%%'.format(key), value)
contents.append(line)
while len(contents) and not contents[0].strip(): # Remove blank lines from the beginning
contents.pop(0)
while len(contents) and not contents[-1].strip(): # Remove blank lines from the end
contents.pop()
return { 'marker': marker, 'files': files, 'contents': contents }
def UpdateFile(path, contentLines, marker, dryrun=False):
"""
Update the given file with the provided config lines.
"""
path = os.path.realpath(ExpandAll(path))
print('Updating ~/%s...' % (os.path.relpath(path, USER_HOME)))
beginComment = re.sub(r'<>', 'Begin', marker)
endComment = re.sub(r'<>', 'End', marker)
with open(path, 'r') as fp:
lines = fp.readlines()
outlines = []
incomment = False
found = False
for line in lines:
if line.lower() == beginComment.lower() and not found:
incomment = True
elif line.lower() == endComment.lower():
outlines.append(beginComment)
outlines.extend(contentLines)
outlines.append(endComment)
incomment = False
found = True
elif not incomment:
outlines.append(line)
if not found:
# Append the config to the end of the existing file if an existing config
# was not found.
outlines.append(beginComment)
outlines.extend(contentLines)
outlines.append(endComment)
if dryrun: # Write to standard output instead
print('Update %s:' % (path))
sys.stdout.writelines(outlines)
print('\n\n')
else:
with open(path, 'w') as fp:
fp.writelines(outlines)
def FindConfigs(configName='.shell_setup'):
configs = []
for root, dirs, files in os.walk(GITHUB_SHELL_PATH):
if configName in files:
configs.append(os.path.join(root, configName))
return configs
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--dry-run", action="store_true",
help="print to the terminal instead of writing to the files")
args = parser.parse_args()
for configFile in FindConfigs():
config = ParseConfig(configFile)
marker = config['marker']
files = config['files']
contents = config['contents']
if not marker or not files or not contents:
continue
for path in files:
if os.path.exists(ExpandAll(path)):
UpdateFile(path, contents, marker, dryrun=args.dry_run)
if __name__ == '__main__':
main()