peridot-releng/pungicatalog/pungicatalog.py
2022-08-04 05:01:32 +02:00

187 lines
7.3 KiB
Python

# -- 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
import os
import kobo.conf
from catalog import (
PeridotCatalogSync,
PeridotCatalogSyncPackage,
PeridotCatalogSyncPackageType,
PeridotCatalogSyncRepository,
)
from scm import SCM
def main(pungi_conf_path: str, output_path: str):
pungi_base = os.path.dirname(pungi_conf_path)
conf = kobo.conf.PyConfigParser()
conf.load_from_file(pungi_conf_path)
gather_prepopulate_scm_dict = conf.get("gather_prepopulate")
gpscm = SCM(pungi_base, gather_prepopulate_scm_dict)
gpjson = gpscm.json()
# Create a catalog
catalog = PeridotCatalogSync()
# Set multilib filters
catalog.additional_multilib.extend(list(conf.get("multilib_whitelist").values())[0])
catalog.exclude_multilib_filter.extend(
list(conf.get("multilib_blacklist").values())[0]
)
# Set additional packages/filters
catalog.exclude_filter.extend(conf.get("filter_packages"))
catalog.include_filter.extend(conf.get("additional_packages"))
# Create indexes
package_index = {}
# Read prepopulate json and create package objects
all_arches = []
for repo in gpjson.keys():
for arch in gpjson[repo].keys():
if arch not in all_arches:
all_arches.append(arch)
for package in gpjson[repo][arch].keys():
if package not in package_index:
package_index[package] = {}
if repo not in package_index[package]:
package_index[package][repo] = {
"include_filter": [],
"multilib": [],
}
na_list = gpjson[repo][arch][package]
for na in na_list:
splitted = na.split(".")
arch_package = splitted[len(splitted) - 1]
if arch != arch_package and arch_package != "noarch":
if arch not in package_index[package][repo]["multilib"]:
package_index[package][repo]["multilib"].append(arch)
if na not in package_index[package][repo]["include_filter"]:
package_index[package][repo]["include_filter"].append(na)
arch_specific_excludes = {}
na_index = {}
for pkg in package_index.keys():
for repo in package_index[pkg].keys():
na_list = list(
filter(
lambda x: x.endswith(".noarch"),
package_index[pkg][repo]["include_filter"],
)
)
if not na_list:
continue
exclude_arches = {}
for na in na_list:
for arch in all_arches:
if (
arch not in gpjson[repo]
or pkg not in gpjson[repo][arch]
or na not in gpjson[repo][arch][pkg]
):
if na not in exclude_arches:
exclude_arches[na] = []
exclude_arches[na].append(arch)
na_index[na] = na
if not exclude_arches:
continue
if pkg not in arch_specific_excludes:
arch_specific_excludes[pkg] = {}
if repo not in arch_specific_excludes[pkg]:
arch_specific_excludes[pkg][repo] = []
arch_specific_excludes[pkg][repo].append(exclude_arches)
# Index arch specific excludes by repo and arch
repo_arch_index = {}
for pkg in arch_specific_excludes.keys():
for repo in arch_specific_excludes[pkg].keys():
if repo not in repo_arch_index:
repo_arch_index[repo] = {}
for arches2 in arch_specific_excludes[pkg][repo]:
for na in arches2.keys():
for arch in arches2[na]:
if arch not in repo_arch_index[repo]:
repo_arch_index[repo][arch] = []
if na not in repo_arch_index[repo][arch]:
repo_arch_index[repo][arch].append(na)
# Add noarch packages not in a specific arch to exclude filter
for repo in repo_arch_index.keys():
repo_key = f"^{repo}$"
filter_tuple = {}
for arch in repo_arch_index[repo].keys():
if arch not in filter_tuple:
filter_tuple[arch] = []
for na in repo_arch_index[repo][arch]:
na = na.removesuffix(".noarch")
if na not in filter_tuple[arch]:
filter_tuple[arch].append(na)
catalog.exclude_filter.append((repo_key, filter_tuple))
for package in package_index.keys():
catalog.add_package(
PeridotCatalogSyncPackage(
package,
PeridotCatalogSyncPackageType.PACKAGE_TYPE_NORMAL_FORK
if not package.startswith("rocky-")
else PeridotCatalogSyncPackageType.PACKAGE_TYPE_NORMAL_SRC,
[],
[
PeridotCatalogSyncRepository(
x,
package_index[package][x]["include_filter"],
package_index[package][x]["multilib"],
)
for x in package_index[package].keys()
],
)
)
f = open(output_path, "w")
f.write(catalog.to_prototxt())
f.close()
pass
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Convert Pungi configuration to Peridot compatible " "catalogs."
)
parser.add_argument("--pungi-conf-path", type=str, required=True)
parser.add_argument("--output-path", type=str, default="catalog.cfg")
args = parser.parse_args()
main(args.pungi_conf_path, args.output_path)