From: Daan De Meyer Date: Wed, 3 May 2023 12:15:22 +0000 (+0200) Subject: opensuse: Use dnf instead of zypper X-Git-Tag: v15~183^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1536%2Fhead;p=thirdparty%2Fmkosi.git opensuse: Use dnf instead of zypper Let's reduce the number of package managers we use by using dnf to build opensuse images. The only caveat is that extra GPG keys are listed in repomd.xml for the opensuse repos, so we have to download that file and parse it to figure out the extra keys that we have to write to the repo configs. --- diff --git a/mkosi/distributions/opensuse.py b/mkosi/distributions/opensuse.py index 1e973ddc7..700280a2f 100644 --- a/mkosi/distributions/opensuse.py +++ b/mkosi/distributions/opensuse.py @@ -1,13 +1,13 @@ # SPDX-License-Identifier: LGPL-2.1+ +import urllib.request +import xml.etree.ElementTree as ElementTree from collections.abc import Sequence -from textwrap import dedent from mkosi.distributions import DistributionInstaller -from mkosi.distributions.fedora import fixup_rpmdb_location -from mkosi.run import bwrap +from mkosi.distributions.fedora import Repo, invoke_dnf, setup_dnf +from mkosi.log import die from mkosi.state import MkosiState -from mkosi.types import PathString class OpensuseInstaller(DistributionInstaller): @@ -34,74 +34,38 @@ class OpensuseInstaller(DistributionInstaller): release_url = f"{state.config.mirror}/tumbleweed/repo/oss/" updates_url = f"{state.config.mirror}/update/tumbleweed/" elif release in ("current", "stable"): - release_url = f"{state.config.mirror}/distribution/openSUSE-stable/repo/oss/" + release_url = f"{state.config.mirror}/distribution/openSUSE-{release}/repo/oss/" updates_url = f"{state.config.mirror}/update/openSUSE-{release}/" else: release_url = f"{state.config.mirror}/distribution/leap/{release}/repo/oss/" updates_url = f"{state.config.mirror}/update/leap/{release}/oss/" - repos = [("repo-oss", release_url)] + repos = [Repo("repo-oss", f"baseurl={release_url}", fetch_gpgurls(release_url))] if updates_url is not None: - repos += [("repo-update", updates_url)] + repos += [Repo("repo-update", f"baseurl={updates_url}", fetch_gpgurls(updates_url))] - setup_zypper(state, repos) - invoke_zypper(state, "install", ["-y", "--download-in-advance", "--no-recommends"], packages, apivfs=apivfs) + setup_dnf(state, repos) + invoke_dnf(state, "install", packages, apivfs=apivfs) @classmethod def remove_packages(cls, state: MkosiState, packages: Sequence[str]) -> None: - invoke_zypper(state, "remove", ["-y", "--clean-deps"], packages) - - -def setup_zypper(state: MkosiState, repos: Sequence[tuple[str, str]] = ()) -> None: - with state.workspace.joinpath("zypp.conf").open("w") as f: - f.write( - dedent( - f"""\ - [main] - rpm.install.excludedocs = {"no" if state.config.with_docs else "yes"} - """ - ) - ) - - state.workspace.joinpath("zypp.repos.d").mkdir(exist_ok=True) - - with state.workspace.joinpath("zypp.repos.d/mkosi.repo").open("w") as f: - for id, url in repos: - f.write( - dedent( - f"""\ - [{id}] - name={id} - baseurl={url} - autorefresh=0 - enabled=1 - keeppackages=1 - """ - ) - ) - - -def invoke_zypper( - state: MkosiState, - verb: str, - options: Sequence[str], - packages: Sequence[str], - apivfs: bool = True -) -> None: - cmdline: list[PathString] = [ - "zypper", - "--root", state.root, - f"--cache-dir={state.cache}", - f"--reposd-dir={state.workspace / 'zypp.repos.d'}", - "--gpg-auto-import-keys" if state.config.repository_key_check else "--no-gpg-checks", - "--non-interactive", - verb, - *options, - *packages, - ] - - env = dict(ZYPP_CONF=str(state.workspace / "zypp.conf"), KERNEL_INSTALL_BYPASS="1") | state.environment - - bwrap(cmdline, apivfs=state.root if apivfs else None, env=env) - - fixup_rpmdb_location(state.root) + invoke_dnf(state, "remove", packages) + + +def fetch_gpgurls(repourl: str) -> list[str]: + gpgurls = [f"{repourl}/repodata/repomd.xml.key"] + + with urllib.request.urlopen(f"{repourl}/repodata/repomd.xml") as f: + xml = f.read().decode() + root = ElementTree.fromstring(xml) + + tags = root.find("{http://linux.duke.edu/metadata/repo}tags") + if not tags: + die("repomd.xml missing element") + + for child in tags.iter("{http://linux.duke.edu/metadata/repo}content"): + if child.text and child.text.startswith("gpg-pubkey"): + gpgkey = child.text.partition("?")[0] + gpgurls += [f"{repourl}{gpgkey}"] + + return gpgurls