From: Daan De Meyer Date: Thu, 6 Mar 2025 22:47:33 +0000 (+0100) Subject: Rework --run-build-scripts X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F3585%2Fhead;p=thirdparty%2Fmkosi.git Rework --run-build-scripts Instead of (optionally) building the image when this option is enabled, let's insist that the image has already been built and cached. This allows us to reuse the history of the previous build if History= is enabled. At the same time, rename the option to --rerun-build-scripts to indicate more clearly that the image needs to have been built once already. This allows the option to be used in systemd's mkosi.clangd script to replace "-t none" and "--incremental=strict" there. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index df59b1a71..126d74718 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -3928,10 +3928,7 @@ def build_image(context: Context) -> None: check_root_populated(context) run_build_scripts(context) - if context.config.output_format == OutputFormat.none or ( - context.args.run_build_scripts - and (context.config.output_dir_or_cwd() / context.config.output).exists() - ): + if context.config.output_format == OutputFormat.none or context.args.rerun_build_scripts: return if wantrepo: @@ -5106,6 +5103,13 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: Verb.sandbox: run_sandbox, }[args.verb](args, last) + if last.output_format == OutputFormat.none: + if args.verb != Verb.build: + die(f"Cannot run '{args.verb}' verb on image with output format 'none'") + + if args.rerun_build_scripts: + die("Cannot use --run-build-scripts on image with output format 'none'") + output = last.output_dir_or_cwd() / last.output_with_compression if ( @@ -5114,11 +5118,17 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: and output.exists() and not output.is_symlink() and last.output_format != OutputFormat.none - and not args.run_build_scripts + and not args.rerun_build_scripts ): logging.info(f"Output path {output} exists already. (Use --force to rebuild.)") return + if args.rerun_build_scripts and not output.exists(): + die( + f"Image '{last.image}' must be built once before --rerun-build-scripts can be used", + hint="Build the image once with 'mkosi build'", + ) + if args.verb != Verb.build and not args.force and not output.exists(): die( f"Image '{last.image}' has not been built yet", @@ -5130,6 +5140,9 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: check_workspace_directory(last) + if args.rerun_build_scripts and not last.is_incremental(): + die("Incremental= must be enabled to be able to use --rerun-build-scripts") + if last.is_incremental(): for a, b in itertools.combinations(images, 2): if a.expand_key_specifiers(a.cache_key) == b.expand_key_specifiers(b.cache_key): @@ -5138,21 +5151,24 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: hint="Add the &I specifier to the cache key to avoid this issue", ) - if last.is_incremental() and last.incremental == Incremental.strict: + if last.is_incremental() and (last.incremental == Incremental.strict or args.rerun_build_scripts): 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 and cache for image {config.image} is out-of-date", - hint="Build once with '-i yes' to update the image cache", - ) + if any((c := config).is_incremental() and not have_cache(config) for config in images): + if args.rerun_build_scripts: + die( + f"Cannot use --rerun-build-scripts as the cache for image {c.image} is out-of-date", + hint="Rebuild the image to update the image cache", + ) + else: + die( + f"Strict incremental mode is enabled and cache for image {c.image} is out-of-date", + hint="Build once with '-i yes' to update the image cache", + ) # First, process all directory removals because otherwise if different images share directories # a later image build could end up deleting the output generated by an earlier image build. @@ -5179,7 +5195,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: images = resolve_deps(images[:-1], last.dependencies) + [last] if ( - args.run_build_scripts + args.rerun_build_scripts or last.output_format == OutputFormat.none or not (last.output_dir_or_cwd() / last.output).exists() ): @@ -5231,7 +5247,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: # nothing to do so exit early. if ( config.output_format == OutputFormat.none - or (args.run_build_scripts and (config.output_dir_or_cwd() / config.output).exists()) + or (args.rerun_build_scripts and (config.output_dir_or_cwd() / config.output).exists()) ) and not config.build_scripts: continue @@ -5265,7 +5281,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: if args.auto_bump: bump_image_version() - if last.history: + if last.history and not args.rerun_build_scripts: Path(".mkosi-private/history").mkdir(parents=True, exist_ok=True) Path(".mkosi-private/history/latest.json").write_text( json.dumps( diff --git a/mkosi/config.py b/mkosi/config.py index 152b75715..002b3e41b 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -1697,7 +1697,7 @@ class Args: doc_format: DocFormat json: bool wipe_build_dir: bool - run_build_scripts: bool + rerun_build_scripts: bool @classmethod def default(cls) -> "Args": @@ -4207,7 +4207,7 @@ def create_argument_parser(chdir: bool = True) -> argparse.ArgumentParser: ) parser.add_argument( "-R", - "--run-build-scripts", + "--rerun-build-scripts", help="Run build scripts even if the image is not rebuilt", action="store_true", default=False, @@ -4710,7 +4710,7 @@ def have_history(args: Args) -> bool: return ( args.directory is not None and args.verb.needs_build() - and args.verb != Verb.build + and (args.verb != Verb.build or args.rerun_build_scripts) and not args.force and Path(".mkosi-private/history/latest.json").exists() ) @@ -4746,6 +4746,9 @@ def parse_config( if args.cmdline and not args.verb.supports_cmdline(): die(f"Arguments after verb are not supported for {args.verb}.") + if args.rerun_build_scripts and args.force: + die("--force cannot be used together with --rerun-build-scripts") + # If --debug was passed, apply it as soon as possible. if ARG_DEBUG.get(): logging.getLogger().setLevel(logging.DEBUG) diff --git a/mkosi/resources/man/mkosi.1.md b/mkosi/resources/man/mkosi.1.md index 0dee6cd9e..17230a24c 100644 --- a/mkosi/resources/man/mkosi.1.md +++ b/mkosi/resources/man/mkosi.1.md @@ -293,6 +293,12 @@ Those settings cannot be configured in the configuration files. `--wipe-build-dir`, `-w` : Wipe the build directory if one is configured before building the image. +`--rerun-build-scripts`, `-R` +: Rerun build scripts. Requires the `Incremental=` option to be + enabled and the image to have been built once already. If `History=` + is enabled, the config from the previous build will be reused and no + new history will be written. + ## Supported output formats The following output formats are supported: diff --git a/tests/test_json.py b/tests/test_json.py index 348ac8a0a..1207459a3 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -67,7 +67,7 @@ def test_args(path: Optional[Path]) -> None: "GenkeyValidDays": "100", "Json": false, "Pager": true, - "RunBuildScripts": true, + "RerunBuildScripts": true, "Verb": "build", "WipeBuildDir": true }} @@ -88,7 +88,7 @@ def test_args(path: Optional[Path]) -> None: genkey_valid_days="100", json=False, pager=True, - run_build_scripts=True, + rerun_build_scripts=True, verb=Verb.build, wipe_build_dir=True, )