first upload
This commit is contained in:
+116
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
# AUR RPC helpers (v5) using curl + jq
|
||||
|
||||
aur_rpc_get() {
|
||||
local url=$1
|
||||
local curl_bin
|
||||
curl_bin=$(resolve_curl)
|
||||
"$curl_bin" -fsSL --connect-timeout 15 --max-time 60 "$url"
|
||||
}
|
||||
|
||||
# Search AUR; prints: name|version|votes|popularity|desc (one per line)
|
||||
aur_search() {
|
||||
local query=$1
|
||||
local by=${2:-$MIAUR_SEARCHBY}
|
||||
local encoded
|
||||
encoded=$(printf '%s' "$query" | jq -sRr @uri)
|
||||
local json
|
||||
json=$(aur_rpc_get "${MIAUR_AURRPC}/search/${encoded}?by=${by}") || return 1
|
||||
local sort=${MIAUR_SORTBY:-votes}
|
||||
local jq_sort
|
||||
case "$sort" in
|
||||
votes) jq_sort='sort_by(.NumVotes) | reverse' ;;
|
||||
popularity) jq_sort='sort_by(.Popularity) | reverse' ;;
|
||||
name) jq_sort='sort_by(.Name)' ;;
|
||||
*) jq_sort='sort_by(.NumVotes) | reverse' ;;
|
||||
esac
|
||||
jq -r --argjson err 0 "
|
||||
if .type == \"error\" then empty
|
||||
else (.results // []) | ${jq_sort} | .[] |
|
||||
[.Name, .Version, (.NumVotes|tostring), (.Popularity|tostring), (.Description // \"\")] | join(\"|\")
|
||||
end
|
||||
" <<<"$json"
|
||||
}
|
||||
|
||||
# Info for one package; prints JSON object or empty
|
||||
aur_info_json() {
|
||||
local name=$1
|
||||
local encoded
|
||||
encoded=$(printf '%s' "$name" | jq -sRr @uri)
|
||||
local json
|
||||
json=$(aur_rpc_get "${MIAUR_AURRPC}/info?arg[]=${encoded}") || return 1
|
||||
jq -c '.results[0] // empty' <<<"$json"
|
||||
}
|
||||
|
||||
# Multi-info: args are package names. Prints JSON array of results.
|
||||
aur_multiinfo_json() {
|
||||
local args=()
|
||||
local n
|
||||
for n in "$@"; do
|
||||
args+=(--data-urlencode "arg[]=${n}")
|
||||
done
|
||||
[[ ${#args[@]} -eq 0 ]] && { echo '[]'; return 0; }
|
||||
local json
|
||||
local curl_bin
|
||||
curl_bin=$(resolve_curl)
|
||||
json=$("$curl_bin" -fsSL --connect-timeout 15 --max-time 60 -G "${MIAUR_AURRPC}/info" "${args[@]}") || return 1
|
||||
jq -c '.results // []' <<<"$json"
|
||||
}
|
||||
|
||||
# Check if package exists on AUR (exit 0 if yes)
|
||||
aur_exists() {
|
||||
local j
|
||||
j=$(aur_info_json "$1") || return 1
|
||||
[[ -n $j && $j != null ]]
|
||||
}
|
||||
|
||||
# Print human-readable info for a package (like pacman -Si for AUR)
|
||||
aur_print_info() {
|
||||
local name=$1
|
||||
local j
|
||||
j=$(aur_info_json "$name") || return 1
|
||||
[[ -z $j || $j == null ]] && return 1
|
||||
jq -r '
|
||||
"Repository : aur",
|
||||
"Name : \(.Name)",
|
||||
"Version : \(.Version)",
|
||||
"Description : \(.Description // "")",
|
||||
"URL : \(.URL // "")",
|
||||
"AUR URL : https://aur.archlinux.org/packages/\(.Name)",
|
||||
"Groups : \((.Groups // []) | join(" "))",
|
||||
"Depends On : \((.Depends // []) | join(" "))",
|
||||
"Make Depends : \((.MakeDepends // []) | join(" "))",
|
||||
"Check Depends : \((.CheckDepends // []) | join(" "))",
|
||||
"Optional Deps : \((.OptDepends // []) | join(" "))",
|
||||
"Provides : \((.Provides // []) | join(" "))",
|
||||
"Conflicts With : \((.Conflicts // []) | join(" "))",
|
||||
"Replaces : \((.Replaces // []) | join(" "))",
|
||||
"Maintainer : \(.Maintainer // "(orphan)")",
|
||||
"Votes : \(.NumVotes)",
|
||||
"Popularity : \(.Popularity)",
|
||||
"Last Modified : \(.LastModified)",
|
||||
"Out Of Date : \(if .OutOfDate then (.OutOfDate|tostring) else "No" end)"
|
||||
' <<<"$j"
|
||||
}
|
||||
|
||||
# Print search line for AUR result: aur/name version (votes) desc
|
||||
aur_format_search_line() {
|
||||
local name=$1 ver=$2 votes=$3 pop=$4 desc=$5
|
||||
local installed=
|
||||
if is_pkg_installed "$name"; then
|
||||
local localver
|
||||
localver=$(pkg_local_version "$name")
|
||||
if [[ $localver == "$ver" ]]; then
|
||||
installed=" ${C_GREEN}[installed]${C_RESET}"
|
||||
else
|
||||
installed=" ${C_YELLOW}[installed: ${localver}]${C_RESET}"
|
||||
fi
|
||||
fi
|
||||
printf '%saur/%s%s %s%s (%s)%s\n %s\n' \
|
||||
"${C_BOLD}${C_CYAN}" "$name" "${C_RESET}" \
|
||||
"${C_BOLD}${C_GREEN}${ver}${C_RESET}" \
|
||||
"$installed" \
|
||||
"$votes" \
|
||||
"" \
|
||||
"$desc"
|
||||
}
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
#!/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
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env bash
|
||||
# CLI parsing — paru-like short option clusters
|
||||
|
||||
# Globals set by parse_args
|
||||
OP= # S Q R G B P D F T U none interactive
|
||||
OP_REFRESH=0 # y
|
||||
OP_UPGRADE=0 # u
|
||||
OP_SEARCH=0 # s (count)
|
||||
OP_INFO=0 # i
|
||||
OP_CLEAN=0 # c
|
||||
OP_AUR_ONLY=0 # a (with S/Q)
|
||||
OP_PRINT=0 # -p for -G
|
||||
OP_BUILD_INSTALL=0 # -i for -B
|
||||
TARGETS=()
|
||||
PACMAN_EXTRA=() # leftover short flags for pacman passthrough
|
||||
DO_PASSTHRU=0
|
||||
|
||||
print_help() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
miaur
|
||||
miaur <operation> [...]
|
||||
miaur <search terms>
|
||||
|
||||
miaur is a pure-shell AUR helper with paru-like everyday commands.
|
||||
|
||||
Pacman operations extended with AUR support:
|
||||
miaur {-h --help}
|
||||
miaur {-V --version}
|
||||
miaur {-Q --query} [options] [packages]
|
||||
miaur {-R --remove} [options] <packages>
|
||||
miaur {-S --sync} [options] [packages]
|
||||
miaur {-U --upgrade} [options] <files>
|
||||
|
||||
Additional operations:
|
||||
miaur {-G --getpkgbuild} [packages]
|
||||
miaur {-B --build} [directories]
|
||||
|
||||
With no arguments, miaur runs 'miaur -Syu'.
|
||||
|
||||
Common commands:
|
||||
miaur -Syu Upgrade repository and AUR packages
|
||||
miaur -Sua Upgrade AUR packages only
|
||||
miaur -S <package> Install from a repository or the AUR
|
||||
miaur -Ss <query> Search packages
|
||||
miaur -Si <package> Show package information
|
||||
miaur -Qua List available AUR upgrades
|
||||
miaur -G <package> Download a PKGBUILD
|
||||
miaur -Gp <package> Print a PKGBUILD
|
||||
miaur -Bi . Build and install a local PKGBUILD
|
||||
|
||||
Options:
|
||||
-a, --aur Assume targets are from the AUR
|
||||
--repo Assume targets are from repositories
|
||||
--skipreview Skip PKGBUILD review
|
||||
--cleanafter Remove build sources after installation
|
||||
--[no]removemake Remove make dependencies after installation
|
||||
--bottomup Show AUR results first
|
||||
--topdown Show repository results first (default)
|
||||
--clonedir <path> Set the PKGBUILD clone directory
|
||||
--mflags <flags> Pass additional flags to makepkg
|
||||
--sudoloop Keep sudo credentials alive (default)
|
||||
--nosudoloop Disable the sudo keep-alive loop
|
||||
EOF
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
OP=S
|
||||
OP_REFRESH=1
|
||||
OP_UPGRADE=1
|
||||
return 0
|
||||
fi
|
||||
|
||||
# No leading dash → interactive search
|
||||
if [[ $1 != -* ]]; then
|
||||
OP=interactive
|
||||
TARGETS=("$@")
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a raw=("$@")
|
||||
local i=0
|
||||
while ((i < ${#raw[@]})); do
|
||||
local arg=${raw[$i]}
|
||||
case "$arg" in
|
||||
-h | --help)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
-V | --version)
|
||||
printf 'miaur v%s\n' "$MIAUR_VERSION"
|
||||
exit 0
|
||||
;;
|
||||
--aur)
|
||||
OP_AUR_ONLY=1
|
||||
MIAUR_MODE=aur
|
||||
;;
|
||||
--repo)
|
||||
MIAUR_MODE=repo
|
||||
;;
|
||||
--skipreview) MIAUR_SKIPREVIEW=1 ;;
|
||||
--review) MIAUR_SKIPREVIEW=0 ;;
|
||||
--cleanafter) MIAUR_CLEANAFTER=1 ;;
|
||||
--nocleanafter) MIAUR_CLEANAFTER=0 ;;
|
||||
--removemake) MIAUR_REMOVEMAKE=1 ;;
|
||||
--noremovermake) MIAUR_REMOVEMAKE=0 ;;
|
||||
--bottomup) MIAUR_BOTTOMUP=1 ;;
|
||||
--topdown) MIAUR_BOTTOMUP=0 ;;
|
||||
--sudoloop) MIAUR_SUDOLOOP=1 ;;
|
||||
--nosudoloop) MIAUR_SUDOLOOP=0 ;;
|
||||
--clonedir)
|
||||
i=$((i + 1))
|
||||
MIAUR_CLONEDIR=${raw[$i]:-}
|
||||
[[ -n $MIAUR_CLONEDIR ]] || die "--clonedir requires a path"
|
||||
;;
|
||||
--clonedir=*) MIAUR_CLONEDIR=${arg#*=} ;;
|
||||
--mflags)
|
||||
i=$((i + 1))
|
||||
MIAUR_MFLAGS=${raw[$i]:-}
|
||||
;;
|
||||
--mflags=*) MIAUR_MFLAGS=${arg#*=} ;;
|
||||
--mode)
|
||||
i=$((i + 1))
|
||||
MIAUR_MODE=${raw[$i]:-}
|
||||
;;
|
||||
--mode=*) MIAUR_MODE=${arg#*=} ;;
|
||||
--sync) OP=S ;;
|
||||
--query) OP=Q ;;
|
||||
--remove)
|
||||
OP=R
|
||||
DO_PASSTHRU=1
|
||||
;;
|
||||
--getpkgbuild) OP=G ;;
|
||||
--build) OP=B ;;
|
||||
--database | --files | --deptest | --upgrade)
|
||||
DO_PASSTHRU=1
|
||||
;;
|
||||
--)
|
||||
i=$((i + 1))
|
||||
while ((i < ${#raw[@]})); do
|
||||
TARGETS+=("${raw[$i]}")
|
||||
i=$((i + 1))
|
||||
done
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
local cluster=${arg:1}
|
||||
local j c
|
||||
for ((j = 0; j < ${#cluster}; j++)); do
|
||||
c=${cluster:j:1}
|
||||
case "$c" in
|
||||
S) OP=S ;;
|
||||
Q) OP=Q ;;
|
||||
R)
|
||||
OP=R
|
||||
DO_PASSTHRU=1
|
||||
;;
|
||||
G) OP=G ;;
|
||||
B) OP=B ;;
|
||||
D | F | T | U) DO_PASSTHRU=1 ;;
|
||||
y) OP_REFRESH=1 ;;
|
||||
u) OP_UPGRADE=1 ;;
|
||||
s) OP_SEARCH=$((OP_SEARCH + 1)) ;;
|
||||
i)
|
||||
if [[ $OP == B ]]; then
|
||||
OP_BUILD_INSTALL=1
|
||||
else
|
||||
OP_INFO=1
|
||||
fi
|
||||
;;
|
||||
c) OP_CLEAN=1 ;;
|
||||
a)
|
||||
OP_AUR_ONLY=1
|
||||
MIAUR_MODE=aur
|
||||
;;
|
||||
p)
|
||||
if [[ $OP == G ]]; then
|
||||
OP_PRINT=1
|
||||
else
|
||||
PACMAN_EXTRA+=("$c")
|
||||
fi
|
||||
;;
|
||||
h)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
V)
|
||||
printf 'miaur v%s\n' "$MIAUR_VERSION"
|
||||
exit 0
|
||||
;;
|
||||
*) PACMAN_EXTRA+=("$c") ;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
*)
|
||||
TARGETS+=("$arg")
|
||||
;;
|
||||
esac
|
||||
i=$((i + 1))
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Clone / update AUR package sources
|
||||
|
||||
pkg_clone_dir() {
|
||||
local name=$1
|
||||
printf '%s/%s' "${MIAUR_CLONEDIR}" "$name"
|
||||
}
|
||||
|
||||
# Clone or pull package; prints absolute path to clone dir
|
||||
aur_clone() {
|
||||
local name=$1
|
||||
local dir
|
||||
dir=$(pkg_clone_dir "$name")
|
||||
mkdir -p "$MIAUR_CLONEDIR"
|
||||
if [[ -d $dir/.git ]]; then
|
||||
msg2 "Updating $name..."
|
||||
if ! (cd "$dir" && ${MIAUR_GIT} pull --ff-only --quiet); then
|
||||
warn "Cannot fast-forward $name; cloning it again"
|
||||
rm -rf "$dir"
|
||||
${MIAUR_GIT} clone --quiet "${MIAUR_AURURL}/${name}.git" "$dir" || die "clone failed: $name"
|
||||
fi
|
||||
else
|
||||
rm -rf "$dir"
|
||||
msg2 "Cloning $name..."
|
||||
${MIAUR_GIT} clone --quiet "${MIAUR_AURURL}/${name}.git" "$dir" || die "clone failed: $name"
|
||||
fi
|
||||
[[ -f $dir/PKGBUILD ]] || die "PKGBUILD not found after cloning: $name"
|
||||
printf '%s\n' "$dir"
|
||||
}
|
||||
|
||||
# Clean clone cache for one package or all
|
||||
aur_clean_cache() {
|
||||
local target=${1:-}
|
||||
if [[ -n $target ]]; then
|
||||
local dir
|
||||
dir=$(pkg_clone_dir "$target")
|
||||
if [[ -d $dir ]]; then
|
||||
msg "Cleaning cache: $dir"
|
||||
rm -rf "$dir"
|
||||
fi
|
||||
else
|
||||
if [[ -d $MIAUR_CLONEDIR ]]; then
|
||||
msg "Cleaning AUR cache: $MIAUR_CLONEDIR"
|
||||
# Keep VCS src dirs? Plan says clean clone cache — remove package dirs
|
||||
find "$MIAUR_CLONEDIR" -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} +
|
||||
fi
|
||||
fi
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034
|
||||
# Common utilities for miaur
|
||||
|
||||
MIAUR_VERSION="0.1.0"
|
||||
|
||||
# Colors (respect pacman Color / NO_COLOR / non-tty)
|
||||
_miaur_color_enabled() {
|
||||
[[ -n ${NO_COLOR:-} ]] && return 1
|
||||
[[ ! -t 1 ]] && return 1
|
||||
if [[ -f /etc/pacman.conf ]] && grep -Eq '^[[:space:]]*Color([[:space:]]|$)' /etc/pacman.conf 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
# Default: enable on tty even if pacman Color is commented
|
||||
return 0
|
||||
}
|
||||
|
||||
if _miaur_color_enabled; then
|
||||
C_RED=$'\033[31m'
|
||||
C_GREEN=$'\033[32m'
|
||||
C_YELLOW=$'\033[33m'
|
||||
C_BLUE=$'\033[34m'
|
||||
C_CYAN=$'\033[36m'
|
||||
C_BOLD=$'\033[1m'
|
||||
C_DIM=$'\033[2m'
|
||||
C_RESET=$'\033[0m'
|
||||
else
|
||||
C_RED= C_GREEN= C_YELLOW= C_BLUE= C_CYAN= C_BOLD= C_DIM= C_RESET=
|
||||
fi
|
||||
|
||||
msg() { printf '%s::%s %s\n' "${C_BOLD}${C_BLUE}" "${C_RESET}" "$*" >&2; }
|
||||
msg2() { printf '%s ->%s %s\n' "${C_BOLD}${C_BLUE}" "${C_RESET}" "$*" >&2; }
|
||||
warn() { printf '%s==>%s WARNING: %s\n' "${C_BOLD}${C_YELLOW}" "${C_RESET}" "$*" >&2; }
|
||||
error() { printf '%s==>%s ERROR: %s\n' "${C_BOLD}${C_RED}" "${C_RESET}" "$*" >&2; }
|
||||
die() { error "$*"; exit 1; }
|
||||
|
||||
need_cmd() {
|
||||
local c
|
||||
for c in "$@"; do
|
||||
command -v "$c" >/dev/null 2>&1 || die "required command not found: $c"
|
||||
done
|
||||
}
|
||||
|
||||
# Prefer system curl — some user PATH wrappers break AUR HTTPS
|
||||
resolve_curl() {
|
||||
if [[ -n ${MIAUR_CURL:-} ]]; then
|
||||
printf '%s' "$MIAUR_CURL"
|
||||
elif [[ -x /usr/bin/curl ]]; then
|
||||
printf '%s' /usr/bin/curl
|
||||
else
|
||||
command -v curl
|
||||
fi
|
||||
}
|
||||
|
||||
# Strip version constraints from a dep string: foo>=1.0 -> foo
|
||||
dep_name() {
|
||||
local d=$1
|
||||
d=${d%%[><=]*}
|
||||
d=${d%%:*}
|
||||
printf '%s' "$d"
|
||||
}
|
||||
|
||||
vercmp_safe() {
|
||||
# pacman --print returns 0 if equal, 1 if first >, -1 if second >
|
||||
/usr/bin/vercmp "$1" "$2"
|
||||
}
|
||||
|
||||
is_pkg_installed() {
|
||||
pacman -Q "$1" &>/dev/null
|
||||
}
|
||||
|
||||
pkg_local_version() {
|
||||
pacman -Q "$1" 2>/dev/null | awk '{print $2}'
|
||||
}
|
||||
|
||||
# Run command as root via sudo
|
||||
as_root() {
|
||||
if [[ ${EUID:-$(id -u)} -eq 0 ]]; then
|
||||
"$@"
|
||||
else
|
||||
${MIAUR_SUDO:-sudo} ${MIAUR_SUDOFLAGS:-} "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Keep sudo credentials alive in background
|
||||
_sudo_loop_pid=
|
||||
sudoloop_start() {
|
||||
[[ ${MIAUR_SUDOLOOP:-0} -eq 1 ]] || return 0
|
||||
[[ ${EUID:-$(id -u)} -eq 0 ]] && return 0
|
||||
${MIAUR_SUDO:-sudo} -v || return 1
|
||||
(
|
||||
while true; do
|
||||
sleep 60
|
||||
${MIAUR_SUDO:-sudo} -v || exit
|
||||
done
|
||||
) &
|
||||
_sudo_loop_pid=$!
|
||||
}
|
||||
|
||||
sudoloop_stop() {
|
||||
if [[ -n ${_sudo_loop_pid:-} ]]; then
|
||||
kill "$_sudo_loop_pid" 2>/dev/null || true
|
||||
wait "$_sudo_loop_pid" 2>/dev/null || true
|
||||
_sudo_loop_pid=
|
||||
fi
|
||||
}
|
||||
|
||||
trap sudoloop_stop EXIT
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# Config defaults and loader for miaur
|
||||
|
||||
# Defaults
|
||||
MIAUR_AURURL="${MIAUR_AURURL:-https://aur.archlinux.org}"
|
||||
MIAUR_AURRPC="${MIAUR_AURRPC:-https://aur.archlinux.org/rpc/v5}"
|
||||
MIAUR_CLONEDIR="${MIAUR_CLONEDIR:-${XDG_CACHE_HOME:-$HOME/.cache}/miaur}"
|
||||
MIAUR_SKIPREVIEW="${MIAUR_SKIPREVIEW:-0}"
|
||||
MIAUR_CLEANAFTER="${MIAUR_CLEANAFTER:-0}"
|
||||
MIAUR_REMOVEMAKE="${MIAUR_REMOVEMAKE:-1}"
|
||||
MIAUR_BOTTOMUP="${MIAUR_BOTTOMUP:-0}"
|
||||
MIAUR_SUDOLOOP="${MIAUR_SUDOLOOP:-1}"
|
||||
MIAUR_MFLAGS="${MIAUR_MFLAGS:--si}"
|
||||
MIAUR_SORTBY="${MIAUR_SORTBY:-votes}"
|
||||
MIAUR_SEARCHBY="${MIAUR_SEARCHBY:-name-desc}"
|
||||
MIAUR_MODE="${MIAUR_MODE:-}" # aur|repo|empty=both
|
||||
MIAUR_SUDO="${MIAUR_SUDO:-sudo}"
|
||||
MIAUR_SUDOFLAGS="${MIAUR_SUDOFLAGS:-}"
|
||||
MIAUR_GIT="${MIAUR_GIT:-git}"
|
||||
MIAUR_MAKEPKG="${MIAUR_MAKEPKG:-makepkg}"
|
||||
MIAUR_PACMAN="${MIAUR_PACMAN:-pacman}"
|
||||
MIAUR_BAT="${MIAUR_BAT:-bat}"
|
||||
MIAUR_EDITOR="${VISUAL:-${EDITOR:-nano}}"
|
||||
|
||||
_bool_val() {
|
||||
case "${1,,}" in
|
||||
1 | true | yes | on) printf '1' ;;
|
||||
0 | false | no | off) printf '0' ;;
|
||||
*) printf '%s' "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
miaur_load_config() {
|
||||
local conf="${XDG_CONFIG_HOME:-$HOME/.config}/miaur/miaur.conf"
|
||||
[[ -f $conf ]] || return 0
|
||||
local line key val
|
||||
while IFS= read -r line || [[ -n $line ]]; do
|
||||
line=${line%%#*}
|
||||
line=${line#"${line%%[![:space:]]*}"}
|
||||
line=${line%"${line##*[![:space:]]}"}
|
||||
[[ -z $line ]] && continue
|
||||
key=${line%%=*}
|
||||
val=${line#*=}
|
||||
key=${key%"${key##*[![:space:]]}"}
|
||||
key=${key#"${key%%[![:space:]]*}"}
|
||||
val=${val#"${val%%[![:space:]]*}"}
|
||||
val=${val%"${val##*[![:space:]]}"}
|
||||
val=${val#\"}
|
||||
val=${val%\"}
|
||||
val=${val#\'}
|
||||
val=${val%\'}
|
||||
case "$key" in
|
||||
AurUrl | AURURL) MIAUR_AURURL=$val ;;
|
||||
AurRpcUrl | AURRPC) MIAUR_AURRPC=$val ;;
|
||||
CloneDir)
|
||||
MIAUR_CLONEDIR=$val
|
||||
[[ $MIAUR_CLONEDIR == ~* ]] && MIAUR_CLONEDIR="${MIAUR_CLONEDIR/#\~/$HOME}"
|
||||
;;
|
||||
SkipReview) MIAUR_SKIPREVIEW=$(_bool_val "$val") ;;
|
||||
CleanAfter) MIAUR_CLEANAFTER=$(_bool_val "$val") ;;
|
||||
RemoveMake) MIAUR_REMOVEMAKE=$(_bool_val "$val") ;;
|
||||
BottomUp) MIAUR_BOTTOMUP=$(_bool_val "$val") ;;
|
||||
SudoLoop) MIAUR_SUDOLOOP=$(_bool_val "$val") ;;
|
||||
MFlags) MIAUR_MFLAGS=$val ;;
|
||||
SortBy) MIAUR_SORTBY=$val ;;
|
||||
SearchBy) MIAUR_SEARCHBY=$val ;;
|
||||
Sudo) MIAUR_SUDO=$val ;;
|
||||
SudoFlags) MIAUR_SUDOFLAGS=$val ;;
|
||||
Git) MIAUR_GIT=$val ;;
|
||||
Makepkg) MIAUR_MAKEPKG=$val ;;
|
||||
Pacman) MIAUR_PACMAN=$val ;;
|
||||
Bat) MIAUR_BAT=$val ;;
|
||||
Editor) MIAUR_EDITOR=$val ;;
|
||||
esac
|
||||
done <"$conf"
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
#!/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 dep 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
|
||||
# Try provides via pacman -Ssq exact? fallback AUR search by name
|
||||
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[*]}"
|
||||
as_root ${MIAUR_PACMAN} -S --needed --asdeps --noconfirm "${list[@]}"
|
||||
}
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
#!/usr/bin/env bash
|
||||
# Dispatch handlers for miaur operations
|
||||
|
||||
# Reconstruct pacman argv from OP + PACMAN_EXTRA + targets for passthrough
|
||||
pacman_passthru() {
|
||||
local -a args=("$@")
|
||||
as_root ${MIAUR_PACMAN} "${args[@]}"
|
||||
}
|
||||
|
||||
# Search repo + AUR
|
||||
cmd_search() {
|
||||
local -a terms=("$@")
|
||||
[[ ${#terms[@]} -eq 0 ]] && die "specify a search query"
|
||||
local query="${terms[*]}"
|
||||
|
||||
local -a repo_lines=() aur_lines=()
|
||||
|
||||
if [[ ${MIAUR_MODE:-} != aur ]]; then
|
||||
mapfile -t repo_lines < <(${MIAUR_PACMAN} -Ss "$query" 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [[ ${MIAUR_MODE:-} != repo ]]; then
|
||||
local line name ver votes pop desc
|
||||
while IFS='|' read -r name ver votes pop desc; do
|
||||
[[ -z $name ]] && continue
|
||||
aur_lines+=("$(aur_format_search_line "$name" "$ver" "$votes" "$pop" "$desc")")
|
||||
done < <(aur_search "$query" || true)
|
||||
fi
|
||||
|
||||
if [[ ${MIAUR_BOTTOMUP:-0} -eq 1 ]]; then
|
||||
local l
|
||||
for l in "${aur_lines[@]}"; do printf '%b\n' "$l"; done
|
||||
[[ ${#repo_lines[@]} -gt 0 && ${#aur_lines[@]} -gt 0 ]] && echo
|
||||
local r
|
||||
for r in "${repo_lines[@]}"; do printf '%s\n' "$r"; done
|
||||
else
|
||||
local r
|
||||
for r in "${repo_lines[@]}"; do printf '%s\n' "$r"; done
|
||||
[[ ${#repo_lines[@]} -gt 0 && ${#aur_lines[@]} -gt 0 ]] && echo
|
||||
local l
|
||||
for l in "${aur_lines[@]}"; do printf '%b\n' "$l"; done
|
||||
fi
|
||||
}
|
||||
|
||||
# Interactive search + install (like `paru foo`)
|
||||
cmd_interactive() {
|
||||
local query="$*"
|
||||
[[ -z $query ]] && die "specify a search query"
|
||||
|
||||
local -a entries=() # type|name
|
||||
local -a display=()
|
||||
|
||||
# Repo results
|
||||
if [[ ${MIAUR_MODE:-} != aur ]]; then
|
||||
local line repo name rest
|
||||
while IFS= read -r line; do
|
||||
[[ $line =~ ^([a-z0-9_-]+)/([^[:space:]]+) ]] || continue
|
||||
repo=${BASH_REMATCH[1]}
|
||||
name=${BASH_REMATCH[2]}
|
||||
entries+=("repo|$name")
|
||||
display+=("${C_BOLD}${C_BLUE}${repo}/${name}${C_RESET}")
|
||||
done < <(${MIAUR_PACMAN} -Ss "$query" 2>/dev/null | grep -E '^[a-z0-9_-]+/' || true)
|
||||
fi
|
||||
|
||||
# AUR results
|
||||
if [[ ${MIAUR_MODE:-} != repo ]]; then
|
||||
local name ver votes pop desc
|
||||
while IFS='|' read -r name ver votes pop desc; do
|
||||
[[ -z $name ]] && continue
|
||||
entries+=("aur|$name")
|
||||
display+=("${C_BOLD}${C_CYAN}aur/${name}${C_RESET} ${ver} (${votes})")
|
||||
done < <(aur_search "$query" || true)
|
||||
fi
|
||||
|
||||
[[ ${#entries[@]} -eq 0 ]] && die "no matches found: $query"
|
||||
|
||||
local i
|
||||
if [[ ${MIAUR_BOTTOMUP:-0} -eq 1 ]]; then
|
||||
for ((i = ${#display[@]} - 1; i >= 0; i--)); do
|
||||
printf '%s%3d%s %b\n' "${C_DIM}" "$((i + 1))" "${C_RESET}" "${display[$i]}"
|
||||
done
|
||||
else
|
||||
for ((i = 0; i < ${#display[@]}; i++)); do
|
||||
printf '%s%3d%s %b\n' "${C_DIM}" "$((i + 1))" "${C_RESET}" "${display[$i]}"
|
||||
done
|
||||
fi
|
||||
|
||||
printf '%s::%s Select packages (for example: 1 3; leave empty to cancel): ' \
|
||||
"${C_BOLD}${C_BLUE}" "${C_RESET}"
|
||||
local sel=
|
||||
read -r sel || exit 1
|
||||
[[ -z $sel ]] && { msg "Cancelled"; return 0; }
|
||||
|
||||
local -a repo_pkgs=() aur_pkgs=()
|
||||
local tok
|
||||
for tok in $sel; do
|
||||
if [[ $tok =~ ^[0-9]+$ ]]; then
|
||||
local idx=$((tok - 1))
|
||||
((idx >= 0 && idx < ${#entries[@]})) || die "invalid number: $tok"
|
||||
local e=${entries[$idx]}
|
||||
case "$e" in
|
||||
repo\|*) repo_pkgs+=("${e#repo|}") ;;
|
||||
aur\|*) aur_pkgs+=("${e#aur|}") ;;
|
||||
esac
|
||||
else
|
||||
die "invalid selection: $tok"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#repo_pkgs[@]} -gt 0 ]]; then
|
||||
as_root ${MIAUR_PACMAN} -S --needed --noconfirm "${repo_pkgs[@]}"
|
||||
fi
|
||||
if [[ ${#aur_pkgs[@]} -gt 0 ]]; then
|
||||
install_aur_packages "${aur_pkgs[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_info() {
|
||||
local -a pkgs=("$@")
|
||||
[[ ${#pkgs[@]} -eq 0 ]] && die "specify at least one package"
|
||||
local p found
|
||||
for p in "${pkgs[@]}"; do
|
||||
found=0
|
||||
if [[ ${MIAUR_MODE:-} != aur ]] && ${MIAUR_PACMAN} -Si "$p" 2>/dev/null; then
|
||||
found=1
|
||||
fi
|
||||
if [[ ${MIAUR_MODE:-} != repo ]]; then
|
||||
if aur_print_info "$p" 2>/dev/null; then
|
||||
found=1
|
||||
fi
|
||||
fi
|
||||
[[ $found -eq 1 ]] || error "package not found: $p"
|
||||
done
|
||||
}
|
||||
|
||||
cmd_sync_install() {
|
||||
local -a pkgs=("$@")
|
||||
[[ ${#pkgs[@]} -eq 0 ]] && die "specify at least one package"
|
||||
|
||||
local -a repo_pkgs=() aur_pkgs=()
|
||||
local p
|
||||
for p in "${pkgs[@]}"; do
|
||||
if [[ ${MIAUR_MODE:-} == aur ]]; then
|
||||
aur_pkgs+=("$p")
|
||||
elif [[ ${MIAUR_MODE:-} == repo ]]; then
|
||||
repo_pkgs+=("$p")
|
||||
elif repo_has_pkg "$p"; then
|
||||
repo_pkgs+=("$p")
|
||||
elif aur_exists "$p"; then
|
||||
aur_pkgs+=("$p")
|
||||
else
|
||||
die "package not found: $p"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#repo_pkgs[@]} -gt 0 ]]; then
|
||||
as_root ${MIAUR_PACMAN} -S --needed --noconfirm "${repo_pkgs[@]}"
|
||||
fi
|
||||
if [[ ${#aur_pkgs[@]} -gt 0 ]]; then
|
||||
install_aur_packages "${aur_pkgs[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_getpkgbuild() {
|
||||
local -a pkgs=("$@")
|
||||
[[ ${#pkgs[@]} -eq 0 ]] && die "specify at least one package"
|
||||
local p dir
|
||||
for p in "${pkgs[@]}"; do
|
||||
if [[ $OP_PRINT -eq 1 ]]; then
|
||||
dir=$(aur_clone "$p")
|
||||
cat "$dir/PKGBUILD"
|
||||
else
|
||||
dir=$(aur_clone "$p")
|
||||
# Copy to cwd like paru -G
|
||||
if [[ -e ./$p ]]; then
|
||||
warn "./$p already exists; replacing it"
|
||||
rm -rf "./$p"
|
||||
fi
|
||||
cp -a "$dir" "./$p"
|
||||
msg "Downloaded to ./$p"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
cmd_clean() {
|
||||
# -Sc: clean pacman cache + AUR clone cache
|
||||
if [[ ${MIAUR_MODE:-} != aur ]]; then
|
||||
as_root ${MIAUR_PACMAN} -Sc --noconfirm || true
|
||||
fi
|
||||
aur_clean_cache
|
||||
}
|
||||
|
||||
dispatch() {
|
||||
# Full passthrough ops (R, D, F, T, U, or unknown)
|
||||
if [[ $DO_PASSTHRU -eq 1 && $OP != S && $OP != Q ]]; then
|
||||
# Rebuild approximate pacman command from original? Simpler: use saved extras
|
||||
local -a args=()
|
||||
case "$OP" in
|
||||
R) args+=(-R) ;;
|
||||
*)
|
||||
# Fall back: user should use pacman; try to forward
|
||||
args+=(-"${OP}")
|
||||
;;
|
||||
esac
|
||||
local c
|
||||
for c in "${PACMAN_EXTRA[@]}"; do
|
||||
args+=("-$c")
|
||||
done
|
||||
args+=("${TARGETS[@]}")
|
||||
pacman_passthru "${args[@]}"
|
||||
return $?
|
||||
fi
|
||||
|
||||
case "$OP" in
|
||||
interactive)
|
||||
need_cmd curl jq
|
||||
cmd_interactive "${TARGETS[@]}"
|
||||
;;
|
||||
S)
|
||||
if [[ $OP_CLEAN -eq 1 ]]; then
|
||||
cmd_clean
|
||||
return
|
||||
fi
|
||||
if [[ $OP_SEARCH -gt 0 ]]; then
|
||||
need_cmd curl jq
|
||||
cmd_search "${TARGETS[@]}"
|
||||
return
|
||||
fi
|
||||
if [[ $OP_INFO -eq 1 ]]; then
|
||||
need_cmd curl jq
|
||||
cmd_info "${TARGETS[@]}"
|
||||
return
|
||||
fi
|
||||
if [[ $OP_UPGRADE -eq 1 ]]; then
|
||||
need_cmd curl jq
|
||||
if [[ $OP_AUR_ONLY -eq 1 ]]; then
|
||||
# -Sua or -Su --aur
|
||||
[[ $OP_REFRESH -eq 1 ]] && as_root ${MIAUR_PACMAN} -Sy --noconfirm
|
||||
cmd_upgrade_aur
|
||||
else
|
||||
cmd_upgrade_all "$OP_REFRESH"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
if [[ $OP_REFRESH -eq 1 && ${#TARGETS[@]} -eq 0 ]]; then
|
||||
as_root ${MIAUR_PACMAN} -Sy --noconfirm
|
||||
return
|
||||
fi
|
||||
# Install packages; optionally refresh first
|
||||
[[ $OP_REFRESH -eq 1 ]] && as_root ${MIAUR_PACMAN} -Sy --noconfirm
|
||||
need_cmd curl jq
|
||||
cmd_sync_install "${TARGETS[@]}"
|
||||
;;
|
||||
Q)
|
||||
if [[ $OP_UPGRADE -eq 1 && $OP_AUR_ONLY -eq 1 ]]; then
|
||||
need_cmd curl jq
|
||||
cmd_query_aur_upgrades
|
||||
return
|
||||
fi
|
||||
if [[ $OP_UPGRADE -eq 1 ]]; then
|
||||
# -Qu: repo + AUR
|
||||
${MIAUR_PACMAN} -Qu || true
|
||||
need_cmd curl jq
|
||||
cmd_query_aur_upgrades || true
|
||||
return
|
||||
fi
|
||||
# Default query passthrough
|
||||
local -a qargs=(-Q)
|
||||
local c
|
||||
for c in "${PACMAN_EXTRA[@]}"; do
|
||||
qargs+=("-$c")
|
||||
done
|
||||
[[ $OP_AUR_ONLY -eq 1 ]] && qargs+=(-m)
|
||||
[[ $OP_SEARCH -gt 0 ]] && qargs+=(-s)
|
||||
[[ $OP_INFO -eq 1 ]] && qargs+=(-i)
|
||||
qargs+=("${TARGETS[@]}")
|
||||
${MIAUR_PACMAN} "${qargs[@]}"
|
||||
;;
|
||||
G)
|
||||
need_cmd curl jq git
|
||||
cmd_getpkgbuild "${TARGETS[@]}"
|
||||
;;
|
||||
B)
|
||||
[[ ${#TARGETS[@]} -eq 0 ]] && TARGETS=(.)
|
||||
need_cmd git makepkg
|
||||
build_local_dirs "$OP_BUILD_INSTALL" "${TARGETS[@]}"
|
||||
;;
|
||||
"")
|
||||
if [[ $DO_PASSTHRU -eq 1 ]]; then
|
||||
die "unable to parse operation; use pacman directly or see --help"
|
||||
fi
|
||||
die "no operation specified"
|
||||
;;
|
||||
*)
|
||||
die "unsupported operation: $OP"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# PKGBUILD review
|
||||
|
||||
# Review PKGBUILD in dir. Returns 0 to continue, 1 to abort.
|
||||
review_pkgbuild() {
|
||||
local dir=$1
|
||||
local name=${2:-$(basename "$dir")}
|
||||
|
||||
[[ ${MIAUR_SKIPREVIEW:-0} -eq 1 ]] && return 0
|
||||
|
||||
local pb="$dir/PKGBUILD"
|
||||
[[ -f $pb ]] || die "PKGBUILD not found: $dir"
|
||||
|
||||
msg "Reviewing the PKGBUILD for $name"
|
||||
if command -v "${MIAUR_BAT}" >/dev/null 2>&1; then
|
||||
"${MIAUR_BAT}" --style=plain --paging=always --language=bash "$pb" || true
|
||||
elif command -v less >/dev/null 2>&1; then
|
||||
less -R "$pb" || true
|
||||
else
|
||||
cat "$pb"
|
||||
fi
|
||||
|
||||
# Also show install script / other files briefly
|
||||
local f
|
||||
for f in "$dir"/*.install "$dir"/PKGBUILD; do
|
||||
[[ -f $f ]] || continue
|
||||
done
|
||||
|
||||
while true; do
|
||||
printf '%s::%s View diff (d), edit (e), continue (y), skip (s), or quit (q)? [Y/d/e/s/q] ' \
|
||||
"${C_BOLD}${C_BLUE}" "${C_RESET}"
|
||||
local ans=
|
||||
read -r ans || return 1
|
||||
ans=${ans:-y}
|
||||
case "${ans,,}" in
|
||||
y | yes | '') return 0 ;;
|
||||
q | quit | n | no)
|
||||
warn "Cancelled by user"
|
||||
return 1
|
||||
;;
|
||||
s | skip) return 2 ;;
|
||||
e | edit)
|
||||
"${MIAUR_EDITOR}" "$pb"
|
||||
;;
|
||||
d | diff)
|
||||
if [[ -d $dir/.git ]]; then
|
||||
(cd "$dir" && ${MIAUR_GIT} diff -- PKGBUILD) || true
|
||||
else
|
||||
warn "No Git history is available for comparison"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
warn "Invalid input"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
# AUR upgrade detection and application
|
||||
|
||||
# List foreign packages (AUR candidates): name version
|
||||
foreign_packages() {
|
||||
pacman -Qm
|
||||
}
|
||||
|
||||
# Compare installed foreign pkgs with AUR; print upgradable: name local -> remote
|
||||
aur_outdated() {
|
||||
local -a names=()
|
||||
local -A localver=()
|
||||
local name ver
|
||||
while read -r name ver; do
|
||||
[[ -z $name ]] && continue
|
||||
names+=("$name")
|
||||
localver[$name]=$ver
|
||||
done < <(foreign_packages)
|
||||
|
||||
[[ ${#names[@]} -eq 0 ]] && return 0
|
||||
|
||||
# Batch in chunks of 100
|
||||
local i chunk=100
|
||||
local -a batch=()
|
||||
for ((i = 0; i < ${#names[@]}; i++)); do
|
||||
batch+=("${names[$i]}")
|
||||
if ((${#batch[@]} == chunk || i == ${#names[@]} - 1)); then
|
||||
local json
|
||||
json=$(aur_multiinfo_json "${batch[@]}") || {
|
||||
warn "Failed to query AUR updates"
|
||||
batch=()
|
||||
continue
|
||||
}
|
||||
local line rname rver
|
||||
while IFS= read -r line; do
|
||||
rname=${line%%|*}
|
||||
rver=${line#*|}
|
||||
[[ -z $rname ]] && continue
|
||||
local lv=${localver[$rname]:-}
|
||||
[[ -z $lv ]] && continue
|
||||
if [[ $(vercmp_safe "$rver" "$lv") -gt 0 ]]; then
|
||||
printf '%s %s -> %s\n' "$rname" "$lv" "$rver"
|
||||
fi
|
||||
done < <(jq -r '.[] | "\(.Name)|\(.Version)"' <<<"$json")
|
||||
batch=()
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Print outdated like pacman -Qu
|
||||
cmd_query_aur_upgrades() {
|
||||
local name old _arrow new
|
||||
while read -r name old _arrow new; do
|
||||
[[ -z $name ]] && continue
|
||||
printf '%s %s -> %s\n' "$name" "$old" "$new"
|
||||
done < <(aur_outdated)
|
||||
return 0
|
||||
}
|
||||
|
||||
# Upgrade all outdated AUR packages
|
||||
cmd_upgrade_aur() {
|
||||
local -a pkgs=()
|
||||
local name old arrow new
|
||||
while read -r name old arrow new; do
|
||||
[[ -z $name ]] && continue
|
||||
pkgs+=("$name")
|
||||
msg2 "$name ${old} -> ${new}"
|
||||
done < <(aur_outdated)
|
||||
|
||||
if [[ ${#pkgs[@]} -eq 0 ]]; then
|
||||
msg "No AUR package upgrades are available"
|
||||
return 0
|
||||
fi
|
||||
msg "Upgrading ${#pkgs[@]} AUR package(s)"
|
||||
install_aur_packages "${pkgs[@]}"
|
||||
}
|
||||
|
||||
# Full -Syu: refresh + repo upgrade + AUR upgrade
|
||||
cmd_upgrade_all() {
|
||||
local refresh=${1:-0}
|
||||
sudoloop_start
|
||||
local -a pac_args=()
|
||||
[[ $refresh -eq 1 ]] && pac_args+=(-y)
|
||||
pac_args+=(-Su)
|
||||
|
||||
msg "Synchronizing databases and upgrading repository packages..."
|
||||
# Use -Syu style via pacman
|
||||
if [[ $refresh -eq 1 ]]; then
|
||||
as_root ${MIAUR_PACMAN} -Syu --noconfirm || die "repository upgrade failed"
|
||||
else
|
||||
as_root ${MIAUR_PACMAN} -Su --noconfirm || die "repository upgrade failed"
|
||||
fi
|
||||
|
||||
msg "Checking for AUR updates..."
|
||||
cmd_upgrade_aur
|
||||
sudoloop_stop
|
||||
}
|
||||
Reference in New Issue
Block a user