]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Introduce dnf.py for dnf related logic
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 26 Jul 2023 13:09:42 +0000 (15:09 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 31 Jul 2023 08:46:55 +0000 (10:46 +0200)
We put this in a new "installer" submodule as well.

mkosi/distributions/alma.py
mkosi/distributions/centos.py
mkosi/distributions/fedora.py
mkosi/distributions/mageia.py
mkosi/distributions/openmandriva.py
mkosi/distributions/opensuse.py
mkosi/distributions/rocky.py
mkosi/installer/__init__.py [new file with mode: 0644]
mkosi/installer/dnf.py [new file with mode: 0644]

index dd66169ac05b3487c02d7ede1c5d81f3d2d3edbf..309a2cefa84a4fb3d8add8d173fb1afce8ce7a9b 100644 (file)
@@ -2,7 +2,7 @@
 
 from mkosi.config import MkosiConfig
 from mkosi.distributions.centos import CentosInstaller
-from mkosi.distributions.fedora import Repo
+from mkosi.installer.dnf import Repo
 
 
 class AlmaInstaller(CentosInstaller):
index cddd943ab23992c7723f4b2cba3cba9bc20c27d8..70fc495e65ef81afd37082da68ef97208e875a61 100644 (file)
@@ -8,7 +8,7 @@ from pathlib import Path
 from mkosi.architecture import Architecture
 from mkosi.config import MkosiConfig
 from mkosi.distributions import DistributionInstaller
-from mkosi.distributions.fedora import Repo, invoke_dnf, setup_dnf
+from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
 from mkosi.log import complete_step, die
 from mkosi.state import MkosiState
 from mkosi.tree import rmtree
index 53dcdd397045a174ed36a790f59faf881c7b2013..50ad2579118ad1ff9dafecf45465d6a0dda63b15 100644 (file)
@@ -1,19 +1,12 @@
 # SPDX-License-Identifier: LGPL-2.1+
 
-import os
-import shutil
-from collections.abc import Iterable, Mapping, Sequence
-from pathlib import Path
-from textwrap import dedent
-from typing import Any, NamedTuple
+from collections.abc import Sequence
 
 from mkosi.architecture import Architecture
 from mkosi.distributions import DistributionInstaller
+from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
 from mkosi.log import die
-from mkosi.run import bwrap
 from mkosi.state import MkosiState
-from mkosi.tree import rmtree
-from mkosi.util import sort_packages
 
 
 class FedoraInstaller(DistributionInstaller):
@@ -101,132 +94,3 @@ def fedora_release_at_least(release: str, threshold: str) -> bool:
         return False
     # If neither is 'rawhide', both must be integers
     return int(release) >= int(threshold)
-
-
-class Repo(NamedTuple):
-    id: str
-    url: str
-    gpgurls: tuple[str, ...]
-    enabled: bool = True
-
-
-def setup_dnf(state: MkosiState, repos: Sequence[Repo]) -> None:
-    config = state.pkgmngr / "etc/dnf/dnf.conf"
-
-    if not config.exists():
-        config.parent.mkdir(exist_ok=True, parents=True)
-        config.write_text(
-            dedent(
-                """\
-                [main]
-                install_weak_deps=0
-                """
-            )
-        )
-
-    repofile = state.pkgmngr / "etc/yum.repos.d/mkosi.repo"
-    if not repofile.exists():
-        repofile.parent.mkdir(exist_ok=True, parents=True)
-        with repofile.open("w") as f:
-            for repo in repos:
-                f.write(
-                    dedent(
-                        f"""\
-                        [{repo.id}]
-                        name={repo.id}
-                        {repo.url}
-                        gpgcheck=1
-                        enabled={int(repo.enabled)}
-                        """
-                    )
-                )
-
-                for i, url in enumerate(repo.gpgurls):
-                    f.write("gpgkey=" if i == 0 else len("gpgkey=") * " ")
-                    f.write(f"{url}\n")
-
-
-def invoke_dnf(
-    state: MkosiState,
-    command: str,
-    packages: Iterable[str],
-    env: Mapping[str, Any] = {},
-    filelists: bool = True,
-    apivfs: bool = True
-) -> None:
-    state.pkgmngr.joinpath("etc/dnf/vars").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("etc/yum.repos.d").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("var/lib/dnf").mkdir(exist_ok=True, parents=True)
-
-    # dnf5 does not support building for foreign architectures yet (missing --forcearch)
-    dnf = shutil.which("dnf5") if state.config.architecture.is_native() else None
-    dnf = dnf or shutil.which("dnf") or "yum"
-
-    cmdline = [
-        dnf,
-        "--assumeyes",
-        f"--config={state.pkgmngr / 'etc/dnf/dnf.conf'}",
-        "--best",
-        f"--releasever={state.config.release}",
-        f"--installroot={state.root}",
-        "--setopt=keepcache=1",
-        f"--setopt=cachedir={state.cache_dir}",
-        f"--setopt=reposdir={state.pkgmngr / 'etc/yum.repos.d'}",
-        f"--setopt=varsdir={state.pkgmngr / 'etc/dnf/vars'}",
-        f"--setopt=persistdir={state.pkgmngr / 'var/lib/dnf'}",
-        "--setopt=check_config_file_age=0",
-        "--no-plugins" if dnf.endswith("dnf5") else "--noplugins",
-    ]
-
-    # Make sure we download filelists so all dependencies can be resolved.
-    # See https://bugzilla.redhat.com/show_bug.cgi?id=2180842
-    if dnf.endswith("dnf5") and filelists:
-        cmdline += ["--setopt=optional_metadata_types=filelists"]
-
-    if not state.config.repository_key_check:
-        cmdline += ["--nogpgcheck"]
-
-    if state.config.repositories:
-        opt = "--enable-repo" if dnf.endswith("dnf5") else "--enablerepo"
-        cmdline += [f"{opt}={repo}" for repo in state.config.repositories]
-
-    # TODO: this breaks with a local, offline repository created with 'createrepo'
-    if state.config.cache_only and not state.config.local_mirror:
-        cmdline += ["--cacheonly"]
-
-    if not state.config.architecture.is_native():
-        cmdline += [f"--forcearch={state.installer.architecture(state.config.architecture)}"]
-
-    if not state.config.with_docs:
-        cmdline += ["--no-docs" if dnf.endswith("dnf5") else "--nodocs"]
-
-    cmdline += [command, *sort_packages(packages)]
-
-    bwrap(cmdline,
-          apivfs=state.root if apivfs else None,
-          env=dict(KERNEL_INSTALL_BYPASS="1") | env | state.config.environment)
-
-    fixup_rpmdb_location(state.root)
-
-    # The log directory is always interpreted relative to the install root so there's nothing we can do but
-    # to remove the log files from the install root afterwards.
-    for p in (state.root / "var/log").iterdir():
-        if any(p.name.startswith(prefix) for prefix in ("dnf", "hawkey", "yum")):
-            p.unlink()
-
-
-def fixup_rpmdb_location(root: Path) -> None:
-    # On Debian, rpm/dnf ship with a patch to store the rpmdb under ~/ so it needs to be copied back in the
-    # right location, otherwise the rpmdb will be broken. See: https://bugs.debian.org/1004863. We also
-    # replace it with a symlink so that any further rpm operations immediately use the correct location.
-    rpmdb_home = root / "root/.rpmdb"
-    if not rpmdb_home.exists() or rpmdb_home.is_symlink():
-        return
-
-    # Take into account the new location in F36
-    rpmdb = root / "usr/lib/sysimage/rpm"
-    if not rpmdb.exists():
-        rpmdb = root / "var/lib/rpm"
-    rmtree(rpmdb)
-    shutil.move(rpmdb_home, rpmdb)
-    rpmdb_home.symlink_to(os.path.relpath(rpmdb, start=rpmdb_home.parent))
index edd4be9f0785ab2a9897357938080248c67aa358..0cd1af4b2224f97489af7322fc2a34b355052638 100644 (file)
@@ -4,7 +4,7 @@ from collections.abc import Sequence
 
 from mkosi.architecture import Architecture
 from mkosi.distributions import DistributionInstaller
-from mkosi.distributions.fedora import Repo, invoke_dnf, setup_dnf
+from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
 from mkosi.log import die
 from mkosi.state import MkosiState
 
index 2331bcaa8e89145964ad8afec6ac938bd78499b0..1702a8272d2949a2d29e0b415c2d997527c219cd 100644 (file)
@@ -4,7 +4,7 @@ from collections.abc import Sequence
 
 from mkosi.architecture import Architecture
 from mkosi.distributions import DistributionInstaller
-from mkosi.distributions.fedora import Repo, invoke_dnf, setup_dnf
+from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
 from mkosi.log import die
 from mkosi.state import MkosiState
 
index fe4de2493712d1c1dd01cf08cae9bf700e74879a..43d149e3a863b2844381ed0658f46594052b94c6 100644 (file)
@@ -8,7 +8,7 @@ from collections.abc import Sequence
 
 from mkosi.architecture import Architecture
 from mkosi.distributions import DistributionInstaller
-from mkosi.distributions.fedora import Repo, fixup_rpmdb_location, invoke_dnf, setup_dnf
+from mkosi.installer.dnf import Repo, fixup_rpmdb_location, invoke_dnf, setup_dnf
 from mkosi.log import die
 from mkosi.run import bwrap
 from mkosi.state import MkosiState
index 52cc5504782df40fd18802bd96816da1416bc9c3..1a3119f3417f2367f12279a0eb285bbc74b499ac 100644 (file)
@@ -2,7 +2,7 @@
 
 from mkosi.config import MkosiConfig
 from mkosi.distributions.centos import CentosInstaller
-from mkosi.distributions.fedora import Repo
+from mkosi.installer.dnf import Repo
 
 
 class RockyInstaller(CentosInstaller):
diff --git a/mkosi/installer/__init__.py b/mkosi/installer/__init__.py
new file mode 100644 (file)
index 0000000..5d742c4
--- /dev/null
@@ -0,0 +1 @@
+# SPDX-License-Identifier: LGPL-2.1+
diff --git a/mkosi/installer/dnf.py b/mkosi/installer/dnf.py
new file mode 100644 (file)
index 0000000..f0e3340
--- /dev/null
@@ -0,0 +1,141 @@
+# SPDX-License-Identifier: LGPL-2.1+
+import os
+import shutil
+import textwrap
+from collections.abc import Iterable, Mapping, Sequence
+from pathlib import Path
+from typing import Any, NamedTuple
+
+from mkosi.run import bwrap
+from mkosi.state import MkosiState
+from mkosi.tree import rmtree
+from mkosi.util import sort_packages
+
+
+class Repo(NamedTuple):
+    id: str
+    url: str
+    gpgurls: tuple[str, ...]
+    enabled: bool = True
+
+
+def setup_dnf(state: MkosiState, repos: Sequence[Repo]) -> None:
+    config = state.pkgmngr / "etc/dnf/dnf.conf"
+
+    if not config.exists():
+        config.parent.mkdir(exist_ok=True, parents=True)
+        config.write_text(
+            textwrap.dedent(
+                """\
+                [main]
+                install_weak_deps=0
+                """
+            )
+        )
+
+    repofile = state.pkgmngr / "etc/yum.repos.d/mkosi.repo"
+    if not repofile.exists():
+        repofile.parent.mkdir(exist_ok=True, parents=True)
+        with repofile.open("w") as f:
+            for repo in repos:
+                f.write(
+                    textwrap.dedent(
+                        f"""\
+                        [{repo.id}]
+                        name={repo.id}
+                        {repo.url}
+                        gpgcheck=1
+                        enabled={int(repo.enabled)}
+                        """
+                    )
+                )
+
+                for i, url in enumerate(repo.gpgurls):
+                    f.write("gpgkey=" if i == 0 else len("gpgkey=") * " ")
+                    f.write(f"{url}\n")
+
+
+def invoke_dnf(
+    state: MkosiState,
+    command: str,
+    packages: Iterable[str],
+    env: Mapping[str, Any] = {},
+    filelists: bool = True,
+    apivfs: bool = True
+) -> None:
+    state.pkgmngr.joinpath("etc/dnf/vars").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("etc/yum.repos.d").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("var/lib/dnf").mkdir(exist_ok=True, parents=True)
+
+    # dnf5 does not support building for foreign architectures yet (missing --forcearch)
+    dnf = shutil.which("dnf5") if state.config.architecture.is_native() else None
+    dnf = dnf or shutil.which("dnf") or "yum"
+
+    cmdline = [
+        dnf,
+        "--assumeyes",
+        f"--config={state.pkgmngr / 'etc/dnf/dnf.conf'}",
+        "--best",
+        f"--releasever={state.config.release}",
+        f"--installroot={state.root}",
+        "--setopt=keepcache=1",
+        f"--setopt=cachedir={state.cache_dir}",
+        f"--setopt=reposdir={state.pkgmngr / 'etc/yum.repos.d'}",
+        f"--setopt=varsdir={state.pkgmngr / 'etc/dnf/vars'}",
+        f"--setopt=persistdir={state.pkgmngr / 'var/lib/dnf'}",
+        "--setopt=check_config_file_age=0",
+        "--no-plugins" if dnf.endswith("dnf5") else "--noplugins",
+    ]
+
+    # Make sure we download filelists so all dependencies can be resolved.
+    # See https://bugzilla.redhat.com/show_bug.cgi?id=2180842
+    if dnf.endswith("dnf5") and filelists:
+        cmdline += ["--setopt=optional_metadata_types=filelists"]
+
+    if not state.config.repository_key_check:
+        cmdline += ["--nogpgcheck"]
+
+    if state.config.repositories:
+        opt = "--enable-repo" if dnf.endswith("dnf5") else "--enablerepo"
+        cmdline += [f"{opt}={repo}" for repo in state.config.repositories]
+
+    # TODO: this breaks with a local, offline repository created with 'createrepo'
+    if state.config.cache_only and not state.config.local_mirror:
+        cmdline += ["--cacheonly"]
+
+    if not state.config.architecture.is_native():
+        cmdline += [f"--forcearch={state.installer.architecture(state.config.architecture)}"]
+
+    if not state.config.with_docs:
+        cmdline += ["--no-docs" if dnf.endswith("dnf5") else "--nodocs"]
+
+    cmdline += [command, *sort_packages(packages)]
+
+    bwrap(cmdline,
+          apivfs=state.root if apivfs else None,
+          env=dict(KERNEL_INSTALL_BYPASS="1") | env | state.config.environment)
+
+    fixup_rpmdb_location(state.root)
+
+    # The log directory is always interpreted relative to the install root so there's nothing we can do but
+    # to remove the log files from the install root afterwards.
+    for p in (state.root / "var/log").iterdir():
+        if any(p.name.startswith(prefix) for prefix in ("dnf", "hawkey", "yum")):
+            p.unlink()
+
+
+def fixup_rpmdb_location(root: Path) -> None:
+    # On Debian, rpm/dnf ship with a patch to store the rpmdb under ~/ so it needs to be copied back in the
+    # right location, otherwise the rpmdb will be broken. See: https://bugs.debian.org/1004863. We also
+    # replace it with a symlink so that any further rpm operations immediately use the correct location.
+    rpmdb_home = root / "root/.rpmdb"
+    if not rpmdb_home.exists() or rpmdb_home.is_symlink():
+        return
+
+    # Take into account the new location in F36
+    rpmdb = root / "usr/lib/sysimage/rpm"
+    if not rpmdb.exists():
+        rpmdb = root / "var/lib/rpm"
+    rmtree(rpmdb)
+    shutil.move(rpmdb_home, rpmdb)
+    rpmdb_home.symlink_to(os.path.relpath(rpmdb, start=rpmdb_home.parent))