]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Introduce apt.py for apt related logic
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 26 Jul 2023 13:17:21 +0000 (15:17 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 31 Jul 2023 08:49:50 +0000 (10:49 +0200)
mkosi/distributions/debian.py
mkosi/installer/apt.py [new file with mode: 0644]

index c13535d43862a9e95dbbce6863629cf4a5a00152..045c644232782bacb2c3eb51315fb5897a77e625 100644 (file)
@@ -1,16 +1,15 @@
 # SPDX-License-Identifier: LGPL-2.1+
 
-import os
 import shutil
 import tempfile
 from collections.abc import Sequence
 from pathlib import Path
-from textwrap import dedent
 
 from mkosi.architecture import Architecture
 from mkosi.distributions import DistributionInstaller
+from mkosi.installer.apt import invoke_apt, setup_apt
 from mkosi.log import die
-from mkosi.run import bwrap, run
+from mkosi.run import run
 from mkosi.state import MkosiState
 
 
@@ -152,105 +151,6 @@ class DebianInstaller(DistributionInstaller):
         return a
 
 
-def setup_apt(state: MkosiState, repos: Sequence[str]) -> None:
-    state.pkgmngr.joinpath("etc/apt").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("etc/apt/apt.conf.d").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("etc/apt/preferences.d").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("etc/apt/sources.list.d").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("var/log/apt").mkdir(exist_ok=True, parents=True)
-    state.pkgmngr.joinpath("var/lib/apt").mkdir(exist_ok=True, parents=True)
-
-    # TODO: Drop once apt 2.5.4 is widely available.
-    state.root.joinpath("var").mkdir(mode=0o755, exist_ok=True)
-    state.root.joinpath("var/lib").mkdir(mode=0o755, exist_ok=True)
-    state.root.joinpath("var/lib/dpkg").mkdir(mode=0o755, exist_ok=True)
-    state.root.joinpath("var/lib/dpkg/status").touch()
-
-    # We have a special apt.conf outside of pkgmngr dir that only configures "Dir" that we pass to
-    # APT_CONFIG to tell apt it should read config files in pkgmngr instead of in its usual locations. This
-    # is required because apt parses CLI configuration options after parsing its configuration files and as
-    # such we can't use CLI options to tell apt where to look for configuration files.
-    config = state.workspace / "apt.conf"
-    if not config.exists():
-        config.write_text(
-            dedent(
-                f"""\
-                Dir "{state.pkgmngr}";
-                """
-            )
-        )
-
-    config = state.pkgmngr / "etc/apt/apt.conf"
-    if not config.exists():
-        # Anything that users can override with dropins is written into the config file.
-        config.write_text(
-            dedent(
-                """\
-                APT::Install-Recommends "false";
-                """
-            )
-        )
-
-    sources = state.pkgmngr / "etc/apt/sources.list"
-    if not sources.exists():
-        with sources.open("w") as f:
-            for repo in repos:
-                f.write(f"{repo}\n")
-
-
-def invoke_apt(
-    state: MkosiState,
-    operation: str,
-    packages: Sequence[str] = (),
-    apivfs: bool = True,
-) -> None:
-    env = dict(
-        APT_CONFIG=os.fspath(state.workspace / "apt.conf"),
-        DEBIAN_FRONTEND="noninteractive",
-        DEBCONF_INTERACTIVE_SEEN="true",
-        KERNEL_INSTALL_BYPASS="1",
-        INITRD="No",
-    )
-
-    debarch = state.installer.architecture(state.config.architecture)
-
-    trustedkeys = state.pkgmngr / "etc/apt/trusted.gpg"
-    trustedkeys = trustedkeys if trustedkeys.exists() else f"/usr/share/keyrings/{state.config.distribution}-archive-keyring.gpg"
-    trustedkeys_dir = state.pkgmngr / "etc/apt/trusted.gpg.d"
-    trustedkeys_dir = trustedkeys_dir if trustedkeys_dir.exists() else "/usr/share/keyrings"
-
-    options = [
-        "-o", f"APT::Architecture={debarch}",
-        "-o", f"APT::Architectures={debarch}",
-        "-o", "APT::Immediate-Configure=off",
-        "-o", "APT::Get::Assume-Yes=true",
-        "-o", "APT::Get::AutomaticRemove=true",
-        "-o", "APT::Get::Allow-Change-Held-Packages=true",
-        "-o", "APT::Get::Allow-Remove-Essential=true",
-        "-o", "APT::Sandbox::User=root",
-        "-o", f"Dir::Cache={state.cache_dir}",
-        "-o", f"Dir::State={state.pkgmngr / 'var/lib/apt'}",
-        "-o", f"Dir::State::status={state.root / 'var/lib/dpkg/status'}",
-        "-o", f"Dir::Etc::trusted={trustedkeys}",
-        "-o", f"Dir::Etc::trustedparts={trustedkeys_dir}",
-        "-o", f"Dir::Log={state.pkgmngr / 'var/log/apt'}",
-        "-o", f"Dir::Bin::dpkg={shutil.which('dpkg')}",
-        "-o", "Debug::NoLocking=true",
-        "-o", f"DPkg::Options::=--root={state.root}",
-        "-o", f"DPkg::Options::=--log={state.pkgmngr / 'var/log/apt/dpkg.log'}",
-        "-o", "DPkg::Options::=--force-unsafe-io",
-        "-o", "DPkg::Options::=--force-architecture",
-        "-o", "DPkg::Options::=--force-depends",
-        "-o", "Dpkg::Use-Pty=false",
-        "-o", "DPkg::Install::Recursive::Minimum=1000",
-        "-o", "pkgCacheGen::ForceEssential=,",
-    ]
-
-    bwrap(["apt-get", *options, operation, *packages],
-          apivfs=state.root if apivfs else None,
-          env=env | state.config.environment)
-
-
 def install_apt_sources(state: MkosiState, repos: Sequence[str]) -> None:
     if not state.root.joinpath("usr/bin/apt").exists():
         return
diff --git a/mkosi/installer/apt.py b/mkosi/installer/apt.py
new file mode 100644 (file)
index 0000000..4499130
--- /dev/null
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: LGPL-2.1+
+import os
+import shutil
+import textwrap
+from collections.abc import Sequence
+
+from mkosi.run import bwrap
+from mkosi.state import MkosiState
+
+
+def setup_apt(state: MkosiState, repos: Sequence[str]) -> None:
+    state.pkgmngr.joinpath("etc/apt").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("etc/apt/apt.conf.d").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("etc/apt/preferences.d").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("etc/apt/sources.list.d").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("var/log/apt").mkdir(exist_ok=True, parents=True)
+    state.pkgmngr.joinpath("var/lib/apt").mkdir(exist_ok=True, parents=True)
+
+    # TODO: Drop once apt 2.5.4 is widely available.
+    state.root.joinpath("var").mkdir(mode=0o755, exist_ok=True)
+    state.root.joinpath("var/lib").mkdir(mode=0o755, exist_ok=True)
+    state.root.joinpath("var/lib/dpkg").mkdir(mode=0o755, exist_ok=True)
+    state.root.joinpath("var/lib/dpkg/status").touch()
+
+    # We have a special apt.conf outside of pkgmngr dir that only configures "Dir" that we pass to
+    # APT_CONFIG to tell apt it should read config files in pkgmngr instead of in its usual locations. This
+    # is required because apt parses CLI configuration options after parsing its configuration files and as
+    # such we can't use CLI options to tell apt where to look for configuration files.
+    config = state.workspace / "apt.conf"
+    if not config.exists():
+        config.write_text(
+            textwrap.dedent(
+                f"""\
+                Dir "{state.pkgmngr}";
+                """
+            )
+        )
+
+    config = state.pkgmngr / "etc/apt/apt.conf"
+    if not config.exists():
+        # Anything that users can override with dropins is written into the config file.
+        config.write_text(
+            textwrap.dedent(
+                """\
+                APT::Install-Recommends "false";
+                """
+            )
+        )
+
+    sources = state.pkgmngr / "etc/apt/sources.list"
+    if not sources.exists():
+        with sources.open("w") as f:
+            for repo in repos:
+                f.write(f"{repo}\n")
+
+
+def invoke_apt(
+    state: MkosiState,
+    operation: str,
+    packages: Sequence[str] = (),
+    apivfs: bool = True,
+) -> None:
+    env = dict(
+        APT_CONFIG=os.fspath(state.workspace / "apt.conf"),
+        DEBIAN_FRONTEND="noninteractive",
+        DEBCONF_INTERACTIVE_SEEN="true",
+        KERNEL_INSTALL_BYPASS="1",
+        INITRD="No",
+    )
+
+    debarch = state.installer.architecture(state.config.architecture)
+
+    trustedkeys = state.pkgmngr / "etc/apt/trusted.gpg"
+    trustedkeys = trustedkeys if trustedkeys.exists() else f"/usr/share/keyrings/{state.config.distribution}-archive-keyring.gpg"
+    trustedkeys_dir = state.pkgmngr / "etc/apt/trusted.gpg.d"
+    trustedkeys_dir = trustedkeys_dir if trustedkeys_dir.exists() else "/usr/share/keyrings"
+
+    options = [
+        "-o", f"APT::Architecture={debarch}",
+        "-o", f"APT::Architectures={debarch}",
+        "-o", "APT::Immediate-Configure=off",
+        "-o", "APT::Get::Assume-Yes=true",
+        "-o", "APT::Get::AutomaticRemove=true",
+        "-o", "APT::Get::Allow-Change-Held-Packages=true",
+        "-o", "APT::Get::Allow-Remove-Essential=true",
+        "-o", "APT::Sandbox::User=root",
+        "-o", f"Dir::Cache={state.cache_dir}",
+        "-o", f"Dir::State={state.pkgmngr / 'var/lib/apt'}",
+        "-o", f"Dir::State::status={state.root / 'var/lib/dpkg/status'}",
+        "-o", f"Dir::Etc::trusted={trustedkeys}",
+        "-o", f"Dir::Etc::trustedparts={trustedkeys_dir}",
+        "-o", f"Dir::Log={state.pkgmngr / 'var/log/apt'}",
+        "-o", f"Dir::Bin::dpkg={shutil.which('dpkg')}",
+        "-o", "Debug::NoLocking=true",
+        "-o", f"DPkg::Options::=--root={state.root}",
+        "-o", f"DPkg::Options::=--log={state.pkgmngr / 'var/log/apt/dpkg.log'}",
+        "-o", "DPkg::Options::=--force-unsafe-io",
+        "-o", "DPkg::Options::=--force-architecture",
+        "-o", "DPkg::Options::=--force-depends",
+        "-o", "Dpkg::Use-Pty=false",
+        "-o", "DPkg::Install::Recursive::Minimum=1000",
+        "-o", "pkgCacheGen::ForceEssential=,",
+    ]
+
+    bwrap(["apt-get", *options, operation, *packages],
+          apivfs=state.root if apivfs else None,
+          env=env | state.config.environment)