#!/usr/bin/env bash # Build and install AUR packages # Build package in dir. install=1 to install after build. # asdeps=1 to mark as dependency. build_pkg() { local dir=$1 local do_install=${2:-1} local asdeps=${3:-0} local name name=$(basename "$dir") msg "Building $name..." ( cd "$dir" || exit 1 # Clear previous package files to avoid installing stale ones rm -f ./*.pkg.tar.* 2>/dev/null || true local -a mflags=() # shellcheck disable=SC2206 mflags=(${MIAUR_MFLAGS}) # If MFLAGS contains -si we handle install ourselves more carefully local -a clean_flags=() local f for f in "${mflags[@]}"; do case "$f" in -i | --install | -si | -is) ;; *) clean_flags+=("$f") ;; esac done # Always sync deps for repo side via makepkg -s when needed ${MIAUR_MAKEPKG} -s --noconfirm "${clean_flags[@]}" || exit 1 ) || die "build failed: $name" if [[ $do_install -eq 1 ]]; then local -a pkgs=() mapfile -t pkgs < <(find "$dir" -maxdepth 1 -type f \( -name '*.pkg.tar.zst' -o -name '*.pkg.tar.xz' -o -name '*.pkg.tar.gz' \) ! -name '*-debug-*' | sort) [[ ${#pkgs[@]} -eq 0 ]] && die "no build artifacts found: $name" msg "Installing $name..." local -a uflags=(-U --noconfirm) [[ $asdeps -eq 1 ]] && uflags+=(--asdeps) as_root ${MIAUR_PACMAN} "${uflags[@]}" "${pkgs[@]}" || die "installation failed: $name" fi if [[ ${MIAUR_CLEANAFTER:-0} -eq 1 ]]; then msg2 "Cleaning build directory: $dir" rm -rf "$dir" fi } # Full install pipeline for AUR package names (and their AUR deps) # Targets are package names. install_aur_packages() { local -a targets=("$@") [[ ${#targets[@]} -eq 0 ]] && return 0 need_cmd curl jq git makepkg pacman sudoloop_start msg "Resolving dependencies..." local -a order=() mapfile -t order < <(aur_resolve_order "${targets[@]}") [[ ${#order[@]} -eq 0 ]] && die "no packages to install" # Collect all repo deps across the graph local -a repo_deps=() local pkg dir line declare -A repo_seen=() for pkg in "${order[@]}"; do dir=$(pkg_clone_dir "$pkg") [[ -d $dir ]] || dir=$(aur_clone "$pkg") while IFS= read -r line; do case "$line" in repo\|*) local rn=${line#repo|} [[ -n ${repo_seen[$rn]+x} ]] && continue repo_seen[$rn]=1 repo_deps+=("$rn") ;; esac done < <(collect_deps_for_dir "$dir" 1 1) done install_repo_deps "${repo_deps[@]}" # Review all packages first (like paru) local -a build_list=() for pkg in "${order[@]}"; do dir=$(pkg_clone_dir "$pkg") [[ -d $dir ]] || dir=$(aur_clone "$pkg") local rc=0 review_pkgbuild "$dir" "$pkg" || rc=$? if [[ $rc -eq 1 ]]; then die "installation cancelled" elif [[ $rc -eq 2 ]]; then warn "Skipping $pkg" continue fi build_list+=("$pkg") done [[ ${#build_list[@]} -eq 0 ]] && die "no packages to build" # Explicit install targets (deps marked --asdeps) declare -A is_target=() for pkg in "${targets[@]}"; do is_target[$pkg]=1 done # Track make deps for optional removal (names from srcinfo) local -a make_pkgs=() declare -A make_seen=() if [[ ${MIAUR_REMOVEMAKE:-0} -eq 1 ]]; then for pkg in "${build_list[@]}"; do dir=$(pkg_clone_dir "$pkg") while IFS= read -r line; do case "$line" in makedepend\|*) local mn mn=$(dep_name "${line#makedepend|}") [[ -n ${is_target[$mn]+x} ]] && continue [[ -n ${make_seen[$mn]+x} ]] && continue make_seen[$mn]=1 make_pkgs+=("$mn") ;; esac done < <(srcinfo_dump "$dir") done fi for pkg in "${build_list[@]}"; do dir=$(pkg_clone_dir "$pkg") local asdeps=0 [[ -z ${is_target[$pkg]+x} ]] && asdeps=1 # Skip if already up to date if is_pkg_installed "$pkg"; then local localver aurver localver=$(pkg_local_version "$pkg") aurver=$(jq -r '.Version // empty' <<<"$(aur_info_json "$pkg")" 2>/dev/null || true) if [[ -n $aurver && $localver == "$aurver" && -z ${is_target[$pkg]+x} ]]; then msg2 "$pkg is up to date ($localver)" continue fi fi build_pkg "$dir" 1 "$asdeps" done # Remove make depends that were installed as deps and not needed if [[ ${MIAUR_REMOVEMAKE:-0} -eq 1 && ${#make_pkgs[@]} -gt 0 ]]; then local -a to_rm=() local m for m in "${make_pkgs[@]}"; do # Only remove if installed as dependency and not required if pacman -Qdtq 2>/dev/null | grep -qx "$m"; then to_rm+=("$m") fi done if [[ ${#to_rm[@]} -gt 0 ]]; then msg "Removing make dependencies: ${to_rm[*]}" as_root ${MIAUR_PACMAN} -Rns --noconfirm "${to_rm[@]}" || warn "failed to remove make dependencies" fi fi sudoloop_stop msg "Done" } # Build from local directories containing PKGBUILD build_local_dirs() { local do_install=${1:-0} shift local -a dirs=("$@") local d for d in "${dirs[@]}"; do [[ -d $d ]] || die "directory does not exist: $d" [[ -f $d/PKGBUILD ]] || die "PKGBUILD not found: $d" # Resolve AUR deps of local pkgbuild local -a aur_deps=() local line while IFS= read -r line; do case "$line" in aur\|*) aur_deps+=("${line#aur|}") ;; missing\|*) die "unable to resolve dependency: ${line#missing|}" ;; repo\|*) ;; esac done < <(collect_deps_for_dir "$d" 1 1) if [[ ${#aur_deps[@]} -gt 0 ]]; then install_aur_packages "${aur_deps[@]}" fi # Install repo deps local -a rd=() while IFS= read -r line; do case "$line" in repo\|*) rd+=("${line#repo|}") ;; esac done < <(collect_deps_for_dir "$d" 1 1) install_repo_deps "${rd[@]}" review_pkgbuild "$d" "$(basename "$d")" || die "cancelled" build_pkg "$d" "$do_install" 0 done }