From 96e512fe6e93846868ff2f8b946b8bbcc4b5fb54 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 10 Apr 2025 22:29:44 +0200 Subject: [PATCH] installer: Make sure package manager state is preserved in the image Package manager state should be preserved in the image as various local features of the package manager may depend on this data to be available. For pacman and zypper we already store local state inside the image. For apt, we achieve this by storing all state in the image by default except lists which is the repository metadata which we still don't include in the image. For dnf/dnf5, we make sure the persistdir points to inside the image. Note that this state is still subject to removal by CleanPackageMetadata= if the package manager is not installed or the option is explicitly enabled. Fixes #3659 --- mkosi/__init__.py | 4 ++++ mkosi/installer/apt.py | 7 ++++++- mkosi/installer/dnf.py | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mkosi/__init__.py b/mkosi/__init__.py index dcffe6346..a737c3ef8 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -3899,6 +3899,10 @@ def copy_repository_metadata(config: Config, dst: Path) -> None: logging.debug(f"{cachedir} does not exist, not copying repository metadata from it") statedir = config.package_cache_dir_or_default() / "lib" / subdir + + with umask(~0o755): + (dst / "lib" / subdir).mkdir(parents=True, exist_ok=True) + for src in config.distribution.package_manager(config).state_subdirs(statedir): if not src.exists(): logging.debug(f"{src} does not exist, not copying repository metadata from it") diff --git a/mkosi/installer/apt.py b/mkosi/installer/apt.py index 12174b71d..1d78f22c5 100644 --- a/mkosi/installer/apt.py +++ b/mkosi/installer/apt.py @@ -101,6 +101,10 @@ class Apt(PackageManager): "mkosi-reinstall": ["apt-get", "install", "--reinstall"], } # fmt: skip + @classmethod + def options(cls, *, root: PathString, apivfs: bool = True) -> list[PathString]: + return super().options(root=root, apivfs=apivfs) + ["--dir", "/var/lib/apt/lists/partial"] + @classmethod def setup(cls, context: Context, repositories: Sequence[AptRepository]) -> None: (context.sandbox_tree / "etc/apt").mkdir(exist_ok=True, parents=True) @@ -171,7 +175,8 @@ class Apt(PackageManager): "-o", "Acquire::AllowReleaseInfoChange=true", "-o", "Acquire::Check-Valid-Until=false", "-o", "Dir::Cache=/var/cache/apt", - "-o", "Dir::State=/var/lib/apt", + "-o", "Dir::State=/buildroot/var/lib/apt", + "-o", "Dir::State::lists=/var/lib/apt/lists/", "-o", "Dir::Log=/var/log/apt", "-o", "Dir::State::Status=/buildroot/var/lib/dpkg/status", "-o", f"Dir::Bin::DPkg={context.config.find_binary('dpkg')}", diff --git a/mkosi/installer/dnf.py b/mkosi/installer/dnf.py index ea4288283..82d23a362 100644 --- a/mkosi/installer/dnf.py +++ b/mkosi/installer/dnf.py @@ -148,10 +148,10 @@ class Dnf(PackageManager): "--setopt=keepcache=1", "--setopt=logdir=/var/log", f"--setopt=cachedir=/var/cache/{cls.subdir(context.config)}", - f"--setopt=persistdir=/var/lib/{cls.subdir(context.config)}", f"--setopt=install_weak_deps={int(context.config.with_recommends)}", "--setopt=check_config_file_age=0", "--disable-plugin=*" if dnf == "dnf5" else "--disableplugin=*", + "--setopt=persistdir=/buildroot/var/lib/dnf", ] # fmt: skip for plugin in ("builddep", "versionlock", "reflink"): -- 2.47.2