#!/usr/bin/env bash

set -euo pipefail

xgit() {
	git -c "user.name=Flake Update Bot" -c "user.email=flake-update-bot@clerie.de" "$@"
}

xgit_parent_commits() {
	xgit show -q --format="%P" "$@" | sed "s/ /\n/g"
}

xgit_refs_for_commit() {
	xgit show -q --format="%D" "$@" | sed "s/, /\n/g" | sed -E "s/((.+) -> )?(.+)/\3/g"
}

commit_is_head_of_branch() {
	COMMIT="$1"
	BRANCH="$2"
	xgit_refs_for_commit "${COMMIT}" | grep -E "^${BRANCH}$" > /dev/null
}

no_confirm=""

while [[ $# -gt 0 ]]; do
  case $1 in
  --no-confirm)
    no_confirm=1
    shift
    ;;
  *)
    echo "unknown option: $1"
    exit 1
    ;;
  esac
done

echo "[!] Init git repo"
xgit status > /dev/null || xgit clone gitea@git.clerie.de:clerie/nixfiles.git .

echo "[!] Make sure git repo is up to date"
xgit fetch --all

echo "[!] Checkout master"
xgit checkout master

echo "[!] Update master"
set +e
if ! xgit merge --ff-only origin/master; then
	echo "[!] Merging failed"
	echo "[!] Please clean up master branch and try again"
	exit 1
fi
set -e

echo "[!] Fetch git commit of last hydra run"
echo "[!] Checking https://hydra.clerie.de/jobset/nixfiles/nixfiles-updated-inputs/latest-eval"
GIT_REV_OF_LAST_HYDRA_RUN=$(curl --json "" -X GET -L https://hydra.clerie.de/jobset/nixfiles/nixfiles-updated-inputs/latest-eval 2> /dev/null | \
	jq -r .flake | sed -E "s/.+&rev=(.*)/\1/g")
echo "[!] Last hydra ran from ${GIT_REV_OF_LAST_HYDRA_RUN} (https://git.clerie.de/clerie/nixfiles/commit/${GIT_REV_OF_LAST_HYDRA_RUN})"

echo "[!] Check if commit is current head of origin/updated-inputs"
set +e
if ! commit_is_head_of_branch "${GIT_REV_OF_LAST_HYDRA_RUN}" "origin/updated-inputs"; then
	echo "[!] Commit is not head of origin/updated-inputs"
	echo "[!] Hydra seem to still process the current head of origin/updated-inputs"
	exit 0
fi
set -e

echo "[!] Find out update branch"
PARENT_COMMITS=$(xgit_parent_commits "${GIT_REV_OF_LAST_HYDRA_RUN}")

update_branch=
for commit in $PARENT_COMMITS; do
	set +e
	if update_branch=$(xgit_refs_for_commit "${commit}" | sort -d | grep -E "^origin/updated-inputs-.+$" | head -1); then
		break
	fi
	set -e
done

if [[ -z "$update_branch" ]]; then
	echo "[!] No update branch found"
	exit 0
fi

echo "[!] Update branch $update_branch"

echo "[!] Check if update branch forks from current master"
contains_current_master_head=
for commit in $(git rev-list "${update_branch}"); do
	set +e
	if xgit_refs_for_commit "${commit}" | sort -d | grep -E "^master$" | head -1 > /dev/null; then
		contains_current_master_head=1
		break
	fi
	set -e
done

if [[ -z "$contains_current_master_head" ]]; then
	echo "[!] ${update_branch} does not contain the current master head"
	echo "[!] Cannot merge ${update_branch}"
	exit 0
fi

echo "[!] ${update_branch} can be merged into master"

merge_diff=$(xgit diff --color master "${update_branch}")

if [[ -z $merge_diff ]]; then
	echo "[!] Nothing changes, nothing to merge"
	exit 0
fi

echo "${merge_diff}"

if [[ -z $no_confirm ]]; then
  read -e -r -p "[?] Merge ${update_branch} into master?" confirm
  echo "$confirm" > /dev/null
fi

echo "[!] Merging ${update_branch} into master"

xgit merge --ff-only "${update_branch}"


echo "[!] Merge successful"