From: Joerg Behrmann Date: Thu, 8 Jun 2023 13:01:23 +0000 (+0200) Subject: config: add PackageManagerTrees= option X-Git-Tag: v15~120^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8bb0b5b8cd84b1137dc6d071372a14f2079c5007;p=thirdparty%2Fmkosi.git config: add PackageManagerTrees= option --- diff --git a/mkosi.md b/mkosi.md index b1bdb5724..9deca9035 100644 --- a/mkosi.md +++ b/mkosi.md @@ -690,6 +690,19 @@ they should be specified with a boolean argument: either "1", "yes", or "true" t file may be provided too. `mkosi.skeleton.tar` will be automatically used if found in the local directory. +`PackageManagerTrees=`, `--package-manager-tree=` + +: This option mirrors the above `SkeletonTrees=` option and defaults to the + same value if not configured otherwise, but installs the files to a + subdirectory of the workspace directory instead of the OS tree. This + subdirectory of the workspace is used to configure the package manager. + +: `SkeletonTrees=` and `PackageManagerTrees=` fulfill similar roles. Use + `SkeletonTrees=` if you want the files to be present in the final image. Use + `PackageManagerTrees=` if you don't want the files to be present in the final + image, e.g. when building an initrd or if you want to refer to paths outside + of the image in your repository configuration. + `ExtraTrees=`, `--extra-tree=` : Takes a colon separated pair of paths. The first path refers to a diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 230385177..719d102c7 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -523,6 +523,24 @@ def install_skeleton_trees(state: MkosiState) -> None: shutil.unpack_archive(source, t) +def install_package_manager_trees(state: MkosiState) -> None: + if not state.config.package_manager_trees: + return + + with complete_step("Copying in package maneger file trees…"): + for source, target in state.config.package_manager_trees: + t = state.workspace / "pkgmngr" + if target: + t = state.workspace / "pkgmngr" / target.relative_to("/") + + t.parent.mkdir(mode=0o755, parents=True, exist_ok=True) + + if source.is_dir() or target: + copy_path(source, t, preserve_owner=False) + else: + shutil.unpack_archive(source, t) + + def install_extra_trees(state: MkosiState) -> None: if not state.config.extra_trees: return @@ -815,6 +833,7 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None: *(["--mirror", state.config.mirror] if state.config.mirror else []), "--repository-key-check", yes_no(state.config.repository_key_check), "--repositories", ",".join(state.config.repositories), + "--package-manager-tree", ",".join(format_source_target(s, t) for s, t in state.config.package_manager_trees), *(["--compress-output", str(state.config.compress_output)] if state.config.compress_output else []), "--with-network", yes_no(state.config.with_network), "--cache-only", yes_no(state.config.cache_only), @@ -1246,11 +1265,15 @@ def line_join_list( return "\n ".join(items) +def format_source_target(source: Path, target: Optional[Path]) -> str: + return f"{source}:{target}" if target else f"{source}" + + def line_join_source_target_list(array: Sequence[tuple[Path, Optional[Path]]]) -> str: if not array: return "none" - items = [f"{source}:{target}" if target else f"{source}" for source, target in array] + items = [format_source_target(source, target) for source, target in array] return "\n ".join(items) @@ -1299,6 +1322,7 @@ def summary(args: MkosiArgs, config: MkosiConfig) -> str: Packages: {line_join_list(config.packages)} With Documentation: {yes_no(config.with_docs)} Skeleton Trees: {line_join_source_target_list(config.skeleton_trees)} + Package Manager Trees: {line_join_source_target_list(config.package_manager_trees)} Extra Trees: {line_join_source_target_list(config.extra_trees)} Clean Package Metadata: {yes_no_auto(config.clean_package_metadata)} Remove Files: {line_join_list(config.remove_files)} diff --git a/mkosi/config.py b/mkosi/config.py index 2a7f6e24f..b95a9eb2a 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -260,6 +260,10 @@ def config_default_mirror(namespace: argparse.Namespace) -> Optional[str]: return None +def config_default_package_manager_tree(namespace: argparse.Namespace) -> list[tuple[Path, Optional[Path]]]: + return getattr(namespace, "skeleton_trees", []) + + def make_enum_parser(type: Type[enum.Enum]) -> Callable[[str], enum.Enum]: def parse_enum(value: str) -> enum.Enum: try: @@ -600,6 +604,7 @@ class MkosiConfig: base_trees: list[Path] extra_trees: list[tuple[Path, Optional[Path]]] skeleton_trees: list[tuple[Path, Optional[Path]]] + package_manager_trees: list[tuple[Path, Optional[Path]]] clean_package_metadata: ConfigFeature remove_files: list[str] environment: dict[str, str] @@ -927,6 +932,12 @@ class MkosiConfigParser: parse=config_make_list_parser(delimiter=",", parse=parse_source_target_paths), paths=("mkosi.skeleton", "mkosi.skeleton.tar"), ), + MkosiConfigSetting( + dest="package_manager_trees", + section="Content", + parse=config_make_list_parser(delimiter=",", parse=parse_source_target_paths), + default_factory=config_default_package_manager_tree, + ), MkosiConfigSetting( dest="clean_package_metadata", section="Content", @@ -1630,6 +1641,13 @@ class MkosiConfigParser: dest="skeleton_trees", action=action, ) + group.add_argument( + "--package-manager-tree", + metavar="PATH", + help="Use a package manager tree to configure the package manager", + dest="package_manager_trees", + action=action, + ) group.add_argument( "--clean-package-metadata", metavar="FEATURE", diff --git a/mkosi/distributions/arch.py b/mkosi/distributions/arch.py index b719f2574..8016b2563 100644 --- a/mkosi/distributions/arch.py +++ b/mkosi/distributions/arch.py @@ -84,6 +84,15 @@ class ArchInstaller(DistributionInstaller): ) ) + if any(state.pkgmngr.joinpath("etc/pacman.d/").glob("*.conf")): + f.write( + dedent( + f"""\ + + Include = {state.pkgmngr}/etc/pacman.d/*.conf + """ + ) + ) return invoke_pacman(state, packages, apivfs=apivfs) diff --git a/mkosi/distributions/fedora.py b/mkosi/distributions/fedora.py index 84a421be9..a57d90f9b 100644 --- a/mkosi/distributions/fedora.py +++ b/mkosi/distributions/fedora.py @@ -174,6 +174,7 @@ def invoke_dnf( "--setopt=keepcache=1", "--setopt=install_weak_deps=0", f"--setopt=cachedir={state.cache_dir}", + f"--setopt=reposdir={state.pkgmngr / 'etc/yum.repos.d'}", f"--setopt=varsdir={state.pkgmngr / 'etc/dnf/vars'}", f"--setopt=logdir={state.pkgmngr / 'var/log'}", f"--setopt=persistdir={state.pkgmngr / 'var/lib/dnf'}", diff --git a/tests/test_parse_load_args.py b/tests/test_parse_load_args.py index 362c9f014..9d045089f 100644 --- a/tests/test_parse_load_args.py +++ b/tests/test_parse_load_args.py @@ -12,8 +12,8 @@ from typing import Iterator, List, Optional import pytest +from mkosi.config import MkosiArgs, MkosiConfig, MkosiConfigParser from mkosi.util import Compression, Distribution, Verb -from mkosi.config import MkosiConfigParser, MkosiConfig, MkosiArgs @contextmanager @@ -360,3 +360,28 @@ def test_match_imageversion(op: str, version: str) -> None: assert ("testpkg1" in conf.packages) == opfunc(123, version) assert ("testpkg2" in conf.packages) == opfunc(123, version) assert "testpkg3" not in conf.packages + + +@pytest.mark.parametrize( + "skel,pkgmngr", itertools.product( + [None, Path("/foo"), Path("/bar")], + [None, Path("/foo"), Path("/bar")], + ) +) +def test_package_manager_tree(skel: Optional[Path], pkgmngr: Optional[Path]) -> None: + with cd_temp_dir(): + config = Path("mkosi.conf") + with config.open("w") as f: + f.write("[Content]\n") + if skel is not None: + f.write(f"SkeletonTrees={skel}\n") + if pkgmngr is not None: + f.write(f"PackageManagerTrees={pkgmngr}\n") + + conf = parse([])[1][0] + + skel_expected = [(skel, None)] if skel is not None else [] + pkgmngr_expected = [(pkgmngr, None)] if pkgmngr is not None else skel_expected + + assert conf.skeleton_trees == skel_expected + assert conf.package_manager_trees == pkgmngr_expected diff --git a/tests/test_util.py b/tests/test_util.py index 758978b9a..fa9717964 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,10 +1,7 @@ # SPDX-License-Identifier: LGPL-2.1+ -from mkosi.util import ( - Compression, - Distribution, - PackageType, -) +from mkosi.util import Compression, Distribution, PackageType + def test_distribution() -> None: assert Distribution.fedora.package_type == PackageType.rpm