#!/bin/bash
# Publishes one PKGBUILD to its AUR package, never by a forced push; docs/release.md has its arguments and environment.
set -euo pipefail

if [ "$#" -ne 3 ]; then
  echo "aur-push: expected <pkgname> <pkgbuild> <commit message>" >&2
  exit 2
fi
pkgname=$1
# The key this runs with can push to every package its AUR account maintains, so only Flea's three are ever named.
case "$pkgname" in
  flea|flea-bin|flea-git) ;;
  *) echo "aur-push: refusing '$pkgname', which is not flea, flea-bin or flea-git" >&2; exit 2 ;;
esac
pkgbuild=$(realpath -e -- "$2") || { echo "aur-push: no file at '$2'" >&2; exit 1; }
message=$3
if [ -z "${AUR_COMMIT_NAME:-}" ] || [ -z "${AUR_COMMIT_EMAIL:-}" ]; then
  echo "aur-push: AUR_COMMIT_NAME and AUR_COMMIT_EMAIL must both be set" >&2
  exit 2
fi

here=$(cd "$(dirname "$0")" && pwd)
# The AUR itself, unless a dry run points this at a directory of bare repositories.
remote_base=${AUR_REMOTE_BASE:-ssh://aur@aur.archlinux.org}
# The only branch the AUR accepts a push to.
aur_branch=master

work=$(mktemp -d "${TMPDIR:-/tmp}/aur-push.XXXXXX")
agent_pid=
cleanup() { rm -rf -- "$work"; if [ -n "$agent_pid" ]; then kill "$agent_pid"; fi; }
trap cleanup EXIT

if [ -n "${AUR_SSH_KEY:-}" ]; then
  # The key goes from the environment into an agent this run starts and kills, never into a file or an argv.
  eval "$(ssh-agent -s)" >/dev/null
  agent_pid=$SSH_AGENT_PID
  printf '%s\n' "$AUR_SSH_KEY" | ssh-add -q -
  unset AUR_SSH_KEY
  # Only the pinned AUR host keys are trusted, and nothing is ever asked or learned on the way.
  export GIT_SSH_COMMAND="ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile='$here/aur.known_hosts' -o GlobalKnownHostsFile=/dev/null"
fi
clone="$work/$pkgname"
git clone --quiet "$remote_base/$pkgname.git" "$clone"

# A -git package is a VCS package, and the AUR guidelines forbid a commit that only moves its pkgver.
if [[ "$pkgname" == *-git ]] && [ -f "$clone/PKGBUILD" ] &&
  diff -q <(grep -v '^pkgver=' "$clone/PKGBUILD") <(grep -v '^pkgver=' "$pkgbuild") >/dev/null; then
  echo "aur-push: $pkgname on the AUR differs from $2 in pkgver at most, so nothing is pushed"
  exit 0
fi

cp "$pkgbuild" "$clone/PKGBUILD"
(cd "$clone" && makepkg --printsrcinfo > .SRCINFO)
git -C "$clone" add PKGBUILD .SRCINFO
if git -C "$clone" diff --cached --quiet; then
  echo "aur-push: $pkgname on the AUR already carries this PKGBUILD, so nothing is pushed"
  exit 0
fi
git -C "$clone" -c user.name="$AUR_COMMIT_NAME" -c user.email="$AUR_COMMIT_EMAIL" commit --quiet -m "$message"
# A plain push: the AUR refuses it when its head moved since the clone, and that refusal is the failure.
git -C "$clone" push origin "HEAD:$aur_branch"
echo "aur-push: pushed $pkgname as $(git -C "$clone" rev-parse --short HEAD)"
