#!/bin/bash
set -e
argv0=sync-list

# Targets are taken from a file or the command-line, to avoid
# redirecting stdin to aur-view or aur-build.
if [[ -s $1 ]]; then
    list=$(realpath -- "$1")
else
    printf >&2 '%s: %s: file is empty or does not exist\n' "$argv0" "$1"
    exit 1
fi

# Create a scratch space. /var/tmp ensures sufficient space for built
# packages (not on tmpfs by default)
var_tmp=$(mktemp -d --tmpdir="${TMPDIR:-/var/tmp/}")
tmp=$(mktemp -d)
trap 'rm -rf "$tmp" "$var_tmp"' EXIT # comment this if inspecting the contents

# 1. Avoid concurrent use
( flock -n 200 || exit 1
  cd "$tmp"

  # Retrieve repository location
  { IFS=: read -r _ db_name
    IFS=: read -r _ db_root
    IFS=: read -r _ db_path
  } < <(aur repo --status "$@")
  wait "$!"

  # 2. Retrieve targets and their dependencies from the local repository.
  aur repo-parse -p "$db_path" --table | tee db_table | \
      cut -f1,2 | grep -Fwf "$list" | tsort >db_deps

  # 3. Remove entries that are not in the dependency tree.
  cut -f1 db_table | grep -Fxvf db_deps | sort -u >db_removals

  files_path=$(realpath "$db_root/$db_name".files)

  # Create copy of local repository database
  cp -Pv "$db_path" "$db_root/$db_name".db "$var_tmp"
  cp -Pv "$files_path" "$db_root/$db_name".files "$var_tmp"

  # 4. Remove entries that are not in the dependency tree.
  cd "$var_tmp"
  xargs -a "$tmp"/db_removals -r repo-remove "${db_path##*/}"

  # 5. Add symlinks to built packages.
  aur repo-parse -p "$db_path" --attr FileName | \
      xargs env -C "$db_root" realpath -z | xargs -0r ln -t "$var_tmp" -s --

  # 6. Point the repository root in pacman.conf to the temporary directory.
  { printf '[options]\n'
    pacconf --raw --options

    while IFS= read -r; do
        # section header
        printf '[%s]\n' "$REPLY"

        if [[ $REPLY == "$db_name" ]]; then
            pacconf --raw --repo="$REPLY" --verbose Usage SigLevel
            printf '%s\n' "Server = file://$var_tmp"
        else
            pacconf --raw --repo="$REPLY" --verbose Usage SigLevel Server
        fi
    done < <(pacconf --repo-list)
  } >"$tmp"/pacman.conf

  # 7. Run aur-sync(1) with the new pacman configuration.
  # Adjust options to preference.
  aur sync -d "$db_name" --pacman-conf="$tmp"/pacman.conf -Rrn $(<"$list")

  # 8. Synchronize the new repository state to the original location.
  # Remove --dry-run if the output is as desired.
  set -x
  rsync -avh "$var_tmp"/ "$db_root"/ --delete \
        --copy-links --exclude={"$db_name".db,"$db_name".files} --dry-run

  # 9. Save list with new dependency tree
  cp -v "$list" "$list".old
  aur repo-parse -p "$db_path" --list | cut -f1 >"$list"

) 200> /tmp/lockfile
