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 (“”)
- pmb.helpers.file.symlink(file: Path, link: Path)¶
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…”)]