]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Add some very basic cache invalidation
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 9 May 2023 09:09:26 +0000 (11:09 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 9 May 2023 09:31:06 +0000 (11:31 +0200)
Let's compare the packages, build packages, repositories and the
contents of the prepare script. This doesn't cover everything but
should be sufficient to catch most changes without having to run
with "-ff".

mkosi/__init__.py
mkosi/config.py

index 16c2b9abceebe57269f2d9e8d90a2316c4bbef70..643da964b9a49a94b058e2fa2bff96601ad79d0c 100644 (file)
@@ -1032,7 +1032,7 @@ def unlink_output(args: MkosiArgs, config: MkosiConfig) -> None:
     if remove_build_cache:
         for p in cache_tree_paths(config):
             if p.exists():
-                with complete_step(f"Removing cache directory {p}…"):
+                with complete_step(f"Removing cache entry {p}…"):
                     unlink_try_hard(p)
 
         if config.build_dir and config.build_dir.exists() and any(config.build_dir.iterdir()):
@@ -1049,9 +1049,13 @@ def unlink_output(args: MkosiArgs, config: MkosiConfig) -> None:
                 empty_directory(config.cache_dir)
 
 
-def cache_tree_paths(config: MkosiConfig) -> tuple[Path, Path]:
+def cache_tree_paths(config: MkosiConfig) -> tuple[Path, Path, Path]:
     assert config.cache_dir
-    return config.cache_dir / f"{config.output}.cache", config.cache_dir / f"{config.output}.build.cache"
+    return (
+        config.cache_dir / f"{config.output}.cache",
+        config.cache_dir / f"{config.output}.build.cache",
+        config.cache_dir / f"{config.output}.manifest",
+    )
 
 
 def check_tree_input(path: Optional[Path]) -> None:
@@ -1456,7 +1460,7 @@ def save_cache(state: MkosiState) -> None:
     if not state.config.incremental:
         return
 
-    final, build = cache_tree_paths(state.config)
+    final, build, manifest = cache_tree_paths(state.config)
 
     with complete_step("Installing cache copies"):
         unlink_try_hard(final)
@@ -1472,15 +1476,22 @@ def save_cache(state: MkosiState) -> None:
             unlink_try_hard(build)
             shutil.move(state.workspace / "build-overlay", build)
 
+        manifest.write_text(json.dumps(state.config.cache_manifest()))
+
 
 def reuse_cache(state: MkosiState) -> bool:
     if not state.config.incremental:
         return False
 
-    final, build = cache_tree_paths(state.config)
+    final, build, manifest = cache_tree_paths(state.config)
     if not final.exists() or (state.config.build_script and not build.exists()):
         return False
 
+    if manifest.exists():
+        prev = json.loads(manifest.read_text())
+        if prev != state.config.cache_manifest():
+            return False
+
     with complete_step("Copying cached trees"):
         btrfs_maybe_snapshot_subvolume(state.config, final, state.root)
         if state.config.build_script:
index 55220ec877b9374b3c23ed4955c416d36a58a645..ebd4871ce567273370c08a08ea60c3906143cdec 100644 (file)
@@ -1,4 +1,5 @@
 import argparse
+import base64
 import configparser
 import copy
 import dataclasses
@@ -716,6 +717,18 @@ class MkosiConfig:
     def output_changelog(self) -> str:
         return f"{self.output_with_version}.changelog"
 
+    def cache_manifest(self) -> dict[str, Any]:
+        manifest: dict[str, Any] = {
+            "packages": self.packages,
+            "build_packages": self.build_packages,
+            "repositories": self.repositories,
+        }
+
+        if self.prepare_script:
+            manifest["prepare_script"] = base64.b64encode(self.prepare_script.read_bytes()).decode()
+
+        return manifest
+
 
 class MkosiConfigParser:
     SETTINGS = (