This repository has been archived by the owner on Nov 21, 2022. It is now read-only.
/
repomd-pattern-builder.py
executable file
·210 lines (166 loc) · 6.79 KB
/
repomd-pattern-builder.py
OlderNewer
1
#!/usr/bin/python3
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# This script is used to convert .yaml files to patterns and package groups.
# Copyright (C) 2011 Marko Saukko <FIRSTNAME.LASTNAME@gmail.com>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# This script is based on MeeGo package-group scripts
# https://meego.gitorious.org/meego-os-base/package-groups/
23
24
25
26
27
28
29
30
31
import yaml
import sys, os
import optparse
from lxml import etree
rpm_ns="http://linux.duke.edu/metadata/rpm"
pattern_ns="http://novell.com/package/metadata/suse/pattern"
NSMAP = {None : pattern_ns, "rpm": rpm_ns}
32
33
NSMAP_GROUP = {None : pattern_ns, "rpm": rpm_ns, "patterns": pattern_ns}
34
def process_yaml(stream, version, release, xmlroot, nsmap_name, newobsapi):
35
"Process all documents in the yaml stream and return a count of number handled"
36
37
all_docs = yaml.load_all(stream, Loader = yaml.SafeLoader)
38
39
for y in all_docs:
40
41
42
# <pattern>
proot = etree.SubElement(xmlroot, "pattern", nsmap=nsmap_name)
43
44
45
46
47
48
# <name>
etree.SubElement(proot, "name").text = y['Name']
# Old OBS isn't able to handle these options.
if newobsapi:
# <version>
49
if 'Version' in y or version:
50
51
52
53
54
55
entry = etree.SubElement(proot, "version")
ver = "0"
if version:
ver = version
else:
ver = y['Version']
56
57
# Set to 0 by default as that is what OBS expects.
58
epoch = "0"
59
if 'Epoch' in y:
60
61
62
epoch = y['Epoch']
# As above...
63
64
65
rel = "0"
if release:
rel = release
66
if 'Release' in y:
67
rel = y['Release']
68
69
70
71
entry.set('ver', "%s" % ver)
entry.set('epoch', "%s" % epoch)
entry.set('rel', "%s" % rel)
72
73
# <arch>
74
if 'Arch' in y:
75
76
77
78
79
80
81
82
83
84
85
86
87
etree.SubElement(proot, "arch").text = "%s" % y['Arch']
# <summary>
etree.SubElement(proot, "summary").text = y['Summary']
# <description>
etree.SubElement(proot, "description").text = y['Description']
# <uservisible>
etree.SubElement(proot, "uservisible")
# <category>
cat = etree.SubElement(proot, "category")
cat.text = "Base Group"
cat.set("lang", "en")
88
package_keys = ['Packages','Conflicts', 'Requires', 'Recommends', 'Suggests', 'Provides', 'Obsoletes']
89
for key in package_keys:
90
if key not in y:
91
92
93
94
95
96
continue
collect = y[key]
if key == "Packages":
# Support obsoleted keys, this should be removed in the future
key = "Requires"
97
print ("WARNING: Oboleted key 'Packages' in .yaml please change to 'Requires'.")
98
99
100
101
req = etree.SubElement(proot, "{%s}%s" % (rpm_ns,key.lower()))
for p in collect:
102
if type(p).__name__=='dict':
103
print ("ERROR: Found dict and expected string value. '%s'" % (p))
104
105
sys.exit(1)
entry = etree.SubElement(req, "{%s}entry" %rpm_ns)
106
107
108
name = p
ver = None
109
110
111
112
op_in = [">=", "<=", ">", "<", "="]
op_out = ["GE", "LE", "GT", "LT", "EQ"]
opc = 0
for op in op_in:
113
114
115
if op in p:
name, ver = p.split(op)
break
116
opc = opc + 1
117
118
119
entry.set("name", name.strip())
if ver:
120
121
entry.set("flags", "%s" % (op_out[opc]))
entry.set("ver", "%s" % (ver.strip()))
122
123
def create_patterns(patterns_dir, version, release, outputdir, newobsapi):
124
125
126
dirlist = os.listdir(patterns_dir)
dirlist.sort()
for f in dirlist:
127
128
129
if not f.endswith('.yaml'):
continue
130
stream = open("%s/%s" %(patterns_dir,f), 'r')
131
132
133
xmlroot = etree.Element("temporary_root", nsmap=NSMAP)
process_yaml(stream, version, release, xmlroot, NSMAP, newobsapi)
134
135
136
137
138
for pattern in xmlroot.findall("pattern"):
name = pattern.find("name")
if name == None:
139
print ("Pattern didn't have name skipping.")
140
141
continue
output_file = "%s/%s.xml" % (outputdir,name.text.lower())
142
print ("Working on %s" % (output_file))
143
144
etree.ElementTree(pattern).write(output_file, pretty_print=True)
145
146
def merge_patterns(patterns_dir, version, release, outputdir, newobsapi):
147
xmlroot = etree.Element("patterns")
148
output_file = "%s/patterns.xml" % (outputdir)
149
150
dirlist = os.listdir(patterns_dir)
dirlist.sort()
151
152
for f in dirlist:
153
154
if not f.endswith('.yaml'):
continue
155
print ("Merging %s to %s." % (f,output_file))
156
stream = file("%s/%s" %(patterns_dir,f), 'r')
157
158
159
160
process_yaml(stream, version, release, xmlroot, NSMAP_GROUP, newobsapi)
patterns = xmlroot.findall("pattern")
xmlroot.set('count', "%d" % (len(patterns)))
161
162
etree.ElementTree(xmlroot).write(output_file, pretty_print=True)
163
164
165
166
if __name__ == '__main__':
parser = optparse.OptionParser()
167
168
169
parser.add_option("", "--patternxml", action="store_true", dest="patternxml",
default=False,
help="Create separated pattern XML file for each pattern.")
170
171
172
parser.add_option("", "--patternsxml", action="store_true", dest="patternsxml",
default=False,
help="Create merged patterns.xml from all the available patterns.")
173
174
parser.add_option("", "--groupxml", action="store_true", dest="groupxml",
default=False,
175
help="Create group.xml.")
176
177
178
179
parser.add_option("-p", "--patterndir", type="string", dest="patterndir",
default=None,
help="Directory where the pattern .yaml files are located.")
parser.add_option("-o", "--outputdir", type="string", dest="outputdir",
180
default=".",
181
help="Output directory where the resulting .xml files are created.")
182
183
184
parser.add_option("", "--old-obs-xml-format", action="store_false", dest="newobsapi",
default=True,
help="The old OBS api isn't able to handle the newer xml format.")
185
186
parser.add_option("--version", type="string", dest="version", default=None, help="Version number")
parser.add_option("--release", type="string", dest="release", default=None, help="Release number")
187
188
(options, args) = parser.parse_args()
189
190
if (options.groupxml):
191
print ("ERROR: Groupxml isn't supported atm.")
192
193
194
exit(1)
if (not options.patternsxml and not options.patternxml):
195
196
# Default to patternxml.
options.patternxml = True
197
198
if (not options.patterndir or not os.path.exists(options.patterndir)):
199
print ("Error: Pattern dir '%s' doesn't exist." % (options.patterndir))
200
exit(1)
201
202
203
204
205
if options.outputdir and not os.path.exists(options.outputdir):
os.makedirs(options.outputdir)
if options.patternxml:
206
create_patterns(options.patterndir, options.version, options.release, options.outputdir, options.newobsapi)
207
208
if options.patternsxml:
209
merge_patterns(options.patterndir, options.version, options.release, options.outputdir, options.newobsapi)