"""
with tempfile.TemporaryDirectory() as tempdir:
with chdir(tempdir):
- args, _ = parse_config([])
+ args, _, _ = parse_config([])
return args
This prevents Config being generated with defaults values implicitly.
"""
with chdir("/proc"):
- _, [config] = parse_config([])
+ _, _, [config] = parse_config([])
return config
self.includes.add((st.st_dev, st.st_ino))
if any(p == Path(c) for c in BUILTIN_CONFIGS):
- _, [config] = parse_config(
+ _, _, [config] = parse_config(
["--directory", "", "--include", os.fspath(path)],
only_sections=self.only_sections,
resources=self.resources,
)
+def finalize_default_tools(config: argparse.Namespace, *, resources: Path) -> Config:
+ main = Config.from_namespace(config)
+
+ if not main.tools_tree_distribution:
+ die(
+ f"{main.distribution} does not have a default tools tree distribution",
+ hint="use ToolsTreeDistribution= to set one explicitly",
+ )
+
+ cmdline = [
+ "--directory=",
+ f"--distribution={main.tools_tree_distribution}",
+ *([f"--release={main.tools_tree_release}"] if main.tools_tree_release else []),
+ *([f"--profile={profile}" for profile in main.tools_tree_profiles]),
+ *([f"--mirror={main.tools_tree_mirror}"] if main.tools_tree_mirror else []),
+ *([f"--repositories={repository}" for repository in main.tools_tree_repositories]),
+ *([f"--sandbox-tree={tree}" for tree in main.tools_tree_sandbox_trees]),
+ f"--repository-key-check={main.repository_key_check}",
+ f"--repository-key-fetch={main.repository_key_fetch}",
+ f"--cache-only={main.cacheonly}",
+ *([f"--workspace-directory={os.fspath(p)}"] if (p := main.workspace_dir) else []),
+ *([f"--package-cache-directory={os.fspath(p)}"] if (p := main.package_cache_dir) else []),
+ "--incremental=no",
+ *([f"--package={package}" for package in main.tools_tree_packages]),
+ *([f"--package-directory={os.fspath(directory)}" for directory in main.tools_tree_package_directories]), # noqa: E501
+ *([f"--build-sources={tree}" for tree in main.build_sources]),
+ f"--build-sources-ephemeral={main.build_sources_ephemeral}",
+ *([f"--sync-script={os.fspath(script)}" for script in main.tools_tree_sync_scripts]),
+ *([f"--prepare-script={os.fspath(script)}" for script in main.tools_tree_prepare_scripts]),
+ *([f"--source-date-epoch={e}"] if (e := main.source_date_epoch) is not None else []),
+ *([f"--environment={k}='{v}'" for k, v in main.environment.items()]),
+ *([f"--proxy-url={main.proxy_url}"] if main.proxy_url else []),
+ *([f"--proxy-exclude={host}" for host in main.proxy_exclude]),
+ *([f"--proxy-peer-certificate={os.fspath(p)}"] if (p := main.proxy_peer_certificate) else []),
+ *([f"--proxy-client-certificate={os.fspath(p)}"] if (p := main.proxy_client_certificate) else []),
+ *([f"--proxy-client-key={os.fspath(p)}"] if (p := main.proxy_client_key) else []),
+ ] # fmt: skip
+
+ _, _, [tools] = parse_config(
+ cmdline + ["--include=mkosi-tools", "build"],
+ resources=resources,
+ )
+
+ tools = dataclasses.replace(tools, image="tools")
+
+ return tools
+
+
def parse_config(
argv: Sequence[str] = (),
*,
resources: Path = Path("/"),
only_sections: Sequence[str] = (),
-) -> tuple[Args, tuple[Config, ...]]:
+) -> tuple[Args, Optional[Config], tuple[Config, ...]]:
argv = list(argv)
context = ParseContext(resources)
PagerHelpAction.__call__(None, argparser, context.cli) # type: ignore
if not args.verb.needs_config():
- return args, ()
+ return args, None, ()
if have_history(args):
try:
for s in SETTINGS:
setattr(config, s.dest, context.finalize_value(s))
+ if getattr(config, "tools_tree", None) == Path("default"):
+ tools = finalize_default_tools(config, resources=resources)
+ else:
+ tools = None
+
if prev:
- return args, (*subimages, Config.from_namespace(config))
+ return args, tools, (*subimages, Config.from_namespace(config))
+
+ if tools:
+ setattr(config, "tools_tree", tools.output_dir_or_cwd() / tools.output)
images = []
subimages = [Config.from_namespace(ns) for ns in images]
subimages = resolve_deps(subimages, main.dependencies)
- return args, tuple(subimages + [main])
+ return args, tools, tuple(subimages + [main])
def finalize_term() -> str:
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.distribution == Distribution.ubuntu
assert config.architecture == Architecture.arm64
assert config.image_id == "base"
with chdir(d):
- _, [config] = parse_config(
+ _, _, [config] = parse_config(
[
"--distribution", "fedora",
"--environment", "MY_KEY=CLI_VALUE",
assert config.repositories == ["epel", "epel-next", "universe"]
with chdir(d):
- _, [config] = parse_config(
+ _, _, [config] = parse_config(
[
"--distribution", "",
"--environment", "",
)
with chdir(d):
- _, [config] = parse_config(["--profile", "last"])
+ _, _, [config] = parse_config(["--profile", "last"])
# Setting a value explicitly in a dropin should override the default from mkosi.conf.
assert config.distribution == Distribution.debian
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
# Test that empty assignment resets settings.
assert config.packages == []
(d / "mkosi.conf.d/d1.conf").unlink()
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
# ImageVersion= is not set explicitly anymore, so now the version from mkosi.version should be used.
assert config.image_version == "1.2.3"
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.bootable == ConfigFeature.auto
assert config.split_artifacts == ArtifactOutput.compat_no()
# Passing the directory should include both the main config file and the dropin.
- _, [config] = parse_config(["--include", os.fspath(d / "abc")] * 2)
+ _, _, [config] = parse_config(["--include", os.fspath(d / "abc")] * 2)
assert config.bootable == ConfigFeature.enabled
assert config.split_artifacts == ArtifactOutput.compat_yes()
# The same extra config should not be parsed more than once.
assert config.build_packages == ["abc"]
# Passing the main config file should not include the dropin.
- _, [config] = parse_config(["--include", os.fspath(d / "abc/mkosi.conf")])
+ _, _, [config] = parse_config(["--include", os.fspath(d / "abc/mkosi.conf")])
assert config.bootable == ConfigFeature.enabled
assert config.split_artifacts == ArtifactOutput.compat_no()
)
with chdir(d):
- _, [one, two, config] = parse_config(
+ _, _, [one, two, config] = parse_config(
["--package", "qed", "--build-package", "def", "--repositories", "cli"]
)
assert len(two.sandbox_trees) == 0
with chdir(d):
- _, [one, two, config] = parse_config(["--image-version", "7.8.9"])
+ _, _, [one, two, config] = parse_config(["--image-version", "7.8.9"])
# Inherited settings specified on the CLI should not override subimages that configure the setting
# explicitly.
)
with chdir(d):
- _, [config] = parse_config(["--include", "abc.conf", "--include", "abc.conf"])
+ _, _, [config] = parse_config(["--include", "abc.conf", "--include", "abc.conf"])
assert config.build_packages == ["abc", "def"]
(d / "mkosi.images").mkdir()
)
with chdir(d):
- _, [one, two, config] = parse_config([])
+ _, _, [one, two, config] = parse_config([])
assert one.build_packages == ["def"]
assert two.build_packages == ["def"]
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.profiles == ["profile"]
# The profile should override mkosi.conf.d/
(d / "mkosi.conf").unlink()
with chdir(d):
- _, [config] = parse_config(["--profile", "profile"])
+ _, _, [config] = parse_config(["--profile", "profile"])
assert config.profiles == ["profile"]
# The profile should override mkosi.conf.d/
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.profiles == ["profile", "abc"]
assert config.distribution == Distribution.opensuse
)
with chdir(d):
- _, [subimage, config] = parse_config()
+ _, _, [subimage, config] = parse_config()
assert subimage.environment["Image"] == "subimage"
)
with chdir(d):
- _, [config] = parse_config(["--tools-tree", "", "--environment", ""])
+ _, _, [config] = parse_config(["--tools-tree", "", "--environment", ""])
assert config.tools_tree is None
assert "MY_KEY" not in config.environment
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.distribution == Distribution.debian
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
# Local config should take precedence over non-local config.
assert config.distribution == Distribution.debian
assert config.with_tests
with chdir(d):
- _, [config] = parse_config(["--distribution", "fedora", "-T"])
+ _, _, [config] = parse_config(["--distribution", "fedora", "-T"])
assert config.distribution == Distribution.fedora
assert not config.with_tests
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.environment == {"FOO": "override", "BAR": "override", "BAZ": "override"}
def test_os_distribution(tmp_path: Path) -> None:
with chdir(tmp_path):
for dist in Distribution:
- _, [config] = parse_config(["-d", dist.value])
+ _, _, [config] = parse_config(["-d", dist.value])
assert config.distribution == dist
with pytest.raises(tuple((argparse.ArgumentError, SystemExit))):
for dist in Distribution:
Path("mkosi.conf").write_text(f"[Distribution]\nDistribution={dist}")
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.distribution == dist
(confd / "10-file.conf").write_text("[Content]\nPackages=yes")
(confd / "20-file.noconf").write_text("[Content]\nPackages=nope")
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.packages == ["yes"]
def test_compression(tmp_path: Path) -> None:
with chdir(tmp_path):
- _, [config] = parse_config(["--format", "disk", "--compress-output", "False"])
+ _, _, [config] = parse_config(["--format", "disk", "--compress-output", "False"])
assert config.compress_output == Compression.none
"""
)
- _, [config] = parse_config(["--format", "tar"])
+ _, _, [config] = parse_config(["--format", "tar"])
assert config.image_id != "abcde"
)
# Both sections are not matched, so image ID should not be "abcde".
- _, [config] = parse_config(["--format", "tar", "--architecture", "s390x"])
+ _, _, [config] = parse_config(["--format", "tar", "--architecture", "s390x"])
assert config.image_id != "abcde"
# Only a single section is matched, so image ID should not be "abcde".
- _, [config] = parse_config(["--format", "disk", "--architecture", "s390x"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture", "s390x"])
assert config.image_id != "abcde"
# Both sections are matched, so image ID should be "abcde".
- _, [config] = parse_config(["--format", "disk", "--architecture", "x86-64"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture", "x86-64"])
assert config.image_id == "abcde"
Path("mkosi.conf").write_text(
)
# Both sections are not matched, so image ID should not be "abcde".
- _, [config] = parse_config(["--format", "tar", "--architecture", "s390x"])
+ _, _, [config] = parse_config(["--format", "tar", "--architecture", "s390x"])
assert config.image_id != "abcde"
# The first section is matched, so image ID should be "abcde".
- _, [config] = parse_config(["--format", "disk", "--architecture", "x86-64"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture", "x86-64"])
assert config.image_id == "abcde"
# The second section is matched, so image ID should be "abcde".
- _, [config] = parse_config(["--format", "directory", "--architecture", "arm64"])
+ _, _, [config] = parse_config(["--format", "directory", "--architecture", "arm64"])
assert config.image_id == "abcde"
# Parts of all section are matched, but none is matched fully, so image ID should not be "abcde".
- _, [config] = parse_config(["--format", "disk", "--architecture", "arm64"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture", "arm64"])
assert config.image_id != "abcde"
Path("mkosi.conf").write_text(
)
# The first section is matched, so image ID should be "abcde".
- _, [config] = parse_config(["--format", "disk"])
+ _, _, [config] = parse_config(["--format", "disk"])
assert config.image_id == "abcde"
Path("mkosi.conf").write_text(
)
# No sections are matched, so image ID should be not "abcde".
- _, [config] = parse_config(["--format", "disk", "--architecture=arm64"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture=arm64"])
assert config.image_id != "abcde"
# Mixing both [Match] and [TriggerMatch]
)
# Match and first TriggerMatch sections match
- _, [config] = parse_config(["--format", "disk", "--architecture=arm64"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture=arm64"])
assert config.image_id == "abcde"
# Match section matches, but no TriggerMatch section matches
- _, [config] = parse_config(["--format", "disk", "--architecture=s390x"])
+ _, _, [config] = parse_config(["--format", "disk", "--architecture=s390x"])
assert config.image_id != "abcde"
# Second TriggerMatch section matches, but the Match section does not
- _, [config] = parse_config(["--format", "tar", "--architecture=x86-64"])
+ _, _, [config] = parse_config(["--format", "tar", "--architecture=x86-64"])
assert config.image_id != "abcde"
"""
)
- _, [config] = parse_config([])
+ _, _, [config] = parse_config([])
assert config.environment.get("ABC") == "QED"
- _, [config] = parse_config(["--profile", "profile"])
+ _, _, [config] = parse_config(["--profile", "profile"])
assert config.environment.get("ABC") is None
"""
)
- _, [conf] = parse_config()
+ _, _, [conf] = parse_config()
assert "testpkg1" in conf.packages
if dist1 == dist2:
assert "testpkg2" in conf.packages
"""
)
- _, [conf] = parse_config()
+ _, _, [conf] = parse_config()
assert "testpkg1" in conf.packages
if release1 == release2:
assert "testpkg2" in conf.packages
)
with chdir(d):
- _, [config] = parse_config(["--build-sources", ".:kernel"])
+ _, _, [config] = parse_config(["--build-sources", ".:kernel"])
assert config.output == "abc"
)
with chdir(d):
- _, [config] = parse_config(["--repositories", "epel,epel-next"])
+ _, _, [config] = parse_config(["--repositories", "epel,epel-next"])
assert config.output == "qed"
"""
)
- _, [conf] = parse_config()
+ _, _, [conf] = parse_config()
assert "testpkg1" in conf.packages
if image1 == image2:
assert "testpkg2" in conf.packages
"""
)
- _, [conf] = parse_config()
+ _, _, [conf] = parse_config()
assert ("testpkg1" in conf.packages) == opfunc(123, version)
assert ("testpkg2" in conf.packages) == opfunc(123, version)
assert "testpkg3" not in conf.packages
)
with chdir(d):
- _, [conf] = parse_config(["--environment", "MYENV=abc"])
+ _, _, [conf] = parse_config(["--environment", "MYENV=abc"])
assert conf.image_id == "matched"
- _, [conf] = parse_config(["--environment", "MYENV=bad"])
+ _, _, [conf] = parse_config(["--environment", "MYENV=bad"])
assert conf.image_id != "matched"
- _, [conf] = parse_config(["--environment", "MYEN=abc"])
+ _, _, [conf] = parse_config(["--environment", "MYEN=abc"])
assert conf.image_id != "matched"
- _, [conf] = parse_config(["--environment", "MYEN=bad"])
+ _, _, [conf] = parse_config(["--environment", "MYEN=bad"])
assert conf.image_id != "matched"
(d / "mkosi.conf").write_text(
)
with chdir(d):
- _, [conf] = parse_config(["--environment", "MYENV=abc"])
+ _, _, [conf] = parse_config(["--environment", "MYENV=abc"])
assert conf.image_id == "matched"
- _, [conf] = parse_config(["--environment", "MYENV=bad"])
+ _, _, [conf] = parse_config(["--environment", "MYENV=bad"])
assert conf.image_id == "matched"
- _, [conf] = parse_config(["--environment", "MYEN=abc"])
+ _, _, [conf] = parse_config(["--environment", "MYEN=abc"])
assert conf.image_id != "matched"
with chdir(tmp_path):
Path("mkosi.sandbox.tar").touch()
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.sandbox_trees == [
ConfigTree(Path.cwd() / "mkosi.sandbox.tar", None),
)
with chdir(d):
- _, [subimage, config] = parse_config()
+ _, _, [subimage, config] = parse_config()
expected = {
"Distribution": "ubuntu",
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.output == "output_1.2.3"
(d / "mkosi.images/sub.conf").touch()
with chdir(d):
- _, [sub, config] = parse_config()
+ _, _, [sub, config] = parse_config()
expected = {
"TestValue1": "100", # from other.env
with chdir(d):
with pytest.raises(SystemExit) as error:
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert error.type is SystemExit
assert error.value.code != 0
version.chmod(0o755)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.image_version == "1.2.3"
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.split_artifacts == [ArtifactOutput.uki]
(d / "mkosi.conf").write_text(
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.split_artifacts == [
ArtifactOutput.uki,
ArtifactOutput.kernel,
d = tmp_path
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.split_artifacts == ArtifactOutput.compat_no()
(d / "mkosi.conf").write_text(
)
with chdir(d):
- _, [config] = parse_config()
+ _, _, [config] = parse_config()
assert config.split_artifacts == ArtifactOutput.compat_yes()
)
with chdir(d):
- _, [config] = parse_config(["--package", ""])
+ _, _, [config] = parse_config(["--package", ""])
assert config.packages == []
- _, [config] = parse_config(["--package", "", "--package", "foo"])
+ _, _, [config] = parse_config(["--package", "", "--package", "foo"])
assert config.packages == ["foo"]
- _, [config] = parse_config(["--package", "foo", "--package", "", "--package", "bar"])
+ _, _, [config] = parse_config(["--package", "foo", "--package", "", "--package", "bar"])
assert config.packages == ["bar"]
- _, [config] = parse_config(["--package", "foo", "--package", ""])
+ _, _, [config] = parse_config(["--package", "foo", "--package", ""])
assert config.packages == []