pmb.helpers package

Submodules

pmb.helpers.apk module

pmb.helpers.apk.apk_with_progress(command: Sequence[Path | str])

Run an apk subcommand while printing a progress bar to STDOUT.

Parameters:
  • command – apk subcommand in list form

  • chroot – whether to run commands inside the chroot or on the host

  • suffix – chroot suffix. Only applies if the “chroot” parameter is set to True.

Raises:

RuntimeError – when the apk command fails

pmb.helpers.apk.check_outdated(version_installed, action_msg)

Check if the provided alpine version is outdated.

This depends on the alpine mirrordir (edge, v3.12, …) related to currently checked out pmaports branch.

Parameters:
  • version_installed – currently installed apk version, e.g. “2.12.1-r0”

  • action_msg – string explaining what the user should do to resolve this

Raises:

RuntimeError if the version is outdated

pmb.helpers.aportupgrade module

pmb.helpers.aportupgrade.get_package_version_info_github(repo_name: str, ref: str | None)
pmb.helpers.aportupgrade.get_package_version_info_gitlab(gitlab_host: str, repo_name: str, ref: str | None)
pmb.helpers.aportupgrade.init_req_headers() None
pmb.helpers.aportupgrade.upgrade(args: PmbArgs, pkgname, git=True, stable=True) None

Find new versions of a single package and upgrade it.

Parameters:
  • pkgname – the name of the package

  • git – True if git packages should be upgraded

  • stable – True if stable packages should be upgraded

pmb.helpers.aportupgrade.upgrade_all(args: PmbArgs) None

Upgrade all packages, based on args.all, args.all_git and args.all_stable.

pmb.helpers.aportupgrade.upgrade_git_package(args: PmbArgs, pkgname: str, package) None

Update _commit/pkgver/pkgrel in a git-APKBUILD (or pretend to do it if args.dry is set).

Parameters:
  • pkgname – the package name

  • package – a dict containing package information

pmb.helpers.aportupgrade.upgrade_stable_package(args: PmbArgs, pkgname: str, package) None

Update _commit/pkgver/pkgrel in an APKBUILD (or pretend to do it if args.dry is set).

Parameters:
  • pkgname – the package name

  • package – a dict containing package information

pmb.helpers.args module

pmb.helpers.args.init(args: PmbArgs) PmbArgs
pmb.helpers.args.please_i_really_need_args() PmbArgs

pmb.helpers.cli module

class pmb.helpers.cli.ReadlineTabCompleter(options)

Bases: object

Store intermediate state for completer function.

completer_func(input_text, iteration)
Parameters:
  • input_text – text that shall be autocompleted

  • iteration – how many times “tab” was hit

pmb.helpers.cli.ask(question='Continue?', choices=['y', 'n'], default='n', lowercase_answer=True, validation_regex=None, complete=None)

Ask a question on the terminal.

Parameters:
  • question – display prompt

  • choices – short list of possible answers, displayed after prompt if set

  • default – default value to return if user doesn’t input anything

  • lowercase_answer – if True, convert return value to lower case

  • validation_regex – if set, keep asking until regex matches

  • complete – set to a list to enable tab completion

pmb.helpers.cli.confirm(question='Continue?', default=False, no_assumptions=False)

Convenience wrapper around ask for simple yes-no questions with validation.

Parameters:

no_assumptions – ask for confirmation, even if “pmbootstrap -y’ is set

Returns:

True for “y”, False for “n”

pmb.helpers.cli.progress_flush()

Finish printing a progress bar.

This will erase the line. Does nothing in non-interactive mode.

pmb.helpers.cli.progress_print(progress)

Print a snapshot of a progress bar to STDOUT.

Call progress_flush to end printing progress and clear the line. No output is printed in non-interactive mode.

Parameters:

progress – completion percentage as a number between 0 and 1

pmb.helpers.devices module

pmb.helpers.devices.find_path(codename: str, file='') Path | None

Find path to device APKBUILD under device/*/device-.

Parameters:
  • codename – device codename

  • file – file to look for (e.g. APKBUILD or deviceinfo), may be empty

Returns:

path to APKBUILD

pmb.helpers.devices.list_codenames(vendor=None, archived=True)

Get all devices, for which aports are available.

Parameters:
  • vendor – vendor name to choose devices from, or None for all vendors

  • archived – include archived devices

Returns:

[“first-device”, “second-device”, …]

pmb.helpers.devices.list_vendors()

Get all device vendors, for which aports are available.

Returns:

{“vendor1”, “vendor2”, …}

pmb.helpers.file module

pmb.helpers.file.is_older_than(path, seconds)

Check if a single file is older than a given amount of seconds.

pmb.helpers.file.is_up_to_date(path_sources, path_target=None, lastmod_target=None)

Check if a file is up-to-date by comparing the last modified timestamps.

(just like make does it).

Parameters:
  • path_sources – list of full paths to the source files

  • path_target – full path to the target file

  • lastmod_target – the timestamp of the target file. specify this as alternative to specifying path_target.

pmb.helpers.file.replace(path: Path, old: str, new: str)
pmb.helpers.file.replace_apkbuild(args: PmbArgs, pkgname, key, new, in_quotes=False)

Replace one key=value line in an APKBUILD and verify it afterwards.

Parameters:
  • pkgname – package name, e.g. “hello-world”

  • key – key that should be replaced, e.g. “pkgver”

  • new – new value

  • in_quotes – expect the value to be in quotation marks (“”)

Check if the symlink is already present, otherwise create it.

pmb.helpers.frontend module

pmb.helpers.frontend.apkbuild_parse(args: PmbArgs)
pmb.helpers.frontend.apkindex_parse(args: PmbArgs)
pmb.helpers.frontend.aportgen(args: PmbArgs)
pmb.helpers.frontend.aportupgrade(args: PmbArgs)
pmb.helpers.frontend.bootimg_analyze(args: PmbArgs)
pmb.helpers.frontend.build(args: PmbArgs)
pmb.helpers.frontend.build_init(args: PmbArgs)
pmb.helpers.frontend.checksum(args: PmbArgs)
pmb.helpers.frontend.chroot(args: PmbArgs)
pmb.helpers.frontend.ci(args: PmbArgs)
pmb.helpers.frontend.config(args: PmbArgs)
pmb.helpers.frontend.deviceinfo_parse(args: PmbArgs)
pmb.helpers.frontend.export(args: PmbArgs)
pmb.helpers.frontend.flasher(args: PmbArgs)
pmb.helpers.frontend.initfs(args: PmbArgs)
pmb.helpers.frontend.install(args: PmbArgs)
pmb.helpers.frontend.lint(args: PmbArgs)
pmb.helpers.frontend.netboot(args: PmbArgs)
pmb.helpers.frontend.newapkbuild(args: PmbArgs)
pmb.helpers.frontend.pkgrel_bump(args: PmbArgs)
pmb.helpers.frontend.qemu(args: PmbArgs)
pmb.helpers.frontend.repo_missing(args: PmbArgs)
pmb.helpers.frontend.sideload(args: PmbArgs)
pmb.helpers.frontend.stats(args: PmbArgs)
pmb.helpers.frontend.status(args: PmbArgs) None
pmb.helpers.frontend.update(args: PmbArgs)
pmb.helpers.frontend.work_migrate(args: PmbArgs)
pmb.helpers.frontend.zap(args: PmbArgs)

pmb.helpers.git module

pmb.helpers.git.branch_looks_official(repo: Path, branch)
Check if a given branch follows the patterns of official branches in

pmaports or aports.

Returns:

True if it looks official, False otherwise

pmb.helpers.git.can_fast_forward(path, branch_upstream, branch='HEAD')
pmb.helpers.git.clean_worktree(path: Path)

Check if there are not any modified files in the git dir.

pmb.helpers.git.clone(name_repo: str)

Clone a git repository to $WORK/cache_git/$name_repo.

(or to the overridden path set in args, as with pmbootstrap --aports).

Parameters:

name_repo – short alias used for the repository name, from pmb.config.git_repos (e.g. “aports_upstream”, “pmaports”)

pmb.helpers.git.get_files(repo: Path)

Get all files inside a git repository, that are either already in the git tree or are not in gitignore.

Do not list deleted files. To be used for creating a tarball of the git repository.

Parameters:

path – top dir of the git repository

Returns:

all files in a git repository as list, relative to path

pmb.helpers.git.get_path(name_repo: str)

Get the path to the repository.

The path is either the default one in the work dir, or a user-specified one in args.

Returns:

full path to repository

pmb.helpers.git.get_topdir(repo: Path)

Get top-dir of git repo.

Returns:

a string with the top dir of the git repository, or an empty string if it’s not a git repository.

pmb.helpers.git.get_upstream_remote(aports: Path)

Find the remote, which matches the git URL from the config.

Usually “origin”, but the user may have set up their git repository differently.

pmb.helpers.git.pull(repo_name: str)

Check if on official branch and essentially try git pull --ff-only.

Instead of really doing git pull --ff-only, do it in multiple steps (fetch, merge --ff-only), so we can display useful messages depending on which part fails.

Returns:

integer, >= 0 on success, < 0 on error

pmb.helpers.git.rev_parse(path: Path, revision='HEAD', extra_args: list = [])

Run “git rev-parse” in a specific repository dir.

Parameters:
  • path – to the git repository

  • extra_args – additional arguments for git rev-parse. Pass --abbrev-ref to get the branch instead of the commit, if possible.

Returns:

commit string like “90cd0ad84d390897efdcf881c0315747a4f3a966” or (with --abbrev-ref): the branch name, e.g. “master”

pmb.helpers.http module

pmb.helpers.http.cache_file(prefix: str, url: str) Path
pmb.helpers.http.download(url, prefix, cache=True, loglevel=20, allow_404=False)

Download a file to disk.

Parameters:
  • url – the http(s) address of to the file to download

  • prefix – for the cache, to make it easier to find (cache files get a hash of the URL after the prefix)

  • cache – if True, and url is cached, do not download it again

  • loglevel – change to logging.DEBUG to only display the download message in ‘pmbootstrap log’, not in stdout. We use this when downloading many APKINDEX files at once, no point in showing a dozen messages.

  • allow_404 – do not raise an exception when the server responds with a 404 Not Found error. Only display a warning on stdout (no matter if loglevel is changed).

Returns:

path to the downloaded file in the cache or None on 404

pmb.helpers.http.retrieve(url, headers=None, allow_404=False)

Fetch the content of a URL and returns it as string.

Parameters:
  • url – the http(s) address of to the resource to fetch

  • headers – dict of HTTP headers to use

  • allow_404 – do not raise an exception when the server responds with a 404 Not Found error. Only display a warning

Returns:

str with the content of the response

pmb.helpers.http.retrieve_json(*args, **kwargs)

Fetch the contents of a URL, parse it as JSON and return it.

See retrieve() for the list of all parameters.

pmb.helpers.lint module

pmb.helpers.lint.check(pkgnames: Sequence[str])

Run apkbuild-lint on the supplied packages.

Parameters:

pkgnames – Names of the packages to lint

pmb.helpers.logging module

pmb.helpers.logging.add_verbose_log_level()

Add a new log level “verbose”, which is below “debug”.

Also monkeypatch logging, so it can be used with logging.verbose().

This function is based on work by Voitek Zylinski and sleepycal: https://stackoverflow.com/a/20602183 All stackoverflow user contributions are licensed as CC-BY-SA: https://creativecommons.org/licenses/by-sa/3.0/

pmb.helpers.logging.critical(msg: object, *args, **kwargs)
pmb.helpers.logging.debug(msg: object, *args, **kwargs)
pmb.helpers.logging.disable()
pmb.helpers.logging.error(msg: object, *args, **kwargs)
pmb.helpers.logging.fatal(msg: object, *args, **kwargs)
pmb.helpers.logging.info(msg: object, *args, **kwargs)
pmb.helpers.logging.init(logfile: Path, verbose: bool, details_to_stdout: bool = False)

Set log format and add the log file descriptor to logfd, add the verbose log level.

pmb.helpers.logging.log(level: int, msg: object, *args, **kwargs)
class pmb.helpers.logging.log_handler(details_to_stdout: bool = False, quiet: bool = False)

Bases: StreamHandler

Write to stdout and to the already opened log file.

emit(record)

Emit a record.

If a formatter is specified, it is used to format the record. The record is then written to the stream with a trailing newline. If exception information is present, it is formatted using traceback.print_exception and appended to the stream. If the stream has an ‘encoding’ attribute, it is used to determine how to do the output to the stream.

pmb.helpers.logging.logfd: TextIO
pmb.helpers.logging.verbose(msg: object, *args, **kwargs)
pmb.helpers.logging.warning(msg: object, *args, **kwargs)

pmb.helpers.mount module

pmb.helpers.mount.bind(source: Path, destination: Path, create_folders=True, umount=False)

Mount –bind a folder and create necessary directory structure.

Parameters:

umount – when destination is already a mount point, umount it first.

pmb.helpers.mount.bind_file(source: Path, destination: Path, create_folders=False)

Mount a file with the –bind option, and create the destination file, if necessary.

pmb.helpers.mount.ismount(folder: Path)

Ismount() implementation that works for mount –bind.

Workaround for: https://bugs.python.org/issue29707

pmb.helpers.mount.mount_device_rootfs(chroot_rootfs: Chroot) PurePath

Mount the device rootfs. :param chroot_rootfs: the chroot where the rootfs that will be

installed on the device has been created (e.g. “rootfs_qemu-amd64”)

Returns:

the mountpoint (relative to the native chroot)

pmb.helpers.mount.umount_all(folder: Path)

Umount all folders that are mounted inside a given folder.

pmb.helpers.mount.umount_all_list(prefix: Path, source: Path = PosixPath('/proc/mounts')) list[Path]

Parse /proc/mounts for all folders beginning with a prefix.

Source:

can be changed for testcases

Returns:

a list of folders that need to be umounted

pmb.helpers.other module

pmb.helpers.other.check_binfmt_misc()

Check if the ‘binfmt_misc’ module is loaded.

This is done by checking, if /proc/sys/fs/binfmt_misc/ exists. If it exists, then do nothing. Otherwise, load the module and mount binfmt_misc. If that fails as well, raise an exception pointing the user to the wiki.

pmb.helpers.other.check_grsec()

Check if the current kernel is based on the grsec patchset.

Also check if the chroot_deny_chmod option is enabled. Raise an exception in that case, with a link to the issue. Otherwise, do nothing.

pmb.helpers.other.folder_size(path: Path)

Run du to calculate the size of a folder.

(this is less code and faster than doing the same task in pure Python) This result is only approximatelly right, but good enough for pmbootstrap’s use case (#760).

Returns:

folder size in kilobytes

pmb.helpers.other.migrate_success(work: Path, version)
pmb.helpers.other.migrate_work_folder(args: PmbArgs)
pmb.helpers.other.validate_hostname(hostname)

Check whether the string is a valid hostname.

Check is performed according to <http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names>

pmb.helpers.package module

Functions that work with both pmaports and binary package repos.

See also:

  • pmb/helpers/pmaports.py (work with pmaports)

  • pmb/helpers/repo.py (work with binary package repos)

pmb.helpers.package.check_arch(pkgname, arch, binary=True)

Check if a package be built for a certain architecture, or is there a binary package for it.

Parameters:
  • pkgname – name of the package

  • arch – architecture to check against

  • binary – set to False to only look at the pmaports, not at binary packages

Returns:

True when the package can be built, or there is a binary package, False otherwise

pmb.helpers.package.remove_operators(package)

pmb.helpers.pkgrel_bump module

pmb.helpers.pkgrel_bump.auto(args: PmbArgs, dry=False)
Returns:

list of aport names, where the pkgrel needed to be changed

pmb.helpers.pkgrel_bump.auto_apkindex_package(args: PmbArgs, arch, aport, apk, dry=False)

Bump the pkgrel of a specific package if it is outdated in the given APKINDEX.

Parameters:
  • arch – the architecture, e.g. “armhf”

  • aport – parsed APKBUILD of the binary package’s origin: {“pkgname”: …, “pkgver”: …, “pkgrel”: …, …}

  • apk – information about the binary package from the APKINDEX: {“version”: …, “depends”: […], …}

  • dry – don’t modify the APKBUILD, just print the message

Returns:

True when there was an APKBUILD that needed to be changed.

pmb.helpers.pkgrel_bump.package(args: PmbArgs, pkgname, reason='', dry=False)

Increase the pkgrel in the APKBUILD of a specific package.

Parameters:
  • pkgname – name of the package

  • reason – string to display as reason why it was increased

  • dry – don’t modify the APKBUILD, just print the message

pmb.helpers.pmaports module

Functions that work with pmaports.

See also: - pmb/helpers/repo.py (work with binary package repos) - pmb/helpers/package.py (work with both)

pmb.helpers.pmaports.check_arches(arches, arch: Arch)

Check if building for a certain arch is allowed.

Parameters:
  • arches – list of all supported arches, as it can be found in the arch=”” line of APKBUILDS (including all, noarch, !arch, …). For example: [“x86_64”, “x86”, “!armhf”]

  • arch – the architecture to check for

Returns:

True when building is allowed, False otherwise

pmb.helpers.pmaports.find_optional(package: str) Path | None
pmb.helpers.pmaports.find_providers(provide)

Search for providers of the specified (virtual) package in pmaports.

Note: Currently only providers from a single APKBUILD are returned.

Parameters:

provide – the (virtual) package to search providers for

Returns:

tuple list (pkgname, apkbuild_pkg) with providers, sorted by provider_priority. The provider with the highest priority (which would be selected by default) comes first.

pmb.helpers.pmaports.get(pkgname, must_exist=True, subpackages=True, skip_extra_repos=False) dict[str, Any]
pmb.helpers.pmaports.get_channel_new(channel: str) str

Translate legacy channel names to the new ones.

Legacy names are still supported for compatibility with old branches (pmb#2015). :param channel: name as read from pmaports.cfg or channels.cfg, like “edge”, “v21.03” etc., or potentially a legacy name like “stable”.

Returns:

name in the new format, e.g. “edge” or “v21.03”

pmb.helpers.pmaports.get_list() Sequence[str]
Returns:

list of all pmaport pkgnames ([“hello-world”, …])

pmb.helpers.pmaports.get_repo(pkgname, must_exist=True) str | None

Get the repository folder of an aport.

Pkgname:

package name

Must_exist:

raise an exception when it can’t be found

Returns:

a string like “main”, “device”, “cross”, … or None when the aport could not be found

pmb.helpers.pmaports.guess_main(subpkgname) Path | None

Find the main package by assuming it is a prefix of the subpkgname.

We do that, because in some APKBUILDs the subpkgname=”” variable gets filled with a shell loop and the APKBUILD parser in pmbootstrap can’t parse this right. (Intentionally, we don’t want to implement a full shell parser.)

Parameters:

subpkgname – subpackage name (e.g. “u-boot-some-device”)

Returns:

  • full path to the aport, e.g.: “/home/user/code/pmbootstrap/aports/main/u-boot”

  • None when we couldn’t find a main package

pmb.helpers.pmaports.guess_main_dev(subpkgname) Path | None

Check if a package without “-dev” at the end exists in pmaports or not, and log the appropriate message.

Don’t call this function directly, use guess_main() instead.

Parameters:

subpkgname – subpackage name, must end in “-dev”

Returns:

full path to the pmaport or None

pmb.helpers.pmaports.require_bootstrap(arch, trigger_str)

Check if repo_bootstrap was done, if any is needed.

Parameters:
  • arch – for which architecture

  • trigger_str – message for the user to understand what caused this

pmb.helpers.pmaports.require_bootstrap_error(repo, arch, trigger_str)

Tell the user that they need to do repo_bootstrap, with some context.

Parameters:
  • repo – which repository

  • arch – for which architecture

  • trigger_str – message for the user to understand what caused this

pmb.helpers.repo module

Functions that work with binary package repos.

See also: - pmb/helpers/pmaports.py (work with pmaports) - pmb/helpers/package.py (work with both)

pmb.helpers.repo.alpine_apkindex_path(repo='main', arch: Arch | None = None)

Get the path to a specific Alpine APKINDEX file on disk and download it if necessary.

Parameters:
  • repo – Alpine repository name (e.g. “main”)

  • arch – Alpine architecture (e.g. “armhf”), defaults to native arch.

Returns:

full path to the APKINDEX file

pmb.helpers.repo.apkindex_files(arch: Arch | None = None, user_repository=True, exclude_mirrors: list[str] = []) list[Path]

Get a list of outside paths to all resolved APKINDEX.tar.gz files for a specific arch.

Parameters:
  • arch – defaults to native

  • user_repository – add path to index of locally built packages

  • exclude_mirrors – list of mirrors to exclude (e.g. [“alpine”, “pmaports”])

Returns:

list of absolute APKINDEX.tar.gz file paths

pmb.helpers.repo.apkindex_hash(url: str, length: int = 8) Path

Generate the hash that APK adds to the APKINDEX and apk packages in its apk cache folder.

It is the “12345678” part in this example: “APKINDEX.12345678.tar.gz”.

Parameters:

length – The length of the hash in the output file.

See also: official implementation in apk-tools: <https://git.alpinelinux.org/cgit/apk-tools/>

blob.c: apk_blob_push_hexdump(), “const char \*xd” apk_defines.h: APK_CACHE_CSUM_BYTES database.c: apk_repo_format_cache_index()

pmb.helpers.repo_missing module

pmb.helpers.repo_missing.filter_aport_packages(pkgnames)

Create a subset of pkgnames where each one has an aport.

Parameters:
  • arch – architecture (e.g. “armhf”)

  • pkgnames – list of package names (e.g. [“hello-world”, “test12”])

Returns:

subset of pkgnames (e.g. [“hello-world”])

pmb.helpers.repo_missing.filter_arch_packages(arch, pkgnames)

Create a subset of pkgnames with packages removed that can not be built for a certain arch.

Parameters:
  • arch – architecture (e.g. “armhf”)

  • pkgnames – list of package names (e.g. [“hello-world”, “test12”])

Returns:

subset of pkgnames (e.g. [“hello-world”])

pmb.helpers.repo_missing.filter_missing_packages(arch, pkgnames)

Create a subset of pkgnames with missing or outdated binary packages.

Parameters:
  • arch – architecture (e.g. “armhf”)

  • pkgnames – list of package names (e.g. [“hello-world”, “test12”])

Returns:

subset of pkgnames (e.g. [“hello-world”])

pmb.helpers.repo_missing.generate(arch, overview, pkgname=None, built=False)

Get packages that need to be built, with all their dependencies.

Parameters:
  • arch – architecture (e.g. “armhf”)

  • pkgname – only look at a specific package

  • built – include packages that have already been built

Returns:

a list like the following: [{“pkgname”: “hello-world”, “repo”: “main”, “version”: “1-r4”}, {“pkgname”: “package-depending-on-hello-world”, “version”: “0.5-r0”, “repo”: “main”}]

pmb.helpers.repo_missing.generate_output_format(arch, pkgnames)

Generate the detailed output format.

Parameters:
  • arch – architecture

  • pkgnames – list of package names that should be in the output, e.g.: [“hello-world”, “pkg-depending-on-hello-world”] :returns: a list like the following: [{“pkgname”: “hello-world”, “repo”: “main”, “version”: “1-r4”, “depends”: []}, {“pkgname”: “pkg-depending-on-hello-world”, “version”: “0.5-r0”, “repo”: “main”, “depends”: [“hello-world”]}]

pmb.helpers.repo_missing.get_relevant_packages(arch, pkgname=None, built=False)

Get all packages that can be built for the architecture in question.

Parameters:
  • arch – architecture (e.g. “armhf”)

  • pkgname – only look at a specific package (and its dependencies)

  • built – include packages that have already been built

Returns:

an alphabetically sorted list of pkgnames, e.g.: [“devicepkg-dev”, “hello-world”, “osk-sdl”]

pmb.helpers.run module

pmb.helpers.run.root(cmd: Sequence[Path | str], working_dir=None, output='log', output_return=False, check=None, env={})

Run a command on the host system as root, with sudo or doas.

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.helpers.run.user(cmd: Sequence[Path | str], working_dir: Path | None = None, output: str = 'log', output_return: bool = False, check: bool | None = None, env: dict[str, Path | str] = {}, sudo: bool = False) str | int | Popen

Run a command on the host system as user.

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.helpers.run.user_output(cmd: Sequence[Path | str], working_dir: Path | None = None, output: str = 'log', check: bool | None = None, env: dict[str, Path | str] = {}, sudo: bool = False) str

pmb.helpers.run_core module

pmb.helpers.run_core.add_proxy_env_vars(env)

Add proxy environment variables from host to the environment of the command we are running.

Parameters:

env – dict of environment variables, it will be extended with all of the proxy env vars that are set on the host

pmb.helpers.run_core.background(cmd, working_dir=None)

Run a subprocess in background and redirect its output to the log.

pmb.helpers.run_core.check_return_code(code, log_message)

Check the return code of a command.

Parameters:
  • code – exit code to check

  • log_message – simplified and more readable form of the command, e.g. “(native) % echo test” instead of the full command with entering the chroot and more escaping

Raises:

RuntimeError – when the code indicates that the command failed

pmb.helpers.run_core.core(log_message, cmd, working_dir=None, output='log', output_return=False, check=None, sudo=False, disable_timeout=False)

Run a command and create a log entry.

This is a low level function not meant to be used directly. Use one of the following instead: pmb.helpers.run.user(), pmb.helpers.run.root(), pmb.chroot.user(), pmb.chroot.root()

Parameters:
  • log_message – simplified and more readable form of the command, e.g. “(native) % echo test” instead of the full command with entering the chroot and more escaping

  • cmd – command as list, e.g. [“echo”, “string with spaces”]

  • working_dir – path in host system where the command should run

  • output

    where to write the output (stdout and stderr) of the

    process. We almost always write to the log file, which can be read with “pmbootstrap log” (output values: “log”, “stdout”, “interactive”, “background”), so it’s easy to trace what pmbootstrap does.

    The exceptions are “tui” (text-based user interface), where it does not make sense to write to the log file (think of ncurses UIs, such as “menuconfig”) and “pipe” where the output is written to a pipe for manual asynchronous consumption by the caller.

    When the output is not set to “interactive”, “tui”, “background” or “pipe”, we kill the process if it does not output anything for 5 minutes (time can be set with “pmbootstrap –timeout”).

    The table below shows all possible values along with their properties. “wait” indicates that we wait for the process to complete.

    output value

    timeout

    out to log

    out to stdout

    wait

    pass stdin

    ”log”

    x

    x

    x

    ”stdout”

    x

    x

    x

    x

    ”interactive”

    x

    x

    x

    x

    ”tui”

    x

    x

    x

    ”background”

    x

    ”pipe”

    ”null”

  • output_return – in addition to writing the program’s output to the destinations above in real time, write to a buffer and return it as string when the command has completed. This is not possible when output is “background”, “pipe” or “tui”.

  • check – an exception will be raised when the command’s return code is not 0. Set this to False to disable the check. This parameter can not be used when the output is “background” or “pipe”.

  • sudo – use sudo to kill the process when it hits the timeout.

Returns:

  • program’s return code (default)

  • subprocess.Popen instance (output is “background” or “pipe”)

  • the program’s entire output (output_return is True)

pmb.helpers.run_core.flat_cmd(cmds: Sequence[Sequence[Path | str]], working_dir: Path | None = None, env: dict[str, Path | str] = {})

Convert a shell command passed as list into a flat shell string with proper escaping.

Parameters:
  • cmds – list of commands as list, e.g. [“echo”, “string with spaces”]

  • working_dir – when set, prepend “cd …;” to execute the command in the given working directory

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

Returns:

the flat string, e.g. echo ‘string with spaces’ cd /home/pmos;echo ‘string with spaces’

pmb.helpers.run_core.foreground_pipe(cmd, working_dir=None, output_to_stdout=False, output_return=False, output_log=True, output_timeout=True, sudo=False, stdin=None)

Run a subprocess in foreground with redirected output.

Optionally kill it after being silent for too long.

Parameters:
  • cmd – command as list, e.g. [“echo”, “string with spaces”]

  • working_dir – path in host system where the command should run

  • output_to_stdout – copy all output to pmbootstrap’s stdout

  • output_return – return the output of the whole program

  • output_timeout – kill the process when it doesn’t print any output after a certain time (configured with –timeout) and raise a RuntimeError exception

  • sudo – use sudo to kill the process when it hits the timeout

Returns:

(code, output) * code: return code of the program * output: “” * output: full program output string (output_return is True)

pmb.helpers.run_core.foreground_tui(cmd, working_dir=None)

Run a subprocess in foreground without redirecting any of its output.

This is the only way text-based user interfaces (ncurses programs like vim, nano or the kernel’s menuconfig) work properly.

pmb.helpers.run_core.kill_command(pid, sudo)

Kill a command process and recursively kill its child processes.

Parameters:
  • pid – process id that will be killed

  • sudo – use sudo to kill the process

pmb.helpers.run_core.kill_process_tree(pid, ppids, sudo)

Recursively kill a pid and its child processes.

Parameters:
  • pid – process id that will be killed

  • ppids – list of process id and parent process id tuples (pid, ppid)

  • sudo – use sudo to kill the process

pmb.helpers.run_core.pipe(cmd, working_dir=None)

Run a subprocess in background and redirect its output to a pipe.

pmb.helpers.run_core.pipe_read(process, output_to_stdout=False, output_log=True, output_return=False, output_return_buffer=False)

Read all output from a subprocess, copy it to the log and optionally stdout and a buffer variable.

This is only meant to be called by foreground_pipe() below.

Parameters:
  • process – subprocess.Popen instance

  • output_to_stdout – copy all output to pmbootstrap’s stdout

  • output_return – when set to True, output_return_buffer will be extended

  • output_return_buffer – list of bytes that gets extended with the current output in case output_return is True.

pmb.helpers.run_core.sanity_checks(output='log', output_return=False, check=None)

Raise an exception if the parameters passed to core() don’t make sense.

(all parameters are described in core() below).

pmb.helpers.run_core.sudo_timer_iterate()

Run sudo -v and schedule a new timer to repeat the same.

pmb.helpers.run_core.sudo_timer_start()

Start a timer to call sudo -v periodically, so that the password is only needed once.

pmb.helpers.status module

pmb.helpers.status.print_channel(config: Config) None
pmb.helpers.status.print_device(config: Config) None
pmb.helpers.status.print_status(args: PmbArgs) None
Parameters:

details – if True, print each passing check instead of a summary

Returns:

True if all checks passed, False otherwise

pmb.helpers.status.print_status_line(key: str, value: str)
pmb.helpers.status.print_systemd(config: Config) None
pmb.helpers.status.print_ui(config: Config) None

pmb.helpers.ui module

pmb.helpers.ui.check_option(ui, option, skip_extra_repos=False)

Check if an option, such as pmb:systemd, is inside an UI’s APKBUILD.

pmb.helpers.ui.list_ui(arch)

Get all UIs, for which aports are available with their description.

Parameters:

arch – device architecture, for which the UIs must be available

Returns:

[(“none”, “No graphical…”), (“weston”, “Wayland reference…”)]

Module contents