]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Cache only files installed on top of base trees
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 27 Apr 2023 13:21:03 +0000 (15:21 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Sun, 30 Apr 2023 20:06:29 +0000 (21:06 +0100)
Currently, when base trees are used in incremental mode, we cache
the base trees as well. When running from a cache copy, any changes
to the base trees are not taken into account. Let's change this and
only cache the files we add/change/delete on top of the base layers.
This makes sure that we can still use our cache even if the base layer
changes, since we won't ignore all changes made to the base layer.

mkosi/__init__.py
mkosi/state.py

index 5095f6d41f95680d4719a0d9a947fa12c3ce772b..e8322779cf8f338cf4b1a1ca31c86e2ff8e1f5c5 100644 (file)
@@ -377,6 +377,16 @@ def configure_autologin(state: MkosiState) -> None:
 
 
 
+@contextlib.contextmanager
+def mount_cache_overlay(state: MkosiState) -> Iterator[None]:
+    if not state.config.incremental:
+        yield
+        return
+
+    with mount_overlay([state.root], state.cache_overlay, state.workdir, state.root, read_only=False):
+        yield
+
+
 def mount_build_overlay(state: MkosiState, read_only: bool = False) -> ContextManager[Path]:
     return mount_overlay([state.root], state.build_overlay, state.workdir, state.root, read_only)
 
@@ -888,7 +898,7 @@ def save_cache(state: MkosiState) -> None:
 
     with complete_step("Installing cache copies"):
         unlink_try_hard(final)
-        shutil.move(state.root, final)
+        shutil.move(state.cache_overlay, final)
         acl_toggle_remove(state.config, final, state.uid, allow=True)
 
         if state.config.build_script:
@@ -1500,15 +1510,16 @@ def invoke_repart(state: MkosiState, skip: Sequence[str] = [], split: bool = Fal
 
 def build_image(state: MkosiState, *, for_cache: bool, manifest: Optional[Manifest] = None) -> None:
     with mount_image(state):
+        install_base_trees(state)
         cached = reuse_cache_tree(state) if not for_cache else False
 
         if not cached:
-            install_base_trees(state)
-            install_skeleton_trees(state)
-            install_distribution(state)
-            run_prepare_script(state, build=False)
-            install_build_packages(state)
-            run_prepare_script(state, build=True)
+            with mount_cache_overlay(state):
+                install_skeleton_trees(state)
+                install_distribution(state)
+                run_prepare_script(state, build=False)
+                install_build_packages(state)
+                run_prepare_script(state, build=True)
 
         if for_cache:
             return
index b8f6bad617a0c0940124751f1c5fc0b47d735323..8d6df09d45f85cc892445b20e1c604b3d08196b6 100644 (file)
@@ -40,6 +40,7 @@ class MkosiState:
 
         self.root.mkdir(exist_ok=True, mode=0o755)
         self.build_overlay.mkdir(exist_ok=True, mode=0o755)
+        self.cache_overlay.mkdir(exist_ok=True, mode=0o755)
         self.workdir.mkdir(exist_ok=True)
         self.staging.mkdir(exist_ok=True)
 
@@ -47,6 +48,10 @@ class MkosiState:
     def root(self) -> Path:
         return self.workspace / "root"
 
+    @property
+    def cache_overlay(self) -> Path:
+        return self.workspace / "cache-overlay"
+
     @property
     def build_overlay(self) -> Path:
         return self.workspace / "build-overlay"