pmb.chroot package

Submodules

pmb.chroot.apk module

pmb.chroot.apk.install(packages: list[str], chroot: Chroot, build: bool = True, quiet: bool = False) None

Install packages from pmbootstrap’s local package index or the pmOS/Alpine binary package mirrors. Iterate over all dependencies recursively, and build missing packages as necessary.

Parameters:
  • packages – list of pkgnames to be installed

  • suffix – the chroot suffix, e.g. “native” or “rootfs_qemu-amd64”

  • build – automatically build the package, when it does not exist yet or needs to be updated, and it is inside pmaports. For the special case that all packages are expected to be in Alpine’s repositories, set this to False for performance optimization.

pmb.chroot.apk.install_run_apk(to_add: list[str], to_add_local: list[Path], to_del: list[str], chroot: Chroot) None

Run apk to add packages, and ensure only the desired packages get explicitly marked as installed.

Parameters:
  • to_add – list of pkgnames to install, without their dependencies

  • to_add_local – return of packages_get_locally_built_apks()

  • to_del – list of pkgnames to be deleted, this should be set to conflicting dependencies in any of the packages to be installed or their dependencies (e.g. [“unl0kr”])

  • chroot – the chroot suffix, e.g. “native” or “rootfs_qemu-amd64”

pmb.chroot.apk.installed(suffix: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>) dict[str, ApkindexBlock]

Read the list of installed packages (which has almost the same format, as an APKINDEX, but with more keys).

Returns:

a dictionary with the following structure: { “postmarketos-mkinitfs”: ApkindexBlock }

pmb.chroot.apk.packages_get_locally_built_apks(package_list: list[str], arch: Arch) list[Path]

Iterate over packages and if existing, get paths to locally built packages. This is used to force apk to upgrade packages to newer local versions, even if the pkgver and pkgrel did not change.

Parameters:
  • packages – list of pkgnames

  • arch – architecture that the locally built packages should have

Returns:

Pair of lists, the first is the input packages with local apks removed. the second is a list of apk file paths that are valid inside the chroots, e.g. [“/mnt/pmbootstrap/packages/x86_64/hello-world-1-r6.apk”, …]

pmb.chroot.apk.packages_split_to_add_del(packages)

Sort packages into “to_add” and “to_del” lists depending on their pkgname starting with an exclamation mark.

Parameters:

packages – list of pkgnames

Returns:

(to_add, to_del) - tuple of lists of pkgnames, e.g. ([“hello-world”, …], [“some-conflict-pkg”, …])

pmb.chroot.binfmt module

pmb.chroot.binfmt.is_registered(arch_qemu: Arch) bool
pmb.chroot.binfmt.register(arch: Arch) None

Get arch, magic, mask.

pmb.chroot.binfmt.unregister(arch: Arch) None

pmb.chroot.init module

class pmb.chroot.init.UsrMerge(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Merge /usr while initializing chroot. https://systemd.io/THE_CASE_FOR_THE_USR_MERGE/

AUTO = 0
OFF = 2
ON = 1
pmb.chroot.init.copy_resolv_conf(chroot: Chroot) None

Use pythons super fast file compare function (due to caching) and copy the /etc/resolv.conf to the chroot, in case it is different from the host. If the file doesn’t exist, create an empty file with ‘touch’.

pmb.chroot.init.init_keys()

All Alpine and postmarketOS repository keys are shipped with pmbootstrap. Copy them into $WORK/config_apk_keys, which gets mounted inside the various chroots as /etc/apk/keys.

This is done before installing any package, so apk can verify APKINDEX files of binary repositories even though alpine-keys/postmarketos-keys are not installed yet.

pmb.chroot.init.init_usr_merge(chroot: Chroot) None
pmb.chroot.init.mark_in_chroot(chroot: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>) None

Touch a flag so we can know when we’re running in chroot (and don’t accidentally flash partitions on our host). This marker gets removed in pmb.chroot.shutdown (pmbootstrap shutdown).

pmb.chroot.initfs module

pmb.chroot.initfs.build(flavor: str | None, chroot: Chroot) None
pmb.chroot.initfs.extract(flavor: str | None, chroot: Chroot, extra: bool = False) Path

Extract the initramfs to /tmp/initfs-extracted or the initramfs-extra to /tmp/initfs-extra-extracted and return the outside extraction path.

pmb.chroot.initfs.frontend(args: PmbArgs) None
pmb.chroot.initfs.ls(flavor, suffix, extra=False)

pmb.chroot.initfs_hooks module

pmb.chroot.initfs_hooks.add(hook: str, suffix: Chroot) None
pmb.chroot.initfs_hooks.delete(hook: str, suffix: Chroot) None
pmb.chroot.initfs_hooks.list_aports() list[str]
pmb.chroot.initfs_hooks.list_chroot(suffix: Chroot, remove_prefix: bool = True) list[str]
pmb.chroot.initfs_hooks.ls(suffix: Chroot) None
pmb.chroot.initfs_hooks.update(suffix: Chroot) None

Rebuild and update all hooks that are out of date

pmb.chroot.mount module

pmb.chroot.mount.create_device_nodes(chroot: Chroot) None

Create device nodes for null, zero, full, random, urandom in the chroot.

pmb.chroot.mount.mount(chroot: Chroot) None
pmb.chroot.mount.mount_chroot_image(chroot: Chroot) None

Mount an IMAGE type chroot, to modify an existing rootfs image. This doesn’t support split images yet!

pmb.chroot.mount.mount_dev_tmpfs(chroot: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>) None

Mount tmpfs inside the chroot’s dev folder to make sure we can create device nodes, even if the filesystem of the work folder does not support it.

pmb.chroot.mount.mount_native_into_foreign(chroot: Chroot) None
pmb.chroot.mount.remove_mnt_pmbootstrap(chroot: Chroot) None

Safely remove /mnt/pmbootstrap directories from the chroot, without running rm -r as root and potentially removing data inside the mountpoint in case it was still mounted (bug in pmbootstrap, or user ran pmbootstrap 2x in parallel). This is similar to running ‘rm -r -d’, but we don’t assume that the host’s rm has the -d flag (busybox does not).

pmb.chroot.other module

pmb.chroot.other.copy_xauthority(chroot: Chroot) None

Copy the host system’s Xauthority file to the pmos user inside the chroot, so we can start X11 applications from there.

pmb.chroot.other.kernel_flavor_installed(chroot: Chroot, autoinstall: bool = True) str | None

Get installed kernel flavor. Optionally install the device’s kernel beforehand.

Parameters:
  • suffix – the chroot suffix, e.g. “native” or “rootfs_qemu-amd64”

  • autoinstall – install the device’s kernel if it is not installed

Returns:

  • string with the installed kernel flavor, e.g. [“postmarketos-qcom-sdm845”]

  • None if no kernel is installed

pmb.chroot.run module

pmb.chroot.run.exists(username: str, chroot: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>) bool

Checks if username exists in the system

Parameters:

username – User name

Returns:

bool

pmb.chroot.run.root(cmds: Sequence[PathString], chroot: Chroot = <pmb.core.chroot.Chroot object>, working_dir: PurePath = PurePosixPath('/'), output: RunOutputTypePopen = 'log', output_return: Literal[False] = False, check: bool | None = None, env: Env = {}, disable_timeout: bool = False, add_proxy_env_vars: bool = True) subprocess.Popen
pmb.chroot.run.root(cmds: Sequence[PathString], chroot: Chroot = <pmb.core.chroot.Chroot object>, working_dir: PurePath = PurePosixPath('/'), output: RunOutputTypeDefault = 'log', output_return: Literal[False] = False, check: bool | None = None, env: Env = {}, disable_timeout: bool = False, add_proxy_env_vars: bool = True) int
pmb.chroot.run.root(cmds: Sequence[PathString], chroot: Chroot = <pmb.core.chroot.Chroot object>, working_dir: PurePath = PurePosixPath('/'), output: RunOutputType = 'log', output_return: Literal[True] = False, check: bool | None = None, env: Env = {}, disable_timeout: bool = False, add_proxy_env_vars: bool = True) str
pmb.chroot.run.rootm(cmds: ~collections.abc.Sequence[~collections.abc.Sequence[~pathlib.Path | str]], chroot: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>, working_dir: ~pathlib.PurePath = PurePosixPath('/'), output: ~typing.Literal['log', 'stdout', 'interactive', 'tui', 'null'] | ~typing.Literal['background', 'pipe'] = 'log', output_return: bool = False, check: bool | None = None, env: dict[str, ~pathlib.Path | str] = {}, disable_timeout: bool = False, add_proxy_env_vars: bool = True) str | int | Popen

Run a list of commands inside a chroot as root.

Parameters:
  • env – dict of environment variables to be passed to the command, e.g. {“JOBS”: “5”}

  • working_dir – chroot-relative working directory

  • add_proxy_env_vars – if True, preserve HTTP_PROXY etc. vars from host environment. pmb.chroot.user sets this to False when calling pmb.chroot.root, because it already makes the variables part of the cmd argument.

See pmb.helpers.run_core.core() for a detailed description of all other arguments and the return value.

pmb.chroot.run.user(cmd: Sequence[PathString], chroot: Chroot = <pmb.core.chroot.Chroot object>, working_dir: Path = PosixPath('/'), output: RunOutputTypePopen = 'log', output_return: Literal[False] = False, check: bool | None = None, env: Env = {}) subprocess.Popen
pmb.chroot.run.user(cmd: Sequence[PathString], chroot: Chroot = <pmb.core.chroot.Chroot object>, working_dir: Path = PosixPath('/'), output: RunOutputTypeDefault = 'log', output_return: Literal[False] = False, check: bool | None = None, env: Env = {}) int
pmb.chroot.run.user(cmd: Sequence[PathString], chroot: Chroot = <pmb.core.chroot.Chroot object>, working_dir: Path = PosixPath('/'), output: RunOutputType = 'log', output_return: Literal[True] = False, check: bool | None = None, env: Env = {}) str
pmb.chroot.run.userm(cmds: ~collections.abc.Sequence[~collections.abc.Sequence[~pathlib.Path | str]], chroot: ~pmb.core.chroot.Chroot = <pmb.core.chroot.Chroot object>, working_dir: ~pathlib.Path = PosixPath('/'), output: ~typing.Literal['log', 'stdout', 'interactive', 'tui', 'null'] | ~typing.Literal['background', 'pipe'] = 'log', output_return: bool = False, check: bool | None = None, env: dict[str, ~pathlib.Path | str] = {}) str | int | Popen

Run a command inside a chroot as “user”. We always use the BusyBox implementation of ‘su’, because other implementations may override the PATH environment variable (#1071).

Parameters:

env – dict of environment variables to be passed to the command, e.g. {“JOBS”: “5”}

See pmb.helpers.run_core.core() for a detailed description of all other arguments and the return value.

pmb.chroot.shutdown module

pmb.chroot.shutdown.kill_adb()

Kill adb daemon if it’s running.

pmb.chroot.shutdown.kill_sccache()

Kill sccache daemon if it’s running. Unlike ccache it automatically spawns a daemon when you call it and exits after some time of inactivity.

pmb.chroot.shutdown.shutdown(only_install_related=False)
pmb.chroot.shutdown.shutdown_cryptsetup_device(name: str) None
Parameters:

name – cryptsetup device name, usually “pm_crypt” in pmbootstrap

pmb.chroot.zap module

pmb.chroot.zap.del_chroot(path: Path, confirm: bool = True, dry: bool = False) None
pmb.chroot.zap.zap(confirm: bool = True, dry: bool = False, pkgs_local: bool = False, http: bool = False, pkgs_local_mismatch: bool = False, pkgs_online_mismatch: bool = False, distfiles: bool = False, rust: bool = False, netboot: bool = False) None

Shutdown everything inside the chroots (e.g. adb), umount everything and then safely remove folders from the work-directory.

Parameters:
  • dry – Only show what would be deleted, do not delete for real

  • pkgs_local – Remove all self-compiled packages (!)

  • http – Clear the http cache (used e.g. for the initial apk download)

  • pkgs_local_mismatch – Remove the packages that have a different version compared to what is in the aports folder.

  • pkgs_online_mismatch – Clean out outdated binary packages downloaded from mirrors (e.g. from Alpine)

  • distfiles – Clear the downloaded files cache

  • rust – Remove rust related caches

  • netboot – Remove images for netboot

NOTE: This function gets called in pmb/config/init.py, with only get_context().config.work and args.device set!

pmb.chroot.zap.zap_pkgs_local_mismatch(confirm: bool = True, dry: bool = False) None
pmb.chroot.zap.zap_pkgs_online_mismatch(confirm=True, dry=False)

Module contents