`SkeletonTree=`, `--skeleton-tree=`
-: Takes a path to a directory to copy into the OS tree before invoking
- the package manager. Use this to insert files and directories into
- the OS tree before the package manager installs any packages. If
- this option is not used, but the `mkosi.skeleton/` directory is
- found in the local directory it is automatically used for this
- purpose (also see the "Files" section below).
+: Takes a colon separated pair of paths. The first path refers to a
+ directory to copy into the OS tree before invoking the package
+ manager. The second path refers to the target directory inside the
+ image. If the second path is not provided, the directory is copied
+ on top of the root directory of the image. Use this to insert files
+ and directories into the OS tree before the package manager installs
+ any packages. If this option is not used, but the `mkosi.skeleton/`
+ directory is found in the local directory it is automatically used
+ for this purpose with the root directory as target (also see the
+ "Files" section below).
: Instead of a directory, a tar file may be provided. In this case
it is unpacked into the OS tree before the package manager is
`ExtraTree=`, `--extra-tree=`
-: Takes a path to a directory to copy on top of the OS tree the
- package manager generated. Use this to override any default
- configuration files shipped with the distribution. If this option is
- not used, but the `mkosi.extra/` directory is found in the local
- directory it is automatically used for this purpose (also see the
- "Files" section below).
+: Takes a colon separated pair of paths. The first path refers to a
+ directory to copy from the host into the image. The second path refers
+ to the target directory inside the image. If the second path is not
+ provided, the directory is copied on top of the root directory of the
+ image. Use this to override any default configuration files shipped
+ with the distribution. If this option is not used, but the
+ `mkosi.extra/` directory is found in the local directory it is
+ automatically used for this purpose with the root directory as target.
+ (also see the "Files" section below).
: As with the skeleton tree logic above, instead of a directory, a tar
file may be provided too. `mkosi.skeleton.tar` will be automatically
return
with complete_step("Copying in extra file trees…"):
- for tree in state.config.extra_trees:
- if tree.is_dir():
- copy_path(tree, state.root, preserve_owner=False)
+ for source, target in state.config.extra_trees:
+ t = state.root
+ if target:
+ t = state.root / target.relative_to("/")
+
+ t.mkdir(mode=0o755, parents=True, exist_ok=True)
+
+ if source.is_dir():
+ copy_path(source, t, preserve_owner=False)
else:
# unpack_archive() groks Paths, but mypy doesn't know this.
# Pretend that tree is a str.
- shutil.unpack_archive(tree, state.root)
+ shutil.unpack_archive(source, t)
def install_build_dest(state: MkosiState) -> None:
mkosi --version
""".format(b=MkosiPrinter.bold, e=MkosiPrinter.reset)
+
+def parse_source_target_paths(value: str) -> tuple[Path, Optional[Path]]:
+ src, _, target = value.partition(':')
+ if target and not Path(target).absolute():
+ die("Target path must be absolute")
+ return Path(src), Path(target) if target else None
+
+
def create_parser() -> ArgumentParserMkosi:
parser = ArgumentParserMkosi(
prog="mkosi",
dest="extra_trees",
default=[],
help="Copy an extra tree on top of image",
- type=Path,
+ type=parse_source_target_paths,
metavar="PATH",
)
group.add_argument(
dest="skeleton_trees",
default=[],
help="Use a skeleton tree to bootstrap the image before installing anything",
- type=Path,
+ type=parse_source_target_paths,
metavar="PATH",
)
group.add_argument(
return
if os.path.isdir("mkosi.extra"):
- args.extra_trees.append(Path("mkosi.extra"))
+ args.extra_trees.append((Path("mkosi.extra"), None))
if os.path.isfile("mkosi.extra.tar"):
- args.extra_trees.append(Path("mkosi.extra.tar"))
+ args.extra_trees.append((Path("mkosi.extra.tar"), None))
def find_skeleton(args: argparse.Namespace) -> None:
return
if os.path.isdir("mkosi.skeleton"):
- args.skeleton_trees.append(Path("mkosi.skeleton"))
+ args.skeleton_trees.append((Path("mkosi.skeleton"), None))
if os.path.isfile("mkosi.skeleton.tar"):
- args.skeleton_trees.append(Path("mkosi.skeleton.tar"))
+ args.skeleton_trees.append((Path("mkosi.skeleton.tar"), None))
def args_find_path(args: argparse.Namespace, name: str, path: str, *, as_list: bool = False) -> None:
if args.extra_trees:
for i in range(len(args.extra_trees)):
- args.extra_trees[i] = args.extra_trees[i].absolute()
+ source, target = args.extra_trees[i]
+ args.extra_trees[i] = (source.absolute(), target)
if args.skeleton_trees is not None:
for i in range(len(args.skeleton_trees)):
- args.skeleton_trees[i] = args.skeleton_trees[i].absolute()
+ source, target = args.skeleton_trees[i]
+ args.skeleton_trees[i] = (source.absolute(), target)
if args.secure_boot_key is not None:
args.secure_boot_key = args.secure_boot_key.absolute()
os.open(path, os.R_OK)
+def check_source_target_input(tree: tuple[Path, Optional[Path]]) -> None:
+ source, _ = tree
+ os.open(source, os.R_OK)
+
+
def check_script_input(path: Optional[Path]) -> None:
if not path:
return
for tree in (config.skeleton_trees,
config.extra_trees):
for item in tree:
- check_tree_input(item)
+ check_source_target_input(item)
for path in (config.build_script,
config.prepare_script,
return "\n ".join(items)
+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]
+ return "\n ".join(items)
+
+
def print_summary(config: MkosiConfig) -> None:
print("COMMANDS:")
print(" With Documentation:", yes_no(config.with_docs))
print(" Package Cache:", none_to_none(config.cache_path))
- print(" Extra Trees:", line_join_list(config.extra_trees, check_tree_input))
- print(" Skeleton Trees:", line_join_list(config.skeleton_trees, check_tree_input))
+ print(" Extra Trees:", line_join_source_target_list(config.extra_trees))
+ print(" Skeleton Trees:", line_join_source_target_list(config.skeleton_trees))
print(" CleanPackageMetadata:", yes_no_or(config.clean_package_metadata))
if config.remove_files: