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
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
*(["--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),
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)
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)}
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:
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]
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",
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",
)
)
+ 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)
"--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'}",
import pytest
+from mkosi.config import MkosiArgs, MkosiConfig, MkosiConfigParser
from mkosi.util import Compression, Distribution, Verb
-from mkosi.config import MkosiConfigParser, MkosiConfig, MkosiArgs
@contextmanager
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
# 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