]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
debian/ubuntu: Run apt/dpkg on the host instead of in the root
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 29 Aug 2022 12:36:26 +0000 (14:36 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 29 Aug 2022 15:58:05 +0000 (17:58 +0200)
Similar to the other package managers, run apt/dpkg on the host
instead of in the container. This should allow us to implement
--repository-directory for apt as well and brings it more in line
with the other package managers.

NEWS.md
mkosi/__init__.py
mkosi/manifest.py

diff --git a/NEWS.md b/NEWS.md
index 5bb7c85c19ee2d4013c02995ee4b0780298d8cf7..d1ef30df9e02984b86e37a628facb552ef32c4f9 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -24,6 +24,9 @@ you need to update the keyring by running `pacman-key --populate archlinux`.
 - Support for BIOS/grub was dropped. To allow users to configure grub themselves, the
 new `--bios-size` option can be used to add a BIOS boot partition of the specified size
 on which grub can be installed.
+- mkosi now runs apt and dpkg on the host. As such, we now require apt and dpkg to be
+installed on the host along with debootstrap in order to be able to build debian/ubuntu
+images.
 
 ## v13
 
index df18e6433391d6ff9894da437d61c5cd0acda5f9..6af6059c70dac7b6708d667366dc47e81caae012 100644 (file)
@@ -2427,20 +2427,28 @@ def debootstrap_knows_arg(arg: str) -> bool:
 
 def invoke_apt(
     args: MkosiArgs,
-    do_run_build_script: bool,
     root: Path,
-    command: str,
+    subcommand: str,
+    operation: str,
     extra: Iterable[str],
-) -> None:
+    **kwargs: Any,
+) -> CompletedProcess:
 
-    cmdline = ["/usr/bin/apt-get", "--assume-yes", command, *extra]
+    cmdline = [
+        f"/usr/bin/apt-{subcommand}",
+        "-o", f"Dir={root}",
+        "-o", f"DPkg::Chroot-Directory={root}",
+        operation,
+        *extra,
+    ]
     env = dict(
         DEBIAN_FRONTEND="noninteractive",
         DEBCONF_NONINTERACTIVE_SEEN="true",
         INITRD="No",
     )
 
-    run_workspace_command(args, root, cmdline, network=True, env=env)
+    with mount_api_vfs(args, root):
+        return run(cmdline, env=env, text=True, **kwargs)
 
 
 def install_debian_or_ubuntu(args: MkosiArgs, root: Path, *, do_run_build_script: bool) -> None:
@@ -2560,14 +2568,13 @@ def install_debian_or_ubuntu(args: MkosiArgs, root: Path, *, do_run_build_script
 
     install_skeleton_trees(args, root, False, late=True)
 
-    invoke_apt(args, do_run_build_script, root, "update", [])
+    invoke_apt(args, root, "get", "update", ["--assume-yes"])
 
     if args.bootable and not do_run_build_script and args.get_partition(PartitionIdentifier.esp):
-        if run_workspace_command(args, root, ["apt-cache", "search", "--names-only", "^systemd-boot$"],
-                                 capture_stdout=True).stdout.strip() != "":
+        if invoke_apt(args, root, "cache", "search", ["--names-only", "^systemd-boot$"], stdout=PIPE).stdout.strip() != "":
             add_packages(args, extra_packages, "systemd-boot")
 
-    invoke_apt(args, do_run_build_script, root, "install", ["--no-install-recommends", *extra_packages])
+    invoke_apt(args, root, "get", "install", ["--assume-yes", "--no-install-recommends", *extra_packages])
 
     policyrcd.unlink()
     dpkg_io_conf.unlink()
@@ -2906,12 +2913,12 @@ def remove_packages(args: MkosiArgs, root: Path) -> None:
     if not args.remove_packages:
         return
 
-    remove: Callable[[List[str]], None]
+    remove: Callable[[List[str]], Any]
 
     if (args.distribution.package_type == PackageType.rpm):
         remove = lambda p: invoke_dnf(args, root, 'remove', p)
     elif args.distribution.package_type == PackageType.deb:
-        remove = lambda p: invoke_apt(args, False, root, "purge", ["--auto-remove", *p])
+        remove = lambda p: invoke_apt(args, root, "get", "purge", ["--assume-yes", "--auto-remove", *p])
     else:
         die(f"Removing packages is not supported for {args.distribution}")
 
index 9d32afc64afa6a715e05d4f97e01d156c3c0d313..b86a244ebf3e5bc25ea786da1ff187efbec1f3ab 100644 (file)
@@ -8,14 +8,7 @@ from subprocess import DEVNULL, PIPE
 from textwrap import dedent
 from typing import IO, Any, Dict, List, Optional, Tuple, cast
 
-from .backend import (
-    Distribution,
-    ManifestFormat,
-    MkosiArgs,
-    PackageType,
-    run,
-    run_workspace_command,
-)
+from .backend import Distribution, ManifestFormat, MkosiArgs, PackageType, run
 
 
 @dataclasses.dataclass
@@ -154,10 +147,11 @@ class Manifest:
             source.add(package)
 
     def record_deb_packages(self, root: Path) -> None:
-        c = run_workspace_command(self.args, root,
-            ["dpkg-query", "--admindir=/var/lib/dpkg", "--show", "--showformat",
+        c = run(
+            ["dpkg-query", f"--admindir={root}/var/lib/dpkg", "--show", "--showformat",
              r'${Package}\t${source:Package}\t${Version}\t${Architecture}\t${Installed-Size}\t${db-fsys:Last-Modified}\n'],
-            capture_stdout=True
+            stdout=PIPE,
+            text=True,
         )
 
         packages = sorted(c.stdout.splitlines())
@@ -189,7 +183,15 @@ class Manifest:
                 # Yes, --quiet is specified twice, to avoid output about download stats.
                 # Note that the argument of the 'changelog' verb is the binary package name,
                 # not the source package name.
-                cmd = ["apt-get", "--quiet", "--quiet", "changelog", name]
+                cmd = [
+                    "apt-get",
+                    "--quiet",
+                    "--quiet",
+                    "-o", f"Dir={root}",
+                    "-o", f"DPkg::Chroot-Directory={root}",
+                    "changelog",
+                    name,
+                ]
 
                 # If we are building with docs then it's easy, as the changelogs are saved
                 # in the image, just fetch them. Otherwise they will be downloaded from the network.
@@ -209,7 +211,7 @@ class Manifest:
                 # We have to run from the root, because if we use the RootDir option to make
                 # apt from the host look at the repositories in the image, it will also pick
                 # the 'methods' executables from there, but the ABI might not be compatible.
-                result = run_workspace_command(self.args, root, cmd, network=not self.args.with_docs, capture_stdout=True)
+                result = run(cmd, text=True, stdout=PIPE)
                 source_package = SourcePackageManifest(source, result.stdout.strip())
                 self.source_packages[source] = source_package