From: Daan De Meyer Date: Fri, 5 May 2023 06:56:48 +0000 (+0200) Subject: Introduce ConfigFeature X-Git-Tag: v15~179^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98830dfa660b4c3529ce271b6b6c8200e26c9634;p=thirdparty%2Fmkosi.git Introduce ConfigFeature --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index f6b0845e5..c9e0c2f67 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -22,7 +22,13 @@ from pathlib import Path from textwrap import dedent from typing import Callable, ContextManager, Optional, TextIO, TypeVar, Union, cast -from mkosi.config import GenericVersion, MkosiArgs, MkosiConfig, MkosiConfigParser +from mkosi.config import ( + ConfigFeature, + GenericVersion, + MkosiArgs, + MkosiConfig, + MkosiConfigParser, +) from mkosi.install import add_dropin_config_from_resource, copy_path, flock from mkosi.log import Style, color_error, complete_step, die, log_step from mkosi.manifest import Manifest @@ -205,13 +211,12 @@ def clean_package_manager_metadata(state: MkosiState) -> None: package manager is present in the image. """ - assert state.config.clean_package_metadata in (False, True, None) - if state.config.clean_package_metadata is False: + if state.config.clean_package_metadata == ConfigFeature.disabled: return # we try then all: metadata will only be touched if any of them are in the # final image - always = state.config.clean_package_metadata is True + always = state.config.clean_package_metadata == ConfigFeature.enabled clean_dnf_metadata(state.root, always=always) clean_yum_metadata(state.root, always=always) clean_rpm_metadata(state.root, always=always) @@ -422,15 +427,15 @@ def run_finalize_script(state: MkosiState) -> None: def install_boot_loader(state: MkosiState) -> None: - if state.config.bootable is False: + if state.config.bootable == ConfigFeature.disabled: return - if state.config.output_format == OutputFormat.cpio and state.config.bootable is None: + if state.config.output_format == OutputFormat.cpio and state.config.bootable == ConfigFeature.auto: return directory = state.root / "usr/lib/systemd/boot/efi" if not directory.exists() or not any(directory.iterdir()): - if state.config.bootable is True: + if state.config.bootable == ConfigFeature.enabled: die("A bootable image was requested but systemd-boot was not found at " f"{directory.relative_to(state.root)}") return @@ -651,14 +656,14 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None: # benefit that they can be signed like normal EFI binaries, and can encode everything necessary to boot a # specific root device, including the root hash. - if state.config.bootable is False: + if state.config.bootable == ConfigFeature.disabled: return for kver, kimg in gen_kernel_images(state): copy_path(state.root / kimg, state.staging / state.config.output_split_kernel) break - if state.config.output_format == OutputFormat.cpio and state.config.bootable is None: + if state.config.output_format == OutputFormat.cpio and state.config.bootable == ConfigFeature.auto: return initrds = [] @@ -777,7 +782,7 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None: if not state.staging.joinpath(state.config.output_split_uki).exists(): copy_path(boot_binary, state.staging / state.config.output_split_uki) - if state.config.bootable is True and not state.staging.joinpath(state.config.output_split_uki).exists(): + if state.config.bootable == ConfigFeature.enabled and not state.staging.joinpath(state.config.output_split_uki).exists(): die("A bootable image was requested but no kernel was found") @@ -1049,12 +1054,12 @@ def check_outputs(config: MkosiConfig) -> None: die(f"Output path {f} exists already. (Consider invocation with --force.)") -def yes_no(b: Optional[bool]) -> str: +def yes_no(b: bool) -> str: return "yes" if b else "no" -def yes_no_auto(b: Optional[bool]) -> str: - return "auto" if b is None else yes_no(b) +def yes_no_auto(f: ConfigFeature) -> str: + return "auto" if f is ConfigFeature.auto else yes_no(f == ConfigFeature.enabled) def none_to_na(s: Optional[T]) -> Union[T, str]: @@ -1277,7 +1282,7 @@ def configure_initrd(state: MkosiState) -> None: def run_depmod(state: MkosiState) -> None: - if state.config.bootable is False: + if state.config.bootable == ConfigFeature.disabled: return for kver, _ in gen_kernel_images(state): @@ -1368,8 +1373,8 @@ def invoke_repart(state: MkosiState, skip: Sequence[str] = [], split: bool = Fal bootdir = state.root.joinpath("boot/EFI/BOOT") # If Bootable=auto and we have at least one UKI and a bootloader, let's generate an ESP partition. - add = (state.config.bootable is True or - (state.config.bootable is None and + add = (state.config.bootable == ConfigFeature.enabled or + (state.config.bootable == ConfigFeature.auto and bootdir.exists() and any(bootdir.iterdir()) and any(gen_kernel_images(state)))) diff --git a/mkosi/config.py b/mkosi/config.py index 4839c64b0..49e231873 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -48,6 +48,15 @@ ConfigMatchCallback = Callable[[str, str, argparse.Namespace], bool] ConfigDefaultCallback = Callable[[argparse.Namespace], Any] +class ConfigFeature(enum.Enum): + auto = "auto" + enabled = "enabled" + disabled = "disabled" + + def __str__(self) -> str: + return str(self.value).lower() + + def parse_boolean(s: str) -> bool: "Parse 1/true/yes/y/t/on as true and 0/false/no/n/f/off/None as false" s_l = s.lower() @@ -132,14 +141,14 @@ def config_match_boolean(dest: str, value: str, namespace: argparse.Namespace) - return cast(bool, getattr(namespace, dest) == parse_boolean(value)) -def config_parse_feature(dest: str, value: Optional[str], namespace: argparse.Namespace) -> Optional[bool]: +def config_parse_feature(dest: str, value: Optional[str], namespace: argparse.Namespace) -> ConfigFeature: if dest in namespace: return getattr(namespace, dest) # type: ignore - if value and value == "auto": - return None + if not value or value == ConfigFeature.auto.value: + return ConfigFeature.auto - return parse_boolean(value) if value else None + return ConfigFeature.enabled if parse_boolean(value) else ConfigFeature.disabled def config_parse_compression(dest: str, value: Optional[str], namespace: argparse.Namespace) -> Optional[Compression]: @@ -565,7 +574,7 @@ class MkosiConfig: base_trees: list[Path] extra_trees: list[tuple[Path, Optional[Path]]] skeleton_trees: list[tuple[Path, Optional[Path]]] - clean_package_metadata: Optional[bool] + clean_package_metadata: ConfigFeature remove_files: list[str] environment: dict[str, str] build_sources: Path @@ -595,7 +604,7 @@ class MkosiConfig: make_initrd: bool kernel_command_line_extra: list[str] acl: bool - bootable: Optional[bool] + bootable: ConfigFeature # QEMU-specific options qemu_gui: bool @@ -2004,11 +2013,13 @@ def load_config(args: argparse.Namespace) -> MkosiConfig: ): die("--repo-dir is only supported on DNF/Debian based distributions and Arch") - if args.qemu_kvm is True and not qemu_check_kvm_support(): + if args.qemu_kvm == ConfigFeature.enabled and not qemu_check_kvm_support(): die("Sorry, the host machine does not support KVM acceleration.") - if args.qemu_kvm is None: + if args.qemu_kvm == ConfigFeature.auto: args.qemu_kvm = qemu_check_kvm_support() + else: + args.qemu_kvm = args.qemu_kvm == ConfigFeature.enabled if args.repositories and not (is_dnf_distribution(args.distribution) or is_apt_distribution(args.distribution)): die("Sorry, the --repositories option is only supported on DNF/Debian based distributions")