Drop default --noconfirm (opt-in via --noconfirm), fix --noremovemake, forward pacman argv intact for -R/-D/-F/-T/-U, deepen PKGBUILD review, show an install plan before building, and add shellcheck CI plus unit tests. Co-authored-by: Frank Vitrano <WHC2006@users.noreply.github.com>
154 lines
3.7 KiB
Bash
154 lines
3.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Dependency resolution from .SRCINFO / makepkg --printsrcinfo
|
|
|
|
# Parse srcinfo from directory into globals via stdout lines:
|
|
# pkgbase|NAME
|
|
# pkgname|NAME
|
|
# depend|DEP
|
|
# makedepend|DEP
|
|
# checkdepend|DEP
|
|
srcinfo_dump() {
|
|
local dir=$1
|
|
(
|
|
cd "$dir" || exit 1
|
|
${MIAUR_MAKEPKG} --printsrcinfo 2>/dev/null
|
|
) | awk '
|
|
/^pkgbase = / { print "pkgbase|" $3 }
|
|
/^[[:space:]]*pkgname = / { print "pkgname|" $3 }
|
|
/^[[:space:]]*depends = / { print "depend|" $3 }
|
|
/^[[:space:]]*makedepends = / { print "makedepend|" $3 }
|
|
/^[[:space:]]*checkdepends = / { print "checkdepend|" $3 }
|
|
'
|
|
}
|
|
|
|
# Returns 0 if dep is satisfied (installed or provided by installed pkg)
|
|
dep_satisfied() {
|
|
local _name
|
|
_name=$(dep_name "$1")
|
|
# pacman -T returns unsatisfied deps; empty means all ok
|
|
local out
|
|
out=$(pacman -T "$1" 2>/dev/null) || true
|
|
[[ -z $out ]]
|
|
}
|
|
|
|
# Is package available in sync repos?
|
|
repo_has_pkg() {
|
|
pacman -Si "$1" &>/dev/null
|
|
}
|
|
|
|
# Resolve whether a dep name is in AUR (not in repos, or --aur mode)
|
|
# Sets: REPO_DEPS[] AUR_DEPS[] (caller-managed arrays passed by name)
|
|
# resolve_one_dep name -> echoes "repo:name" or "aur:name" or "ok" or "missing:name"
|
|
resolve_one_dep() {
|
|
local raw=$1
|
|
local name
|
|
name=$(dep_name "$raw")
|
|
if dep_satisfied "$raw"; then
|
|
echo "ok"
|
|
return 0
|
|
fi
|
|
if [[ ${MIAUR_MODE:-} != aur ]] && repo_has_pkg "$name"; then
|
|
echo "repo:$name"
|
|
return 0
|
|
fi
|
|
if [[ ${MIAUR_MODE:-} != repo ]] && aur_exists "$name"; then
|
|
echo "aur:$name"
|
|
return 0
|
|
fi
|
|
echo "missing:$name"
|
|
}
|
|
|
|
# Collect all deps for a cloned package dir into named arrays via stdout
|
|
# Format lines: repo|pkg / aur|pkg / missing|pkg
|
|
collect_deps_for_dir() {
|
|
local dir=$1
|
|
local include_make=${2:-1}
|
|
local include_check=${3:-1}
|
|
local line kind val
|
|
declare -A seen=()
|
|
while IFS= read -r line; do
|
|
kind=${line%%|*}
|
|
val=${line#*|}
|
|
case "$kind" in
|
|
depend) ;;
|
|
makedepend) [[ $include_make -eq 1 ]] || continue ;;
|
|
checkdepend) [[ $include_check -eq 1 ]] || continue ;;
|
|
*) continue ;;
|
|
esac
|
|
local name
|
|
name=$(dep_name "$val")
|
|
[[ -n ${seen[$name]+x} ]] && continue
|
|
seen[$name]=1
|
|
local r
|
|
r=$(resolve_one_dep "$val")
|
|
case "$r" in
|
|
ok) ;;
|
|
repo:*) echo "repo|${r#repo:}" ;;
|
|
aur:*) echo "aur|${r#aur:}" ;;
|
|
missing:*) echo "missing|${r#missing:}" ;;
|
|
esac
|
|
done < <(srcinfo_dump "$dir")
|
|
}
|
|
|
|
# Recursively expand AUR deps for a list of package names.
|
|
# Prints ordered AUR package names (dependencies first).
|
|
# Uses DFS + topo-ish order.
|
|
aur_resolve_order() {
|
|
local -a roots=("$@")
|
|
declare -A visiting=() visited=()
|
|
local -a order=()
|
|
|
|
_visit() {
|
|
local pkg=$1
|
|
[[ -n ${visited[$pkg]+x} ]] && return 0
|
|
if [[ -n ${visiting[$pkg]+x} ]]; then
|
|
warn "Dependency cycle detected at: $pkg"
|
|
return 0
|
|
fi
|
|
visiting[$pkg]=1
|
|
local dir
|
|
dir=$(aur_clone "$pkg") || die "failed to fetch dependency: $pkg"
|
|
local line
|
|
while IFS= read -r line; do
|
|
case "$line" in
|
|
aur\|*)
|
|
_visit "${line#aur|}"
|
|
;;
|
|
missing\|*)
|
|
die "unable to resolve dependency ${line#missing|} required by $pkg"
|
|
;;
|
|
esac
|
|
done < <(collect_deps_for_dir "$dir" 1 1)
|
|
unset 'visiting[$pkg]'
|
|
visited[$pkg]=1
|
|
order+=("$pkg")
|
|
}
|
|
|
|
local r
|
|
for r in "${roots[@]}"; do
|
|
_visit "$r"
|
|
done
|
|
printf '%s\n' "${order[@]}"
|
|
}
|
|
|
|
# Install repo packages as deps
|
|
install_repo_deps() {
|
|
local -a pkgs=("$@")
|
|
[[ ${#pkgs[@]} -eq 0 ]] && return 0
|
|
# Dedup
|
|
local -A u=()
|
|
local p
|
|
local -a list=()
|
|
for p in "${pkgs[@]}"; do
|
|
[[ -n ${u[$p]+x} ]] && continue
|
|
u[$p]=1
|
|
is_pkg_installed "$p" && continue
|
|
list+=("$p")
|
|
done
|
|
[[ ${#list[@]} -eq 0 ]] && return 0
|
|
msg "Installing repository dependencies: ${list[*]}"
|
|
local -a conf=()
|
|
mapfile -t conf < <(pac_noconfirm_args)
|
|
as_root ${MIAUR_PACMAN} -S --needed --asdeps "${conf[@]}" "${list[@]}"
|
|
}
|