]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Add Incremental=strict 3060/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sat, 21 Sep 2024 16:07:52 +0000 (18:07 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 22 Sep 2024 15:17:24 +0000 (17:17 +0200)
This ensures cached images already exist and fails the build if they
don't exist yet.

mkosi/__init__.py
mkosi/config.py
mkosi/resources/man/mkosi.md
tests/test_json.py

index 4739ce64908162f79d39ddd6608ee8f257d075ae..cf9886e8668e803872973c42c050d5d679618c01 100644 (file)
@@ -56,6 +56,7 @@ from mkosi.config import (
     Config,
     ConfigFeature,
     DocFormat,
+    Incremental,
     JsonEncoder,
     KeySourceType,
     ManifestFormat,
@@ -4243,6 +4244,22 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None:
 
     check_workspace_directory(last)
 
+    if last.incremental == Incremental.strict:
+        if args.force > 1:
+            die(
+                "Cannot remove incremental caches when building with Incremental=strict",
+                hint="Build once with -i yes to update the image cache",
+            )
+
+        for config in images:
+            if have_cache(config):
+                continue
+
+            die(
+                f"Strict incremental mode is enabled but the cache for image {config.name()} is out-of-date",
+                hint="Build once with -i yes to update the image cache",
+            )
+
     # If we're doing an incremental build and the cache is not out of date, don't clean up the
     # tools tree so that we can reuse the previous one.
     if tools and (
@@ -4250,6 +4267,12 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None:
         or ((args.verb == Verb.build or args.force > 0) and not have_cache(tools))
         or needs_build(args, tools, force=2)
     ):
+        if tools.incremental == Incremental.strict:
+            die(
+                "Tools tree does not exist or is out-of-date but the strict incremental mode is enabled",
+                hint="Build once with -i yes to update the tools tree",
+            )
+
         run_clean(args, tools, resources=resources)
 
     # First, process all directory removals because otherwise if different images share directories
index 18c9e76965e62bd6c523066c27d4bd6229eebc4f..277aae5f6804b47b089bee94215fe24abb110f75 100644 (file)
@@ -306,6 +306,15 @@ class Vmm(StrEnum):
     vmspawn = enum.auto()
 
 
+class Incremental(StrEnum):
+    yes = enum.auto()
+    no = enum.auto()
+    strict = enum.auto()
+
+    def __bool__(self) -> bool:
+        return self != Incremental.no
+
+
 class Architecture(StrEnum):
     alpha = enum.auto()
     arc = enum.auto()
@@ -1599,7 +1608,7 @@ class Config:
     tools_tree_sandbox_trees: list[ConfigTree]
     tools_tree_packages: list[str]
     tools_tree_certificates: bool
-    incremental: bool
+    incremental: Incremental
     cacheonly: Cacheonly
     sandbox_trees: list[ConfigTree]
     workspace_dir: Optional[Path]
@@ -2882,12 +2891,13 @@ SETTINGS = (
     ConfigSetting(
         dest="incremental",
         short="-i",
-        metavar="BOOL",
         nargs="?",
         section="Build",
-        parse=config_parse_boolean,
+        parse=config_make_enum_parser_with_boolean(Incremental, yes=Incremental.yes, no=Incremental.no),
+        default=Incremental.no,
         help="Make use of and generate intermediary cache images",
         scope=SettingScope.universal,
+        choices=Incremental.values(),
     ),
     ConfigSetting(
         dest="cacheonly",
@@ -4478,7 +4488,7 @@ def summary(config: Config) -> str:
                 Tools Tree Packages: {line_join_list(config.tools_tree_packages)}
             Tools Tree Certificates: {yes_no(config.tools_tree_certificates)}
 
-                        Incremental: {yes_no(config.incremental)}
+                        Incremental: {config.incremental}
              Use Only Package Cache: {config.cacheonly}
                       Sandbox Trees: {line_join_list(config.sandbox_trees)}
                 Workspace Directory: {config.workspace_dir_or_default()}
@@ -4659,6 +4669,7 @@ def json_type_transformer(refcls: Union[type[Args], type[Config]]) -> Callable[[
         OutputFormat: enum_transformer,
         QemuFirmware: enum_transformer,
         SecureBootSignTool: enum_transformer,
+        Incremental: enum_transformer,
         Optional[Distribution]: optional_enum_transformer,
         list[ManifestFormat]: enum_list_transformer,
         Verb: enum_transformer,
index 14b9e945f6be7ffc3e511de592225548167a984e..d164e3e828e85e68701f032be7efd19891b17725 100644 (file)
@@ -1309,16 +1309,20 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
     Otherwise, these directories are picked up from the host.
 
 `Incremental=`, `--incremental=`, `-i`
-:   Enable incremental build mode. In this mode, a copy of the OS image is
-    created immediately after all OS packages are installed and the
-    prepare scripts have executed but before the `mkosi.build` scripts are
-    invoked (or anything that happens after it). On subsequent invocations
-    of `mkosi` with the `-i` switch this cached image may be used to skip
-    the OS package installation, thus drastically speeding up repetitive
-    build times. Note that while there is some rudimentary cache
-    invalidation, it is definitely not perfect. In order to force
-    rebuilding of the cached image, combine `-i` with `-ff` to ensure the
-    cached image is first removed and then re-created.
+:   Takes either `strict` or a boolean value as its argument. Enables
+    incremental build mode. In this mode, a copy of the OS image is created
+    immediately after all OS packages are installed and the prepare scripts
+    have executed but before the `mkosi.build` scripts are invoked (or
+    anything that happens after it). On subsequent invocations of `mkosi`
+    with the `-i` switch this cached image may be used to skip the OS package
+    installation, thus drastically speeding up repetitive build times. Note
+    that while there is some rudimentary cache invalidation, it is definitely
+    not perfect. In order to force a rebuild of the cached image, combine
+    `-i` with `-ff` to ensure the cached image is first removed and then
+    re-created.
+
+    If set to `strict`, the build fails if previously built cached image does
+    not exist.
 
 `CacheOnly=`, `--cache-only=`
 :   Takes one of `auto`, `metadata`, `always` or `never`. Defaults to
index 4dad9a9f24c27ce8b1f458c3d0058fa5b15eb517..8b56e733482aa6b8e8caaab53984e8a476750516 100644 (file)
@@ -19,6 +19,7 @@ from mkosi.config import (
     ConfigFeature,
     ConfigTree,
     DocFormat,
+    Incremental,
     KeySource,
     KeySourceType,
     ManifestFormat,
@@ -147,7 +148,7 @@ def test_config() -> None:
             "Image": "default",
             "ImageId": "myimage",
             "ImageVersion": "5",
-            "Incremental": false,
+            "Incremental": "no",
             "InitrdPackages": [
                 "clevis"
             ],
@@ -404,7 +405,7 @@ def test_config() -> None:
         image="default",
         image_id="myimage",
         image_version="5",
-        incremental=False,
+        incremental=Incremental.no,
         initrd_packages=["clevis"],
         initrd_volatile_packages=["abc"],
         initrds=[Path("/efi/initrd1"), Path("/efi/initrd2")],