diff --git a/pmb/__init__.py b/pmb/__init__.py index 01bd6eb7..dfe1bc4b 100644 --- a/pmb/__init__.py +++ b/pmb/__init__.py @@ -14,7 +14,7 @@ if TYPE_CHECKING: from . import config from . import parse -from .config import init as config_init +from .config import init as config_init, require_programs from .helpers import frontend from .helpers import logging from .helpers import mount @@ -76,6 +76,9 @@ def main() -> int: if not args.as_root and os.geteuid() == 0: raise RuntimeError("Do not run pmbootstrap as root!") + # Check for required programs (and find their absolute paths) + require_programs() + # Initialize or require config if args.action == "init": config_init.frontend(args) diff --git a/pmb/config/__init__.py b/pmb/config/__init__.py index 22bfdcb6..844f4712 100644 --- a/pmb/config/__init__.py +++ b/pmb/config/__init__.py @@ -14,6 +14,7 @@ from collections.abc import Sequence from pmb.config.file import load, save, serialize from pmb.config.sudo import which_sudo from pmb.config.other import is_systemd_selected +from .init import require_programs from . import workdir @@ -58,14 +59,16 @@ ondev_min_version = "0.2.0" # Programs that pmbootstrap expects to be available from the host system. Keep # in sync with README.md, and try to keep the list as small as possible. The # idea is to run almost everything in Alpine chroots. -required_programs = [ - "git", - "kpartx", - "losetup", - "openssl", - "ps", - "tar", -] +required_programs: dict[str, str] = { + "git": "", + "kpartx": "", + "losetup": "", + "openssl": "", + "ps": "", + "tar": "", + "chroot": "", + "sh": "", +} def sudo(cmd: Sequence[PathString]) -> Sequence[PathString]: diff --git a/pmb/config/init.py b/pmb/config/init.py index 52418e79..2b364f4b 100644 --- a/pmb/config/init.py +++ b/pmb/config/init.py @@ -36,11 +36,14 @@ import pmb.parse._apkbuild def require_programs() -> None: missing = [] - for program in pmb.config.required_programs: + for program in pmb.config.required_programs.keys(): # Debian: some programs are in /usr/sbin, which is not in PATH # unless using sudo - if not shutil.which(program) and not os.path.exists(os.path.join("/usr/sbin", program)): + prog = shutil.which(program, path=pmb.config.host_path) + if not prog: missing.append(program) + else: + pmb.config.required_programs[program] = prog losetup_missing_json = False @@ -694,8 +697,6 @@ def ask_for_locale(current_locale: str) -> str: def frontend(args: PmbArgs) -> None: - require_programs() - # Work folder (needs to be first, so we can create chroots early) config = get_context().config