#!/usr/bin/env bash

# SPDX-FileCopyrightText: 2021 Robin Vobruba <hoijui.quaero@gmail.com>
#
# SPDX-License-Identifier: Unlicense

# Exit immediately on each error and unset variable;
# see: https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
set -Eeuo pipefail
#set -Eeu

script_dir=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
# shellcheck source=./env
source "$script_dir/env"

APP_NAME="Rust release script"

push="false"

function print_help() {

	script_name="$(basename "$0")"
	echo "${APP_NAME} - Releases a new version of this software."
	echo "Including a commit that changes the Cargo.toml|lock version, and a tag."
	echo
	echo "Usage:"
	echo "  $script_name [OPTION...] [NEW-VERSION]"
	echo "Options:"
	echo "  -h, --help"
	echo "    Show this help message and exit"
	echo "  -p, --push"
	echo "    Also push commit and tag to origin"
	echo "Examples:"
	echo "  $script_name"
}

# read command-line args
POSITIONAL=()
while [[ $# -gt 0 ]]
do
	arg="$1"
	shift # $2 -> $1, $3 -> $2, ...

	case "$arg" in
		-p|--push)
			push="true"
			;;
		-h|--help)
			print_help
			exit 0
			;;
		*) # non-/unknown option
			POSITIONAL+=("$arg") # save it in an array for later
			;;
	esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters

new_version="${1:-}"

if [ -z "${new_version:-}" ]
then
  >&2 echo "ERROR: Please supply the new version as first argument to this script; aborting release process!"
  exit 1
fi

if [ -n "$(git diff --cached --numstat)" ]
then
  >&2 echo "ERROR: There are staged changes in the repo; aborting release process!"
  exit 2
fi

# Refreshes the index, so 'git diff-index' will show correct results.
git update-index --refresh || true > /dev/null
if git diff-index HEAD -- | grep -q "\sCargo\.\(lock\|toml\)\$"
then
  >&2 echo "ERROR: There are changes in Cargo.(toml|lock); aborting release process!"
  exit 3
fi

# Set new version in Cargo.toml
sed -i -e 's|^version[ \t]*=[ \t]*".*"$|version = "'"$new_version"'"|g' "Cargo.toml"

# Set new version in Cargo.lock
awk -e "
BEGIN {
  found = 0
  replaced = 0
}
/^name = \"$NAME\"$/ {
  if (!replaced) {
    found = 1
  }
}
/^version = \".*\"$/ {
  if (found) {
    gsub(\"\\\".*\\\"\", \"\\\"$new_version\\\"\", \$0)
    replaced = 1
    found = 0
  }
}
{
  print(\$0)
}
" < "Cargo.lock" > "Cargo.lock.tmp"
mv "Cargo.lock.tmp" "Cargo.lock"
grep -A 1 "$NAME" < "Cargo.lock"

git add Cargo.toml Cargo.lock
git commit -m "Switch our version to $new_version"
git tag -a -m "Release $NAME version $new_version" "$new_version"

if $push
then
  branch_name="$(git symbolic-ref HEAD 2>/dev/null)" \
    || branch_name="(unnamed branch)" # detached HEAD
  branch_name="${branch_name##refs/heads/}"
  git push origin --tags
  sleep 2
  git push origin "$branch_name"
else
  echo "Ready to release with:"
  echo "git push origin --tags master"
fi
