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
|
#!/usr/bin/env python3
import argparse
import sys
from pathlib import Path
def handle_file(path):
"""
Return a tuple of (header, path) for the file at path.
If the file does not have a header, the header is the empty string.
"""
with open(path) as fd:
header = fd.readline()
if header.startswith("! "):
return header, path
else:
return "", path
def merge(dest, files):
"""
Merge the content of all files into the file dest.
The first line of each file is an optional section header in the form
e.g.
! model = keycodes
Where two sections have identical headers, the second header is skipped.
Special case are header-less files which we store with the empty string
as header, these need to get written out first.
"""
def sort_basename(path):
return path.name
# sort the file list by basename
files.sort(key=sort_basename)
# pre-populate with the empty header so it's the first one to be written
# out. We use section_names to keep the same order as we get the files
# passed in (superfluous with python 3.6+ since the dict keeps the
# insertion order anyway).
sections = {"": []}
section_names = [""]
for path in files:
# files may exist in srcdir or builddir, depending whether they're
# generated
header, path = handle_file(path)
paths = sections.get(header, [])
paths.append(path)
sections[header] = paths
if header not in section_names:
section_names.append(header)
for header in section_names:
if header:
dest.write("\n")
dest.write(header)
for f in sections[header]:
with open(f) as fd:
if header:
fd.readline() # drop the header
dest.write(fd.read())
if __name__ == "__main__":
parser = argparse.ArgumentParser("rules file merge script")
parser.add_argument("--dest", type=str, default=None)
parser.add_argument("--srcdir", type=str)
parser.add_argument("--builddir", type=str)
parser.add_argument("files", nargs="+", type=str)
ns = parser.parse_args()
if ns.dest is None:
dest = sys.stdout
else:
dest = ns.dest
with dest or open(dest, "w") as fd:
basename = Path(sys.argv[0]).name
fd.write(
"// DO NOT EDIT THIS FILE - IT WAS AUTOGENERATED BY {} FROM rules/*.part\n".format(
basename
)
)
fd.write("//\n")
def find_file(f):
if ns.builddir:
path = Path(ns.builddir) / f
if path.exists():
return path
if ns.srcdir:
path = Path(ns.srcdir) / f
if path.exists():
return path
return Path(f)
merge(fd, [find_file(f) for f in ns.files])
|