Guest User

check-aur-maintainers.sh

a guest
Jul 31st, 2026
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.61 KB | None | 0 0
  1. #!/usr/bin/env bash
  2.  
  3. STATE_FILE="$HOME/.config/aur-maintainers.json"
  4.  
  5. # Ensure jq is installed
  6. if ! command -v jq >/dev/null 2>&1; then
  7.     echo "ERROR: 'jq' is required for maintainer tracking." >&2
  8.     exit 1
  9. fi
  10.  
  11. # Fetch installed foreign/AUR packages
  12. mapfile -t foreign_pkgs < <(pacman -Qmq)
  13.  
  14. if [ "${#foreign_pkgs[@]}" -eq 0 ]; then
  15.     exit 0
  16. fi
  17.  
  18. # Initialize state file if it doesn't exist
  19. if [ ! -f "$STATE_FILE" ]; then
  20.     echo "{}" > "$STATE_FILE"
  21. fi
  22.  
  23. # Query AUR RPC v5
  24. curl_args=(-sL -G "https://aur.archlinux.org/rpc/v5/info")
  25. for pkg in "${foreign_pkgs[@]}"; do
  26.     curl_args+=(--data-urlencode "arg[]=$pkg")
  27. done
  28.  
  29. response=$(curl "${curl_args[@]}")
  30.  
  31. if [ -z "$response" ]; then
  32.     echo "⚠️  WARNING: Unable to reach AUR RPC. Proceed with caution." >&2
  33.     read -p "Continue update anyway? [y/N]: " -n 1 -r
  34.     echo ""
  35.     [[ $REPLY =~ ^[Yy]$ ]] && exit 0 || exit 1
  36. fi
  37.  
  38. # Build current remote state as JSON: {"pkgname": "MaintainerOrNull"}
  39. remote_json=$(echo "$response" | jq -c '
  40.  [.results[] | {key: .Name, value: (.Maintainer // "ORPHANED")}] | from_entries
  41. ')
  42.  
  43. # Detect maintainer changes and classify risk
  44. changes=$(jq -n \
  45.   --argjson old "$(cat "$STATE_FILE")" \
  46.   --argjson new "$remote_json" '
  47.  $new | to_entries[] | .key as $pkg | .value as $new_m |
  48.  ($old[$pkg]) as $old_m |
  49.  if $old_m != null and $old_m != $new_m then
  50.    {
  51.      package: $pkg,
  52.      old: $old_m,
  53.      new: $new_m,
  54.      is_high_risk: ($new_m == "ORPHANED" or $old_m == "ORPHANED")
  55.    }
  56.  else
  57.    empty
  58.  end
  59. ')
  60.  
  61. # Check for packages completely removed from AUR
  62. found_pkgs=$(echo "$response" | jq -r '.results[].Name')
  63. declare -A found_map
  64. for pkg in $found_pkgs; do
  65.     found_map["$pkg"]=1
  66. done
  67.  
  68. dropped_pkgs=()
  69. for pkg in "${foreign_pkgs[@]}"; do
  70.     if [[ -z "${found_map[$pkg]}" ]]; then
  71.         dropped_pkgs+=("$pkg")
  72.     fi
  73. done
  74.  
  75. # Collect all flagged package names for removal option
  76. flagged_pkgs=()
  77. if [ -n "$changes" ]; then
  78.     mapfile -t changed_names < <(echo "$changes" | jq -r '.package')
  79.     flagged_pkgs+=("${changed_names[@]}")
  80. fi
  81. if [ "${#dropped_pkgs[@]}" -gt 0 ]; then
  82.     flagged_pkgs+=("${dropped_pkgs[@]}")
  83. fi
  84.  
  85. # If changes or dropped packages are found, issue interactive prompt
  86. if [ "${#flagged_pkgs[@]}" -gt 0 ]; then
  87.     echo -e "\n\033[1;31m========================================================\033[0m"
  88.     echo -e "\033[1;31m⚠️   AUR SECURITY ALERT: HIGH RISK CHANGES DETECTED!    ⚠️\033[0m"
  89.     echo -e "\033[1;31m========================================================\033[0m\n"
  90.  
  91.     high_risk_changes=$(echo "$changes" | jq -c 'select(.is_high_risk == true)')
  92.     std_changes=$(echo "$changes" | jq -c 'select(.is_high_risk == false)')
  93.  
  94.     if [ -n "$high_risk_changes" ]; then
  95.         echo -e "\033[1;31m🚨 HIGH RISK: Package Orphaned or Adopted:\033[0m"
  96.         echo "$high_risk_changes" | jq -r '"  • \(.package): \(.old) ➔ \(.new)"'
  97.         echo ""
  98.     fi
  99.  
  100.     if [ -n "$std_changes" ]; then
  101.         echo -e "\033[1;33m⚠️  MAINTAINER HANDOFF: Ownership transferred:\033[0m"
  102.         echo "$std_changes" | jq -r '"  • \(.package): \(.old) ➔ \(.new)"'
  103.         echo ""
  104.     fi
  105.  
  106.     if [ "${#dropped_pkgs[@]}" -gt 0 ]; then
  107.         echo -e "\033[1;31m🚨 HIGH RISK: Completely REMOVED from AUR:\033[0m"
  108.         for pkg in "${dropped_pkgs[@]}"; do
  109.             echo "  • $pkg"
  110.         done
  111.         echo ""
  112.     fi
  113.  
  114.     echo "Inspect the PKGBUILD on aur.archlinux.org before approving."
  115.     echo ""
  116.     read -p "Options: [y]es accept all | [r]emove flagged packages | [N]o abort update: " -n 1 -r
  117.     echo ""
  118.  
  119.     case "$REPLY" in
  120.         [Yy])
  121.             # Save current state to JSON on approval
  122.             echo "$remote_json" > "$STATE_FILE"
  123.             echo ":: AUR maintainer state updated."
  124.             exit 0
  125.             ;;
  126.         [Rr])
  127.             echo -e "\n\033[1;33mSelect packages to remove (space-separated names), or press Enter to remove ALL flagged:\033[0m"
  128.             echo "Flagged packages: ${flagged_pkgs[*]}"
  129.             read -p "Packages to remove [default: all]: " -r pkgs_to_remove
  130.  
  131.             if [ -z "$pkgs_to_remove" ]; then
  132.                 pkgs_to_remove="${flagged_pkgs[*]}"
  133.             fi
  134.  
  135.             echo -e "\n:: Running: sudo pacman -Rns $pkgs_to_remove"
  136.             if sudo pacman -Rns $pkgs_to_remove; then
  137.                 # Re-query remaining foreign packages to update state JSON accurately
  138.                 mapfile -t remaining_foreign < <(pacman -Qmq)
  139.                 if [ "${#remaining_foreign[@]}" -gt 0 ]; then
  140.                     updated_json=$(echo "$response" | jq -c --argjson remaining "$(printf '%s\n' "${remaining_foreign[@]}" | jq -R . | jq -s .)" '
  141.                      [.results[] | select(.Name as $name | $remaining | contains([$name])) | {key: .Name, value: (.Maintainer // "ORPHANED")}] | from_entries
  142.                    ')
  143.                     echo "$updated_json" > "$STATE_FILE"
  144.                 else
  145.                     echo "{}" > "$STATE_FILE"
  146.                 fi
  147.                 echo ":: Specified packages removed and state file updated."
  148.             else
  149.                 echo -e "\033[1;31mFailed to remove packages via pacman.\033[0m"
  150.             fi
  151.  
  152.             echo -e "\n\033[1;31mUpdate process paused. Re-run cachy-update to proceed with clean state.\033[0m"
  153.             exit 1
  154.             ;;
  155.         *)
  156.             echo -e "\n\033[1;31mUpdate aborted by user.\033[0m"
  157.             exit 1
  158.             ;;
  159.     esac
  160. fi
  161.  
  162. # Save current state to JSON on normal runs
  163. echo "$remote_json" > "$STATE_FILE"
  164. echo ":: AUR maintainer state verified."
  165. exit 0
  166.  
Advertisement
Add Comment
Please, Sign In to add comment