From: Daan De Meyer Date: Thu, 10 Apr 2025 20:29:44 +0000 (+0200) Subject: installer: Make sure package manager state is preserved in the image X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F3682%2Fhead;p=thirdparty%2Fmkosi.git 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 --- 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"):