From: Daan De Meyer Date: Mon, 29 Aug 2022 12:36:26 +0000 (+0200) Subject: debian/ubuntu: Run apt/dpkg on the host instead of in the root X-Git-Tag: v14~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21c2b99281b87896950dd39e9fcb190d926ea3cf;p=thirdparty%2Fmkosi.git debian/ubuntu: Run apt/dpkg on the host instead of in the root 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. --- diff --git a/NEWS.md b/NEWS.md index 5bb7c85c1..d1ef30df9 100644 --- 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 diff --git a/mkosi/__init__.py b/mkosi/__init__.py index df18e6433..6af6059c7 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -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}") diff --git a/mkosi/manifest.py b/mkosi/manifest.py index 9d32afc64..b86a244eb 100644 --- a/mkosi/manifest.py +++ b/mkosi/manifest.py @@ -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