]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
installer: Make sure package manager state is preserved in the image 3682/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 10 Apr 2025 20:29:44 +0000 (22:29 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 16 Apr 2025 09:01:55 +0000 (11:01 +0200)
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
mkosi/installer/apt.py
mkosi/installer/dnf.py

index dcffe6346f6f61e6ccc9cacb09c044f9cd6e6301..a737c3ef836c7056df3817d15b42603fb700794e 100644 (file)
@@ -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")
index 12174b71d6f2adacbdd695933dc20d6492bf1564..1d78f22c532a8a477a1f87b856cf144419d88647 100644 (file)
@@ -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')}",
index ea42882837eb6fc3ee34b0cd93473e522ab1e129..82d23a362878da58acb2a3c632efc23edde26d83 100644 (file)
@@ -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"):