# Host package handling: maps the logical names in distroPackages.txt to # apt or dnf packages, reports which are missing, and installs them. # Sourced after lib/common.sh. JOEY_PACKAGE_MAP="$JOEY_INSTALLER/distroPackages.txt" # distroFamily -- print apt, dnf or unknown. distroFamily() { local id="" local like="" if [ -r /etc/os-release ]; then id="$(. /etc/os-release && printf '%s' "${ID:-}")" like="$(. /etc/os-release && printf '%s' "${ID_LIKE:-}")" fi case " $id $like " in *" debian "*|*" ubuntu "*) printf 'apt\n' ;; *" fedora "*|*" rhel "*|*" centos "*|*" rocky "*) printf 'dnf\n' ;; *) printf 'unknown\n' ;; esac } # distroPackageNames LOGICAL... -- print the real package names, one per line. distroPackageNames() { local family local column local name local row family="$(distroFamily)" case "$family" in apt) column=2 ;; dnf) column=3 ;; *) die "unsupported Linux distribution (need apt or dnf); install host packages by hand: $*" ;; esac for name in "$@"; do row="$(awk -v n="$name" -v c="$column" '$1 == n { print $c }' "$JOEY_PACKAGE_MAP")" [ -n "$row" ] || die "no entry for host dependency '$name' in distroPackages.txt" [ "$row" != "-" ] || die "host dependency '$name' has no $family package" printf '%s\n' "${row//,/$'\n'}" done } # distroMissing PACKAGE... -- print the packages that are not installed. distroMissing() { local family local pkg local native="" family="$(distroFamily)" [ "$family" = "apt" ] && native="$(dpkg --print-architecture)" for pkg in "$@"; do case "$family" in apt) aptInstalled "$pkg" "$native" || printf '%s\n' "$pkg" ;; dnf) rpm -q "$pkg" >/dev/null 2>&1 || printf '%s\n' "$pkg" ;; esac done } # aptInstalled PACKAGE NATIVE-ARCH -- PACKAGE is installed for this machine. # dpkg-query prints one line per architecture present (libc6 on a system # with i386 multiarch has two), so look for a native or arch-all line. aptInstalled() { local arch local status while read -r arch status; do if [ "$status" = "installed" ] && { [ "$arch" = "$2" ] || [ "$arch" = "all" ]; }; then return 0 fi done <<< "$(dpkg-query -W -f='${Architecture} ${db:Status-Status}\n' "$1" 2>/dev/null || true)" return 1 } # distroInstall PACKAGE... -- install with one sudo call (none when already # root, as in containers and CI, which often have no sudo at all). distroInstall() { local family local yes=() local asRoot=() [ $# -gt 0 ] || return 0 family="$(distroFamily)" [ "$JOEY_ASSUME_YES" = "1" ] && yes=(-y) [ "$(id -u)" = "0" ] || asRoot=(sudo) info "installing host packages: $*" case "$family" in apt) "${asRoot[@]}" apt-get update "${asRoot[@]}" env DEBIAN_FRONTEND=noninteractive apt-get install "${yes[@]}" --no-install-recommends "$@" ;; dnf) "${asRoot[@]}" dnf install "${yes[@]}" "$@" ;; *) die "unsupported Linux distribution; install by hand: $*" ;; esac }