-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBuildUtils.py
179 lines (146 loc) · 4.39 KB
/
BuildUtils.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import sys, os, locale, re
encoding = locale.getpreferredencoding()
def makeEscape():
value = sys.argv[1]
value = re.sub('(\\\\*)([ \\t])', '\\1\\1\\\\\\2', value)
value = re.sub('(\\\\*)$', '\\1\\1', value)
sys.stdout.write(value)
def _deepEncode(value):
if isinstance(value, dict):
return {_deepEncode(k): _deepEncode(v) for k, v in value.items()}
if isinstance(value, list):
return [_deepEncode(e) for e in value]
if isinstance(value, unicode):
return value.encode(encoding)
return value
def _deepDecode(value):
if isinstance(value, dict):
return {_deepDecode(k): _deepDecode(v) for k, v in value.items()}
if isinstance(value, list):
return [_deepDecode(e) for e in value]
if isinstance(value, str):
return value.decode(encoding)
return value
def _getErrorDescription(error):
info = CF.CFErrorCopyUserInfo(error)
if info is not None:
try:
return info['NSDebugDescription']
except KeyError:
pass
return CF.CFErrorCopyDescription(error)
def _readPList(f):
data = f.read()
properties, _, error = CF.CFPropertyListCreateWithData(
None, CF.CFDataCreateWithBytesNoCopy(
None, data, len(data), CF.kCFAllocatorNull
), CF.kCFPropertyListMutableContainersAndLeaves, None, None
)
if error is not None:
raise RuntimeError(_getErrorDescription(error).encode(encoding))
return properties
def _writePList(properties, f):
data, error = CF.CFPropertyListCreateData(
None, properties, CF.kCFPropertyListXMLFormat_v1_0, 0, None
)
if error is not None:
raise RuntimeError(_getErrorDescription(error).encode(encoding))
if data is None:
raise RuntimeError('Failed to serialize properties')
f.write(data)
def _cleanArray(array):
for e in array:
if e is None:
continue
e = e.strip()
if e == '':
continue
yield e
def getProgramArguments(executable):
h = os.path.abspath(os.environ['HOME'])
lh = len(h)
e = os.path.abspath(executable)
if not(lh > 0 and e.startswith(h) and (len(e) == lh or e[lh] == '/')):
return [e]
e = re.sub('([\\\\"`\\$])', '\\\\\\1', e[lh:])
return ['/bin/sh', '-c', 'exec "$HOME' + e + '"']
def getSessionTypes(sessionTypesString):
sessionArray = re.split(",", sessionTypesString)
sessionArray = [e for e in _cleanArray(sessionArray)]
al = len(sessionArray)
if al > 1:
return sessionArray
if al > 0:
return sessionArray[0]
return None
def getBoolean(value):
return bool(distutils.util.strtobool(str(value)))
def _processSettings(properties, settings):
keys = settings[0::2]
expressions = settings[1::2]
if len(expressions) < len(keys):
expressions.append('None')
for key, expression in zip(keys, expressions):
key = key.decode(encoding)
try:
value = _deepEncode(properties[key])
except KeyError:
value = None
value = eval(expression, globals(), {'value': value})
if value is None:
try:
del properties[key]
except KeyError:
pass
else:
properties[key] = _deepDecode(value)
def processPList():
global CF, distutils
import CoreFoundation as CF, distutils.util
plist = sys.argv[1]
with open(plist, 'rb') as f:
properties = _readPList(f)
_processSettings(properties, sys.argv[2:])
with os.fdopen(os.dup(sys.stdout.fileno()), 'wb') as f:
_writePList(properties, f)
def _getCurrentVariables(argv):
variables = argv[0::2]
values = argv[1::2]
if len(values) < len(variables):
values.append('')
result = {}
noop = False
for k, v in zip(variables, values):
if k.startswith('.') or k.startswith('MAKE') or \
k == '-*-command-variables-*-' or \
k.startswith('__CF_') or \
k == 'SHLVL' or k == 'OLDPWD' or k == '_' or \
k.endswith('DIR'):
continue
if k == 'MFLAGS':
if re.match('-\\w*n', v) is not None:
noop = True
continue
try:
if v == os.environ[k]:
continue
except KeyError:
pass
result[k.decode(encoding)] = v.decode(encoding)
return result, noop
def checkAndSaveMakeVariables():
import json
varsfile = sys.argv[1]
makefile = sys.argv[2]
try:
with open(varsfile, 'rb') as f:
saved = json.load(f)
except:
saved = {}
current, noop = _getCurrentVariables(sys.argv[3:])
if current != saved:
if not noop:
with open(varsfile, 'wb') as f:
json.dump(current, f, indent=2)
os.utime(makefile, None)
sys.stdout.write('1')