# -- peridot-releng-header-v0.1 -- # Copyright (c) Peridot-Releng Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # 3. Neither the name of the copyright holder nor the names of its contributors # may be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import argparse # noinspection PyPep8Naming import xml.etree.ElementTree as ET from xml.dom import minidom from group import Group, PackageReq, Environment, EnvGroup def write_variant(groups, environments, categories, out): root = ET.Element('comps') for group in groups: group_elem = ET.SubElement(root, 'group') ET.SubElement(group_elem, 'id').text = group.id for lang in group.name: name = ET.SubElement(group_elem, 'name') if lang != "": name.set('xml:lang', lang) name.text = group.name[lang] for lang in group.description: description = ET.SubElement(group_elem, 'description') if lang != "": description.set('xml:lang', lang) description.text = group.description[lang] ET.SubElement(group_elem, 'default').text = str(group.default).lower() ET.SubElement(group_elem, 'uservisible').text = str( group.user_visible).lower() package_list = ET.SubElement(group_elem, 'packagelist') for package in group.packages: package_elem = ET.SubElement(package_list, 'packagereq') package_elem.set('type', package.type) package_elem.text = package.name for environment in environments: env_elem = ET.SubElement(root, 'environment') ET.SubElement(env_elem, 'id').text = environment.id for lang in environment.name: name = ET.SubElement(env_elem, 'name') if lang != "": name.set('xml:lang', lang) name.text = environment.name[lang] for lang in environment.description: description = ET.SubElement(env_elem, 'description') if lang != "": description.set('xml:lang', lang) description.text = environment.description[lang] ET.SubElement(env_elem, 'display_order').text = str( environment.display_order) group_list = ET.SubElement(env_elem, 'grouplist') for group in environment.group_list: ET.SubElement(group_list, 'groupid').text = group.name option_list = ET.SubElement(env_elem, 'optionlist') for option in environment.option_list: ET.SubElement(option_list, 'optionid').text = option.name for category_name in categories.keys(): category = categories[category_name] new_group_list = [] for group in category.group_list: for ggroup in groups: if ggroup.id == group.name: new_group_list.append(group) break if len(new_group_list) == 0: continue category_elem = ET.SubElement(root, 'category') ET.SubElement(category_elem, 'id').text = category_name for lang in category.name: name = ET.SubElement(category_elem, 'name') if lang != "": name.set('xml:lang', lang) name.text = category.name[lang] for lang in category.description: description = ET.SubElement(category_elem, 'description') if lang != "": description.set('xml:lang', lang) description.text = category.description[lang] ET.SubElement(category_elem, 'display_order').text = str( category.display_order) group_list = ET.SubElement(category_elem, 'grouplist') for group in new_group_list: ET.SubElement(group_list, 'groupid').text = group.name ET.ElementTree(root).write(out, encoding='utf-8', xml_declaration=False) with open(out, 'r') as f: data = f.read() with open(out, 'w') as f: f.writelines(""" """ + minidom.parseString(data).toprettyxml(indent=" ").replace('\n', '')) def main(comps_path: str, variants_path: str, output_path: str): default_arches = ['x86_64', 'aarch64', 'ppc64le', 's390x'] variants = {} environments = {} categories = {} tree = ET.parse(comps_path) root = tree.getroot() for gchild in root: if gchild.tag == 'group': group_name = {} group_desc = {} group_id = '' is_default = False is_visible = False variant = '' package_list_xml = None if 'variant' in gchild.attrib: variant = gchild.attrib['variant'] if 'arch' in gchild.attrib: arches = gchild.attrib['arch'].split(',') else: arches = default_arches for gattr in gchild: if gattr.tag == 'id': group_id = gattr.text elif gattr.tag == 'name': if '{http://www.w3.org/XML/1998/namespace}lang' in gattr.attrib: group_name[gattr.attrib[ '{http://www.w3.org/XML/1998/namespace}lang']] = gattr.text else: group_name[""] = gattr.text elif gattr.tag == 'description': if '{http://www.w3.org/XML/1998/namespace}lang' in gattr.attrib: group_desc[gattr.attrib[ '{http://www.w3.org/XML/1998/namespace}lang']] = gattr.text else: group_desc[""] = gattr.text elif gattr.tag == 'default': is_default = gattr.text == 'true' elif gattr.tag == 'uservisible': is_visible = gattr.text == 'true' elif gattr.tag == 'packagelist': package_list_xml = gattr package_list = {} if variant != '': package_list[variant] = {} for reqxml in package_list_xml: req_variant = variant req_type = 'default' if 'variant' in reqxml.attrib: req_variant = reqxml.attrib['variant'] if 'type' in reqxml.attrib: req_type = reqxml.attrib['type'] if 'arch' in reqxml.attrib: req_arches = reqxml.attrib['arch'].split(',') else: req_arches = arches if req_variant not in package_list: package_list[req_variant] = {} for arch in req_arches: if arch not in package_list[req_variant]: package_list[req_variant][arch] = [] package_list[req_variant][arch].append( PackageReq(reqxml.text, req_type, req_arches)) for variant in package_list: if variant not in variants: variants[variant] = {} for arch in arches: if arch not in package_list[variant]: package_list[variant][arch] = [] if group_id not in variants[variant]: variants[variant][group_id] = {} variants[variant][group_id][arch] = Group(group_id, group_name, group_desc, is_default, is_visible, package_list[ variant][ arch]) elif gchild.tag == 'environment' or gchild.tag == 'category': env_name = {} env_desc = {} env_id = '' display_order = 0 group_list = [] option_list = [] for gattr in gchild: if gattr.tag == 'id': env_id = gattr.text elif gattr.tag == 'name': if '{http://www.w3.org/XML/1998/namespace}lang' in gattr.attrib: env_name[gattr.attrib[ '{http://www.w3.org/XML/1998/namespace}lang']] = gattr.text else: env_name[""] = gattr.text elif gattr.tag == 'description': if '{http://www.w3.org/XML/1998/namespace}lang' in gattr.attrib: env_desc[gattr.attrib[ '{http://www.w3.org/XML/1998/namespace}lang']] = gattr.text else: env_desc[""] = gattr.text elif gattr.tag == 'display_order': display_order = gattr.text elif gattr.tag == 'grouplist': for group in gattr: if 'arch' in group.attrib: arches = group.attrib['arch'].split(',') else: arches = default_arches group_list.append(EnvGroup(group.text, arches)) elif gattr.tag == 'optionlist': for group in gattr: if 'arch' in group.attrib: arches = group.attrib['arch'].split(',') else: arches = default_arches option_list.append(EnvGroup(group.text, arches)) new_env = Environment(env_id, env_name, env_desc, display_order, group_list, option_list) dictmap = categories if gchild.tag == 'environment': dictmap = environments if 'arch' in gchild.attrib: arches = gchild.attrib['arch'].split(',') else: arches = default_arches for arch in arches: if arch not in dictmap: dictmap[arch] = {} dictmap[arch][env_id] = new_env environment_id_index = {} for arch in environments.keys(): for env in environments[arch].values(): if env.id not in environment_id_index: environment_id_index[env.id] = {} environment_id_index[env.id][arch] = env variant_arch_index = {} environment_arch_index = {} pungi_variants_tree = ET.parse(variants_path).getroot() for pungi_variant in pungi_variants_tree: if pungi_variant.tag == 'variant': if pungi_variant.attrib['type'] != 'variant': continue arches = [] groups = {} n_environments = {} variant_id = pungi_variant.attrib['id'] for child in pungi_variant: if child.tag == 'arches': for arch in child: arches.append(arch.text) elif child.tag == 'groups': for group in child: groupbase = variants[""] if variant_id in variants: groupbase = variants[variant_id] if group.text not in groupbase: continue groupind = groupbase[group.text].copy() for arch_group in groupind.keys(): if arch_group not in groups: groups[arch_group] = [] if 'default' in group.attrib: groupind[arch_group].default = group.attrib['default'] == 'true' groups[arch_group].append(groupind[arch_group]) elif child.tag == 'environments': for environment in child: envind = environment_id_index[environment.text] for arch_environment in envind.keys(): if arch_environment not in n_environments: n_environments[arch_environment] = [] n_environments[arch_environment].append( envind[arch_environment]) for arch in arches: if arch in groups: if arch not in variant_arch_index: variant_arch_index[arch] = {} if variant_id not in variant_arch_index[arch]: variant_arch_index[arch][variant_id] = [] variant_arch_index[arch][variant_id].extend(groups[arch]) if arch in n_environments: if arch not in environment_arch_index: environment_arch_index[arch] = {} if variant_id not in environment_arch_index[arch]: environment_arch_index[arch][variant_id] = [] environment_arch_index[arch][variant_id].extend( n_environments[arch]) for arch in variant_arch_index.keys(): for variant in variant_arch_index[arch].keys(): write_variant(variant_arch_index[arch][variant] if variant in variant_arch_index[ arch] else [], environment_arch_index[arch][variant] if variant in environment_arch_index[ arch] else [], categories[arch].copy(), f'{output_path}/{variant}-{arch}.xml') if __name__ == '__main__': parser = argparse.ArgumentParser( description='Convert comps to Peridot compatible configuration.') parser.add_argument('--comps-path', type=str, required=True) parser.add_argument('--variants-path', type=str, required=True) parser.add_argument('--output-path', type=str, default=".") args = parser.parse_args() main(args.comps_path, args.variants_path, args.output_path)