#!/bin/bash
# =============================================================================
# Pull the seed repository.
#
#   muli-db-seed-pull [--check]
#
# Clones on first run, fetches thereafter, into $MULI_SEED_ROOT. Read-only by
# construction: the deploy key this runs under has read access to the Gitea
# repository and nothing more, so a compromised contract container cannot
# publish data to any other container.
#
# Configuration lives in /etc/muli/seed.conf:
#
#   SEED_REMOTE=gitea@gitea.mercuran.com.au:data_controls/muli_data_seeding.git
#   SEED_BRANCH=master
#   SEED_SSH_KEY=/usr/local/muli/etc/seed_deploy_key
#
# Pulling and applying are separate on purpose. A fetch that brings down a bad
# commit changes nothing until muli-db-seed runs, and `--check` reports what a
# pull would bring without touching the working tree.
# =============================================================================
set -euo pipefail

CONF="${MULI_SEED_CONF:-/etc/muli/seed.conf}"
SEED_ROOT="${MULI_SEED_ROOT:-/usr/local/muli/dbmaster}"
SEED_BRANCH="${SEED_BRANCH:-master}"
CHECK_ONLY=false
[ "${1:-}" = "--check" ] && CHECK_ONLY=true

log() { echo "[muli-db-seed-pull] $*"; }
die() { echo "[muli-db-seed-pull] ERROR: $*" >&2; exit 1; }

# shellcheck source=/dev/null
[ -f "$CONF" ] && . "$CONF"
[ -n "${SEED_REMOTE:-}" ] || die "SEED_REMOTE is not set (looked in ${CONF})"

# Restrict SSH to the deploy key, and do not fall back to an agent or to any
# other identity that happens to be present.
if [ -n "${SEED_SSH_KEY:-}" ]; then
    # IdentityAgent=none matters: without it ssh will happily offer an agent
    # identity ahead of the deploy key, and a host whose operator has their own
    # Gitea key loaded would authenticate as that person instead. Verified - it
    # silently authenticated as the wrong user until this was added.
    export GIT_SSH_COMMAND="ssh -i ${SEED_SSH_KEY} -o IdentitiesOnly=yes -o IdentityAgent=none -o StrictHostKeyChecking=accept-new"
fi

if [ ! -d "${SEED_ROOT}/.git" ]; then
    [ "$CHECK_ONLY" = true ] && { log "not cloned yet; a pull would clone ${SEED_REMOTE}"; exit 0; }
    log "cloning ${SEED_REMOTE} into ${SEED_ROOT}"
    mkdir -p "$(dirname "$SEED_ROOT")"
    git clone --depth 1 --branch "$SEED_BRANCH" "$SEED_REMOTE" "$SEED_ROOT"
else
    git -C "$SEED_ROOT" fetch --depth 1 origin "$SEED_BRANCH" --quiet
    local_rev=$(git -C "$SEED_ROOT" rev-parse HEAD)
    remote_rev=$(git -C "$SEED_ROOT" rev-parse FETCH_HEAD)
    if [ "$local_rev" = "$remote_rev" ]; then
        log "already at $(git -C "$SEED_ROOT" rev-parse --short HEAD)"
        exit 0
    fi
    if [ "$CHECK_ONLY" = true ]; then
        log "update available: $(echo "$local_rev" | cut -c1-7) -> $(echo "$remote_rev" | cut -c1-7)"
        git -C "$SEED_ROOT" log --oneline "${local_rev}..${remote_rev}" | sed 's/^/    /'
        exit 0
    fi
    log "updating $(echo "$local_rev" | cut -c1-7) -> $(echo "$remote_rev" | cut -c1-7)"
    # Hard reset rather than merge: this is a read-only mirror of the feed, and
    # local divergence would mean someone edited data that should be a commit.
    git -C "$SEED_ROOT" reset --hard FETCH_HEAD --quiet
fi

log "at $(git -C "$SEED_ROOT" rev-parse --short HEAD); run muli-db-seed to apply"
