forked from wraeth/misc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
check-files.py
executable file
·252 lines (189 loc) · 6.62 KB
/
check-files.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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/usr/bin/env python3
"""
Checks ebuilds in current directory for required files and ensures they exist
within a 'files' subdirectory; as well as listing files in FILESDIR that are
no longer required.
"""
import argparse
import os
import re
import sys
from portage.output import colorize as colorize
error_colour = 'red'
warn_colour = 'yellow'
good_colour = 'green'
cpv_colour = 'blue'
file_colour = 'teal'
show_output = True
debug = False
def main() -> int:
"""Entry point for CLI usage."""
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--debug', help='Print line matches for debug', action='store_true')
parser.add_argument('-q', '--quiet', help='Print no output (overrides verbose)', action='store_false')
parser.add_argument('-n', '--nocolour', help='Do not colourise output', action='store_true')
parser.add_argument('-p', '--path', help='Path to ebuild directory', default=os.path.abspath(os.curdir))
args = parser.parse_args()
if args.nocolour:
global colorize
colorize = nocolor
global show_output
global debug
show_output = args.quiet
debug = args.debug
try:
return check_files(args.path)
except RuntimeError as err:
print_err(str(err))
return -1
def check_files(directory: str) -> int:
"""
Checks files in $(pwd)/files for required files.
:param directory: path to ebuild directory
:param debug: output match string for debugging
:return: number of missing required files
"""
assert isinstance(directory, str)
assert isinstance(debug, bool)
ebuilds = [f for f in os.listdir(directory) if f.endswith('.ebuild')]
if len(ebuilds) == 0:
raise RuntimeError('Not a valid ebuild directory: %r' % directory)
files = {}
missing_files = 0
for ebuild in ebuilds:
P = ebuild[:-7]
P = re.sub('-r\d+', '', P)
PN = re.sub('-\d.*', '', P)
PV = re.search('-\d.*', P).group(0)[1:]
for line in open(os.path.join(directory, ebuild), 'r').readlines():
if 'FILESDIR' in line:
org_line = line.strip()
# Ignore comment lines
if re.match('\s*#', line):
continue
line = line.replace('${FILESDIR}', 'files')
line = line.replace('${P}', P)
line = line.replace('${PN}', PN)
line = line.replace('${PV}', PV)
line = line.replace('"', '')
line = line.replace('.patch)', '.patch')
print_dbg('%r -> %r' % (org_line, line.strip()))
try:
required_file = re.search('files\S+', line).group(0)
except AttributeError:
print_err('Unable to get path from string: %r' % line.strip())
continue
try:
files[P]
except KeyError:
files[P] = []
files[P].append(required_file)
file_list = list(files.keys())
file_list.sort()
files_dir_path = os.path.join(directory, 'files')
if len(file_list) > 0:
if not os.path.isdir(files_dir_path):
print_err('FILESDIR does not exist - %d files missing!' % len(file_list))
# All patch files are missing
for l in files.values():
for v in l:
missing_files += len(v)
else:
for pkg in file_list:
print_out(_p_pkg(pkg))
for f in files[pkg]:
if not os.path.isfile(os.path.join(directory, f)):
print_dbg('PATH NOT FOUND: %r' % os.path.join(directory, 'files', f))
print_out(' ', _p_warn('missing:'), _p_file(os.path.basename(f)))
missing_files += 1
else:
print_out(' ', _p_good(' found:'), _p_file(os.path.basename(f)))
required_files = [v for l in files.values() for v in l]
print_dbg(required_files)
if os.path.isdir(files_dir_path):
not_required = []
files_dir = [f for f in os.listdir(files_dir_path)]
for f in files_dir:
path = os.path.join('files', f)
if path not in required_files:
print_dbg('PATH NOT REQUIRED: %r' % path)
not_required.append(path)
if len(not_required) > 0:
print_out('')
print_out('The following files are no longer required:')
[print_out(' ', _p_file(os.path.basename(f))) for f in not_required]
return missing_files
def print_out(*message: list) -> None:
"""
Wrapper for conditionally printing messages.
:param message: message to print
:return: None
"""
global show_output
if show_output:
print(' '.join(message))
return
def print_err(*message: list) -> None:
"""
Simple wrapper for printing an error message.
:param message: error message to print.
:return: None
"""
print(_p_error('Error:'), ' '.join(message), file=sys.stderr)
return
def print_dbg(*message: list) -> None:
"""
Simple wrapper for printing debug output.
:param message: error message to print.
:return: None
"""
global debug
if debug:
print(_p_error('DEBUG: '), ' '.join(message), file=sys.stderr)
return
# noinspection PyUnusedLocal
def nocolor(color: str, string: str) -> str:
"""
Override function if called with --nocolour
:param color: String for colour to be used (for compat)
:param string: Text to (not) colourise
:return:
"""
return string
def _p_good(name: str) -> str:
"""
Prints good output consistently.
:param name: Name to print
:return: string of colourised name
"""
return colorize(good_colour, name)
def _p_error(addr: str) -> str:
"""
Prints an error text consistently.
:param addr: Address to print
:return: colourised address
"""
return colorize(error_colour, addr)
def _p_pkg(pkg: str) -> str:
"""
Prints a package name consistently.
:param pkg: Package name to print
:return: colourised package name
"""
return colorize(cpv_colour, pkg)
def _p_file(field: str) -> str:
"""
Prints a file name consistently.
:param field: Field label to print
:return: colourised string
"""
return colorize(file_colour, field)
def _p_warn(txt: str) -> str:
"""
Prints warning text consistently.
:param txt: Text to print (addr or "Maintainer Needed" etc)
:return: colourised text
"""
return colorize(warn_colour, txt)
if __name__ == '__main__':
exit(main())