Dotfiles/setup/audit-packages.sh

215 lines
7.6 KiB
Bash
Executable File

#!/bin/bash
# Verifies installed packages come from the expected source (pacman/AUR/flatpak).
# Reports missing packages, wrong-source installs, and unexpected foreign packages.
# Pass --fix / -f to automatically reinstall packages from the correct source.
set -euo pipefail
RED="\e[31m"; YELLOW="\e[33m"; GREEN="\e[32m"; CYAN="\e[36m"; BOLD="\e[1m"; RESET="\e[0m"
ok() { echo -e " ${GREEN}${RESET} $1"; }
warn() { echo -e " ${YELLOW}${RESET} $1"; }
err() { echo -e " ${RED}${RESET} $1"; }
hdr() { echo -e "\n${BOLD}${CYAN}$1${RESET}"; }
fix() { echo -e " ${CYAN}${RESET} $1"; }
FIX=0
[[ "${1:-}" == "--fix" || "${1:-}" == "-f" ]] && FIX=1
ISSUES=0
flag() { ISSUES=$((ISSUES + 1)); }
WRONG_SOURCE_OFFICIAL=() # expected from pacman, installed from AUR
WRONG_SOURCE_AUR=() # expected from AUR, installed from official
# ---------------------------------------------------------------------------
# Expected package sources — keep in sync with setup/modules/
# ---------------------------------------------------------------------------
PACMAN_PKGS=(
# core-packages.sh
7zip arch-install-scripts atftp atool
base base-devel bind bluez btrfs-progs btop
cockpit cockpit-files cockpit-podman cronie curl
distrobox fail2ban fastfetch fd ffmpeg firefox flatpak
gcc glib2 greetd-tuigreet grub
htop inetutils iwd jq ldns less libpulse linux linux-firmware
man-db mc nano neovim networkmanager
openssh pciutils pipewire podman podman-compose
python python-pip qrencode ruby-pkg-config rust rustup
ipcalc iputils mtr net-tools nmap
smartmontools symlinks tcpdump traceroute tree
udisks2 udisks2-btrfs udiskie ufw usbutils
vim vnstat wget wireplumber wireless_tools wpa_supplicant wprs
yazi zip unzip zram-generator
# shell-setup.sh
zsh pyright bash atftp bash-language-server clang fzf hyfetch
lua-language-server micro pulsemixer z dysk glow
# hyprland.sh (official-repo portion)
hyprland hyprcursor wl-clipboard hyprpaper hyprlock wofi kitty dunst
nwg-dock-hyprland nwg-drawer nwg-menu nwg-look
cmake meson cpio pkgconf
hyprsunset hypridle ksshaskpass
nm-connection-editor network-manager-applet blueman
pipewire alsa-utils greetd-tuigreet
grim slurp gst-plugin-pipewire imagemagick
nerd-fonts otf-font-awesome
pipewire-alsa pipewire-jack pipewire-pulse
qt5-wayland qt6-wayland swww ttf-jetbrains-mono
qt6ct xdg-desktop-portal-hyprland xdg-utils
xorg-server xorg-xinit papirus-icon-theme
cool-retro-term qalculate-gtk dbus
thunar tumbler thunar-archive-plugin thunar-shares-plugin thunar-volman
hyprpicker pcmanfm-qt ly
hyprpolkitagent pavucontrol playerctl wf-recorder sound-theme-freedesktop
kew
)
AUR_PKGS=(
# hyprland.sh AUR portion
hyprland-workspaces vicinae-bin bluetuith wvkbd iwmenu
walker-bin ulauncher bzmenu wofi-calc bri chamel
# optional apps
pamtester
pinta
localsend
vesktop
onlyoffice-bin
vintagestory
wprs-git
zfs-dkms
)
FLATPAK_PKGS=(
org.prismlauncher.PrismLauncher
)
# ---------------------------------------------------------------------------
# Snapshot current state
# ---------------------------------------------------------------------------
ALL_INSTALLED=$(pacman -Qq 2>/dev/null)
FOREIGN=$(pacman -Qmq 2>/dev/null) # AUR / manually installed
OFFICIAL=$(pacman -Qnq 2>/dev/null) # in a sync repo
is_installed() { echo "$ALL_INSTALLED" | grep -qx "$1"; }
is_from_official() { echo "$OFFICIAL" | grep -qx "$1"; }
is_from_aur() { echo "$FOREIGN" | grep -qx "$1"; }
# ---------------------------------------------------------------------------
# 1. Check pacman packages
# ---------------------------------------------------------------------------
hdr "1/3 Official-repo packages (pacman)"
for pkg in "${PACMAN_PKGS[@]}"; do
if ! is_installed "$pkg"; then
err "$pkg — NOT INSTALLED"; flag
elif is_from_aur "$pkg"; then
warn "$pkg — installed, but from AUR instead of official repo"; flag
WRONG_SOURCE_OFFICIAL+=("$pkg")
else
ok "$pkg"
fi
done
# ---------------------------------------------------------------------------
# 2. Check AUR packages
# ---------------------------------------------------------------------------
hdr "2/3 AUR packages (yay)"
for pkg in "${AUR_PKGS[@]}"; do
if ! is_installed "$pkg"; then
warn "$pkg — not installed (optional — may be intentional)"
elif is_from_official "$pkg"; then
warn "$pkg — installed from official repo, not AUR (may need AUR build for correct version)"; flag
WRONG_SOURCE_AUR+=("$pkg")
else
ok "$pkg"
fi
done
# ---------------------------------------------------------------------------
# 3. Check flatpak packages
# ---------------------------------------------------------------------------
hdr "3/3 Flatpak packages"
if command -v flatpak &>/dev/null; then
FLATPAK_INSTALLED=$(flatpak list --app --columns=application 2>/dev/null)
for pkg in "${FLATPAK_PKGS[@]}"; do
if echo "$FLATPAK_INSTALLED" | grep -qx "$pkg"; then
ok "$pkg"
else
warn "$pkg — not installed (optional — may be intentional)"
fi
done
else
warn "flatpak not found — skipping flatpak checks"
fi
# ---------------------------------------------------------------------------
# 4. Flag unexpected foreign (AUR) packages not in our lists
# ---------------------------------------------------------------------------
hdr "Bonus: foreign packages not declared in setup scripts"
AUR_SET=$(printf "%s\n" "${AUR_PKGS[@]}")
while IFS= read -r pkg; do
if ! echo "$AUR_SET" | grep -qx "$pkg"; then
echo -e " ${CYAN}?${RESET} $pkg — foreign package not in setup scripts"
fi
done <<< "$FOREIGN"
# ---------------------------------------------------------------------------
# Fix: reinstall wrong-source packages
# ---------------------------------------------------------------------------
FIXED=0
if [ "$FIX" -eq 1 ]; then
if [ ${#WRONG_SOURCE_OFFICIAL[@]} -gt 0 ] || [ ${#WRONG_SOURCE_AUR[@]} -gt 0 ]; then
hdr "Reinstalling wrong-source packages"
fi
for pkg in "${WRONG_SOURCE_OFFICIAL[@]}"; do
fix "Reinstalling $pkg from official repo (was AUR)..."
if sudo pacman -S --noconfirm "$pkg"; then
ok "$pkg reinstalled from official repo"
FIXED=$((FIXED + 1))
ISSUES=$((ISSUES - 1))
else
err "$pkg reinstall failed"
fi
done
for pkg in "${WRONG_SOURCE_AUR[@]}"; do
fix "Reinstalling $pkg from AUR (was official repo)..."
if yay -S --aur --noconfirm "$pkg"; then
ok "$pkg reinstalled from AUR"
FIXED=$((FIXED + 1))
ISSUES=$((ISSUES - 1))
else
err "$pkg reinstall failed"
fi
done
fi
# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
echo
if [ "$FIX" -eq 1 ] && [ "$FIXED" -gt 0 ]; then
echo -e "${GREEN}${BOLD}Fixed ${FIXED} wrong-source package(s).${RESET}"
fi
if [ "$ISSUES" -eq 0 ]; then
echo -e "${GREEN}${BOLD}All checks passed — no source mismatches or missing required packages.${RESET}"
else
echo -e "${RED}${BOLD}${ISSUES} issue(s) found — review items marked ✘ or ⚠ above.${RESET}"
[ "$FIX" -eq 0 ] && [ $((${#WRONG_SOURCE_OFFICIAL[@]} + ${#WRONG_SOURCE_AUR[@]})) -gt 0 ] && \
echo -e "${YELLOW} Run with --fix to automatically reinstall wrong-source packages.${RESET}"
exit 1
fi