From: Daan De Meyer Date: Mon, 22 Jan 2024 14:17:01 +0000 (+0100) Subject: Allow including builtin configs X-Git-Tag: v21~97^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=68cb849550077c98f2a39dd737aa9ce166cc39f5;p=thirdparty%2Fmkosi.git Allow including builtin configs Let's make it possible to include builtin configurations using e.g. Include=mkosi-initrd. This allows building the default initrd or default tools tree independently whereas currently these can only be built as part of another image. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index f4b5e57f2..62ff23075 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -1519,7 +1519,7 @@ def build_initrd(context: Context) -> Path: for include in context.config.initrd_include: cmdline += ["--include", os.fspath(include)] - args, [config] = parse_config(cmdline + ["build"]) + args, [config] = parse_config(cmdline + ["build"], resources=context.resources) make_executable( *config.prepare_scripts, @@ -3368,7 +3368,10 @@ def finalize_default_tools(args: Args, config: Config, *, resources: Path) -> Co *(["-f"] * args.force), ] - _, [tools] = parse_config(cmdline + ["--include", os.fspath(resources / "mkosi-tools"), "build"]) + _, [tools] = parse_config( + cmdline + ["--include", os.fspath(resources / "mkosi-tools"), "build"], + resources=resources, + ) make_executable( *tools.prepare_scripts, @@ -3540,11 +3543,10 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: if not args.verb.needs_build() and args.verb != Verb.clean: continue - if config.tools_tree and config.tools_tree.name == "default": - tools = finalize_default_tools(args, config, resources=resources) - fork_and_wait(lambda: run_clean(args, tools)) # type: ignore + if config.tools_tree and config.tools_tree == Path("default"): + fork_and_wait(run_clean, args, finalize_default_tools(args, config, resources=resources)) - fork_and_wait(lambda: run_clean(args, config)) + fork_and_wait(run_clean, args, config) if args.verb == Verb.clean: return @@ -3557,7 +3559,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: tools = ( finalize_default_tools(args, config, resources=resources) - if config.tools_tree and config.tools_tree.name == "default" + if config.tools_tree and config.tools_tree == Path("default") else None ) @@ -3567,12 +3569,12 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: ) if tools and not (tools.output_dir_or_cwd() / tools.output_with_compression).exists(): - fork_and_wait(lambda: run_build(args, tools, resources=resources)) # type:ignore + fork_and_wait(run_build, args, tools, resources=resources) if (config.output_dir_or_cwd() / config.output_with_compression).exists(): continue - fork_and_wait(lambda: run_build(args, config, resources=resources)) + fork_and_wait(run_build, args, config, resources=resources) build = True diff --git a/mkosi/__main__.py b/mkosi/__main__.py index 7f93e7fd6..3293814d3 100644 --- a/mkosi/__main__.py +++ b/mkosi/__main__.py @@ -28,7 +28,7 @@ def main() -> None: INVOKING_USER.init() with resource_path(mkosi.resources) as resources: - args, images = parse_config(sys.argv[1:]) + args, images = parse_config(sys.argv[1:], resources=resources) if args.debug: faulthandler.enable() diff --git a/mkosi/config.py b/mkosi/config.py index 43c2fe924..bb97c0053 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -34,7 +34,14 @@ from mkosi.pager import page from mkosi.run import find_binary, run from mkosi.sandbox import sandbox_cmd from mkosi.types import PathString, SupportsRead -from mkosi.util import INVOKING_USER, StrEnum, chdir, flatten, is_power_of_2 +from mkosi.util import ( + INVOKING_USER, + StrEnum, + chdir, + flatten, + is_power_of_2, + make_executable, +) from mkosi.versioncomp import GenericVersion __version__ = "20.2" @@ -44,6 +51,9 @@ ConfigMatchCallback = Callable[[str, Any], bool] ConfigDefaultCallback = Callable[[argparse.Namespace], Any] +BUILTIN_CONFIGS = ("mkosi-tools", "mkosi-initrd") + + class Verb(StrEnum): build = enum.auto() clean = enum.auto() @@ -408,7 +418,11 @@ def parse_path(value: str, expanduser: bool = True, expandvars: bool = True, secret: bool = False, - absolute: bool = False) -> Path: + absolute: bool = False, + constants: Sequence[str] = ()) -> Path: + if value in constants: + return Path(value) + if expandvars: value = os.path.expandvars(value) @@ -718,7 +732,8 @@ def make_path_parser(*, resolve: bool = True, expanduser: bool = True, expandvars: bool = True, - secret: bool = False) -> Callable[[str], Path]: + secret: bool = False, + constants: Sequence[str] = ()) -> Callable[[str], Path]: return functools.partial( parse_path, required=required, @@ -726,6 +741,7 @@ def make_path_parser(*, expanduser=expanduser, expandvars=expandvars, secret=secret, + constants=constants, ) @@ -734,7 +750,8 @@ def config_make_path_parser(*, resolve: bool = True, expanduser: bool = True, expandvars: bool = True, - secret: bool = False) -> ConfigParseCallback: + secret: bool = False, + constants: Sequence[str] = ()) -> ConfigParseCallback: def config_parse_path(value: Optional[str], old: Optional[Path]) -> Optional[Path]: if not value: return None @@ -746,6 +763,7 @@ def config_make_path_parser(*, expanduser=expanduser, expandvars=expandvars, secret=secret, + constants=constants, ) return config_parse_path @@ -1508,7 +1526,11 @@ SETTINGS = ( ConfigSetting( dest="include", section="Config", - parse=config_make_list_parser(delimiter=",", reset=False, parse=make_path_parser()), + parse=config_make_list_parser( + delimiter=",", + reset=False, + parse=make_path_parser(constants=BUILTIN_CONFIGS), + ), help="Include configuration from the specified file or directory", ), ConfigSetting( @@ -2325,7 +2347,7 @@ SETTINGS = ( dest="tools_tree", metavar="PATH", section="Host", - parse=config_make_path_parser(required=False), + parse=config_make_path_parser(required=False, constants=("default",)), paths=("mkosi.tools",), help="Look up programs to execute inside the given tree", ), @@ -2731,7 +2753,7 @@ def resolve_deps(images: Sequence[Config], include: Sequence[str]) -> list[Confi return sorted(images, key=lambda i: order.index(i.image)) -def parse_config(argv: Sequence[str] = ()) -> tuple[Args, tuple[Config, ...]]: +def parse_config(argv: Sequence[str] = (), *, resources: Path = Path("/")) -> tuple[Args, tuple[Config, ...]]: # Compare inodes instead of paths so we can't get tricked by bind mounts and such. parsed_includes: set[tuple[int, int]] = set() immutable_settings: set[str] = set() @@ -2781,13 +2803,29 @@ def parse_config(argv: Sequence[str] = ()) -> tuple[Args, tuple[Config, ...]]: finally: # Parse any includes that were added after yielding. for p in getattr(namespace, "include", [])[current_num_of_includes:]: - st = p.stat() + for c in BUILTIN_CONFIGS: + if p == Path(c): + path = resources / c + break + else: + path = p + + st = path.stat() if (st.st_dev, st.st_ino) in parsed_includes: continue - with chdir(p if p.is_dir() else Path.cwd()): - parse_config_one(p if p.is_file() else Path("."), namespace, defaults) + if any(p == Path(c) for c in BUILTIN_CONFIGS): + _, [config] = parse_config(["--include", os.fspath(path)]) + make_executable( + *config.prepare_scripts, + *config.postinst_scripts, + *config.finalize_scripts, + *config.build_scripts, + ) + + with chdir(path if path.is_dir() else Path.cwd()): + parse_config_one(path if path.is_file() else Path("."), namespace, defaults) parsed_includes.add((st.st_dev, st.st_ino)) class ConfigAction(argparse.Action): diff --git a/mkosi/resources/mkosi.md b/mkosi/resources/mkosi.md index 7be757f08..7c3a83e60 100644 --- a/mkosi/resources/mkosi.md +++ b/mkosi/resources/mkosi.md @@ -474,6 +474,10 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`, : Note that each path containing extra configuration is only parsed once, even if included more than once with `Include=`. +: The builtin configs for the mkosi default initrd and default tools + tree can be included by including the literal value `mkosi-initrd` and + `mkosi-tools` respectively. + `InitrdInclude=`, `--initrd-include=` : Same as `Include=`, but the extra configuration files or directories diff --git a/mkosi/run.py b/mkosi/run.py index c72ed4eca..8c5cb1526 100644 --- a/mkosi/run.py +++ b/mkosi/run.py @@ -195,12 +195,12 @@ def uncaught_exception_handler(exit: Callable[[int], NoReturn] = sys.exit) -> It exit(rc) -def fork_and_wait(target: Callable[[], None]) -> None: +def fork_and_wait(target: Callable[..., None], *args: Any, **kwargs: Any) -> None: pid = os.fork() if pid == 0: with uncaught_exception_handler(exit=os._exit): make_foreground_process() - target() + target(*args, **kwargs) try: _, status = os.waitpid(pid, 0)