die(f"{script} is not executable")
-def check_outputs(config: Config) -> None:
- if config.output_format == OutputFormat.none:
- return
-
- f = config.output_dir_or_cwd() / config.output_with_compression
-
- if f.exists() and not f.is_symlink():
- logging.info(f"Output path {f} exists already. (Use --force to rebuild.)")
-
-
def check_tool(config: Config, *tools: PathString, reason: str, hint: Optional[str] = None) -> Path:
tool = config.find_binary(*tools)
if not tool:
)
-def needs_clean(args: Args, config: Config, force: int = 1) -> bool:
+def needs_build(args: Args, config: Config, force: int = 1) -> bool:
return (
- args.verb == Verb.clean or
args.force >= force or
not (config.output_dir_or_cwd() / config.output_with_compression).exists() or
# When the output is a directory, its name is the same as the symlink we create that points to the actual
page(text, args.pager)
return
+ last = images[-1]
+
+ if (minversion := last.minimum_version) and minversion > __version__:
+ die(f"mkosi {minversion} or newer is required by this configuration (found {__version__})")
+
if args.verb in (Verb.journalctl, Verb.coredumpctl, Verb.ssh):
# We don't use a tools tree for verbs that don't need an image build.
last = dataclasses.replace(images[-1], tools_tree=None)
Verb.coredumpctl: run_coredumpctl,
}[args.verb](args, last)
- assert args.verb.needs_build() or args.verb == Verb.clean
-
- for config in images:
- if args.verb == Verb.build and not args.force:
- check_outputs(config)
-
- last = images[-1]
-
if last.tools_tree and last.tools_tree == Path("default"):
tools = finalize_default_tools(args, last, resources=resources)
-
- # 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 (
- not tools.incremental or
- ((args.verb == Verb.build or args.force > 0) and not have_cache(tools)) or
- needs_clean(args, tools, force=2)
- ):
- run_clean(args, tools, resources=resources)
else:
tools = None
- # 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.
- for config in images:
- if needs_clean(args, config) or args.wipe_build_dir:
+ if args.verb == Verb.clean:
+ if tools:
+ run_clean(args, tools, resources=resources)
+
+ for config in images:
run_clean(args, config, resources=resources)
- if args.verb == Verb.clean:
return
- for config in images:
- if (minversion := config.minimum_version) and minversion > __version__:
- die(f"mkosi {minversion} or newer is required to build this configuration (found {__version__})")
+ assert args.verb.needs_build()
- if not config.repart_offline and os.getuid() != 0:
- die(f"Must be root to build {config.name()} image configured with RepartOffline=no")
+ if (
+ tools and
+ not (tools.output_dir_or_cwd() / tools.output).exists() and
+ args.verb != Verb.build and
+ not args.force
+ ):
+ die(f"Default tools tree requested for image '{last.name()}' but it has not been built yet",
+ hint="Make sure to build the image first with 'mkosi build' or use '--force'")
- check_workspace_directory(config)
+ if not last.repart_offline and os.getuid() != 0:
+ die(f"Must be root to build {last.name()} image configured with RepartOffline=no")
- if tools and not (tools.output_dir_or_cwd() / tools.output).exists():
- if args.verb == Verb.build or args.force > 0:
- with prepend_to_environ_path(tools):
- check_tools(tools, Verb.build)
- run_sync(args, tools, resources=resources)
- fork_and_wait(run_build, args, tools, resources=resources)
- else:
- die(f"Default tools tree requested for image '{last.name()}' but it has not been built yet",
- hint="Make sure to build the image first with 'mkosi build' or use '--force'")
+ output = last.output_dir_or_cwd() / last.output_with_compression
- build = False
+ if args.verb == Verb.build and not args.force and output.exists() and not output.is_symlink():
+ logging.info(f"Output path {output} exists already. (Use --force to rebuild.)")
+ return
- with tempfile.TemporaryDirectory(dir=last.workspace_dir_or_default(), prefix="mkosi-packages-") as package_dir:
- for i, config in enumerate(images):
- images[i] = config = dataclasses.replace(
- config,
- tools_tree=(
- tools.output_dir_or_cwd() / tools.output
- if tools and config.tools_tree == Path("default")
- else config.tools_tree
- )
- )
+ if args.verb != Verb.build and not args.force and not output.exists():
+ die(f"Image '{last.name()}' has not been built yet",
+ hint="Make sure to build the image first with 'mkosi build' or use '--force'")
- with prepend_to_environ_path(config):
- check_tools(config, args.verb)
- images[i] = config = run_configure_scripts(config)
+ check_workspace_directory(last)
- if args.verb != Verb.build and args.force == 0:
- continue
+ # 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
+ (
+ not tools.incremental or
+ ((args.verb == Verb.build or args.force > 0) and not have_cache(tools)) or
+ needs_build(args, tools, force=2)
+ )
+ ):
+ run_clean(args, tools, resources=resources)
- if (
- config.output_format != OutputFormat.none and
- (config.output_dir_or_cwd() / config.output_with_compression).exists()
- ):
- continue
+ # 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.
+ if needs_build(args, last) or args.wipe_build_dir:
+ for config in images:
+ run_clean(args, config, resources=resources)
+ if tools and not (tools.output_dir_or_cwd() / tools.output).exists():
+ with prepend_to_environ_path(tools):
+ check_tools(tools, Verb.build)
+ run_sync(args, tools, resources=resources)
+ fork_and_wait(run_build, args, tools, resources=resources)
+
+ for i, config in enumerate(images):
+ images[i] = config = dataclasses.replace(
+ config,
+ tools_tree=(
+ tools.output_dir_or_cwd() / tools.output
+ if tools and config.tools_tree == Path("default")
+ else config.tools_tree
+ )
+ )
+
+ with prepend_to_environ_path(config):
+ check_tools(config, args.verb)
+ images[i] = config = run_configure_scripts(config)
+
+ # The images array has been modified so we need to reevaluate last again.
+ last = images[-1]
+
+ if not (last.output_dir_or_cwd() / last.output).exists():
+ with (
+ tempfile.TemporaryDirectory(dir=last.workspace_dir_or_default(), prefix="mkosi-packages-") as package_dir,
+ ):
+ for config in images:
# If the output format is "none" and there are no build scripts, there's nothing to do so exit early.
if config.output_format == OutputFormat.none and not config.build_scripts:
- return
-
- if args.verb != Verb.build:
- check_tools(config, Verb.build)
+ continue
- check_inputs(config)
- run_sync(args, config, resources=resources)
- fork_and_wait(run_build, args, config, resources=resources, package_dir=Path(package_dir))
+ with prepend_to_environ_path(config):
+ if args.verb != Verb.build:
+ check_tools(config, Verb.build)
- build = True
+ check_inputs(config)
+ run_sync(args, last, resources=resources)
+ fork_and_wait(run_build, args, config, resources=resources, package_dir=Path(package_dir))
- if build and args.auto_bump:
- bump_image_version()
+ if args.auto_bump:
+ bump_image_version()
if args.verb == Verb.build:
return
- # The images array has been modified so we need to reevaluate last again.
- last = images[-1]
-
- if not (last.output_dir_or_cwd() / last.output_with_compression).exists():
- die(f"Image '{last.name()}' has not been built yet",
- hint="Make sure to build the image first with 'mkosi build' or use '--force'")
-
if (
last.output_format == OutputFormat.directory and
(last.output_dir_or_cwd() / last.output).stat().st_uid == 0 and