-
Notifications
You must be signed in to change notification settings - Fork 15
/
generate_spec_sources.py
executable file
·148 lines (120 loc) · 4.6 KB
/
generate_spec_sources.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
#!/usr/bin/python3
import sys
import io
import re
import yaml
COLLECTION_RELEASE = "collection_release.yml"
SPECFILE_IN = sys.argv[1]
SPECFILE_OUT = sys.argv[2]
BEGIN_SOURCES_MARKER = "# BEGIN AUTOGENERATED SOURCES"
END_SOURCES_MARKER = "# END AUTOGENERATED SOURCES"
BEGIN_SETUP_MARKER = "# BEGIN AUTOGENERATED SETUP"
END_SETUP_MARKER = "# END AUTOGENERATED SETUP"
BEGIN_SETUP_TMPL = "%setup -q "
END_SETUP_TMPL = " -n %{getarchivedir 0}"
class Replacement:
"""Class describing a replacement of lines between markers in a file"""
def __init__(self, begin_marker, end_marker, generate):
self.begin_marker = begin_marker
self.end_marker = end_marker
self.generate = generate
self.throwaway = False
self.marker_seen = False
def process_line(self, line):
# did we change the input line? If not, we are merely returning it.
changed = False
of = io.StringIO()
if not self.throwaway:
of.write(line)
if line.strip() == self.begin_marker:
if self.marker_seen:
sys.exit("Duplicate replacement section")
changed = True
self.generate(of)
self.throwaway = True
self.marker_seen = True
elif line.strip() == self.end_marker:
sys.exit("End marker '{}' without begin marker".format(self.end_marker))
else:
if line.strip() == self.end_marker:
self.throwaway = False
of.write(line)
elif line.strip() == self.begin_marker:
sys.exit("Duplicate begin marker: {}".format(self.begin_marker))
else:
# we discarded the input line
changed = True
return (changed, of.getvalue())
def inside(self):
"""Are we currently inside the replacement block?"""
return self.throwaway
def after(self):
"""Have we been inside the replacement block?"""
return self.marker_seen and not self.throwaway
def ref_is_commit(ref):
if re.match(r"[0-9a-f]{5,40}$", ref):
# is a SHA-1 commit id
return True
elif re.search(r"[0-9]+[.][0-9]+[.][0-9]+", ref):
# is a tag
# search() and not match() because there could be something in front
# of the semantic version number, like literal "v" - we have tags looking
# both like "v1.2.0" and like "1.2.0"
return False
else:
sys.exit(f"unknown format of reference '{ref}': neither commit nor semver tag")
def generate_sources(output):
k = list(rolesbysourcenum.keys())
k.sort()
for i in k:
r = rolesbysourcenum[i]
org = roles[r].get("org")
repo = roles[r].get("repo")
ref = roles[r]["ref"]
if org:
# If we support other hosting service than Github, the format
# of collection_release.yml will have to change a bit.
output.write(f"%global forgeorg{i} https://github.com/{org}\n")
if repo:
output.write(f"%global repo{i} {repo}\n")
output.write(f"%global rolename{i} {r}\n")
if ref_is_commit(ref):
output.write(f"%defcommit {i} {ref}\n\n")
else:
output.write(f"%deftag {i} {ref}\n\n")
for i in k:
output.write(f"Source{i}: %{{archiveurl{i}}}\n")
def generate_setup(output):
k = list(rolesbysourcenum.keys())
k.sort()
output.write(
BEGIN_SETUP_TMPL + " ".join(f"-a{i}" for i in k) + END_SETUP_TMPL + "\n"
)
with open(COLLECTION_RELEASE, "r") as cf:
roles = yaml.safe_load(cf)
for rolename, roleinfo in roles.items():
print(roleinfo)
rolesbysourcenum = {
roleinfo["sourcenum"]: rolename for rolename, roleinfo in roles.items()
}
sources_replacement = Replacement(
BEGIN_SOURCES_MARKER, END_SOURCES_MARKER, generate_sources
)
setup_replacement = Replacement(BEGIN_SETUP_MARKER, END_SETUP_MARKER, generate_setup)
f = open(SPECFILE_IN, "r")
of = open(SPECFILE_OUT, "w")
for line in f:
changed_sources, new_line = sources_replacement.process_line(line)
changed_setup, new_new_line = setup_replacement.process_line(new_line)
if changed_sources and changed_setup:
sys.exit(
"Begin marker {} in the output of sources replacement".format(
setup_replacement.begin_marker
)
)
of.write(new_new_line)
for i in (sources_replacement, setup_replacement):
if i.inside():
sys.exit("Missing end marker '{}'".format(i.end_marker))
elif not i.after():
sys.exit("Missing begin marker '{}'".format(i.begin_marker))