#!/usr/bin/env bash
##
##  Package update helper script which sets new SHA-256 for source bundle.
##
##  Licensed under the Apache License, Version 2.0 (the "License");
##  you may not use this file except in compliance with the License.
##  You may obtain a copy of the License at
##
##    http://www.apache.org/licenses/LICENSE-2.0
##
##  Unless required by applicable law or agreed to in writing, software
##  distributed under the License is distributed on an "AS IS" BASIS,
##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
##  See the License for the specific language governing permissions and
##  limitations under the License.
##

set -e

(( $# )) || {
	echo "Usage: update-checksum [package name] ..."
	echo
	echo "Update TERMUX_PKG_SHA256 of package and optionally commit changes."
	echo
	exit 1
}

REPO_ROOT="$(realpath "$(dirname "$0")/../../")"
IS_GIT_REPOSITORY=false

if git status >/dev/null 2>&1; then
	IS_GIT_REPOSITORY=true
fi

# We'll need these later when sourcing build scripts.
# shellcheck source=scripts/properties.sh
source "$REPO_ROOT/scripts/properties.sh"

for package_dir in "$@"; do
	buildsh_path=
	repo=
	# Did we get the package in the form of ${channel}/${package_dir}?
	if [[ -d "${package_dir}" && -f "${package_dir}/build.sh" ]]; then
		repo="${package_dir%\/*}"
		buildsh_path="${package_dir}/build.sh"
		package_dir="$(basename "${package_dir}")"
	else # If we did not, search each channel listed in repo.json for that package directory.
		for channel in $(jq --raw-output 'del(.pkg_format) | keys | .[]' "$REPO_ROOT/repo.json"); do
			if [[ -d "${channel}/${package_dir}" && -f "${channel}/${package_dir}/build.sh" ]]; then
				repo="$(jq --raw-output ".[\"$channel\"].name | sub(\"^termux-\"; \"\")" "$REPO_ROOT/repo.json")"
				buildsh_path="${channel}/${package_dir}/build.sh"
				package_dir="$(basename "${package_dir}")"
			fi
		done
	fi

	if [[ ! -f "${buildsh_path}" ]]; then
		echo "${package_dir}: skipping as no build.sh found"
		continue
	fi

	# Process substitution creates a subshell, we want to do this
	# to not effect the main scope's variables by sourcing the build script
	mapfile -t new_checksum < <(
		# shellcheck source=/dev/null
		source "${buildsh_path}" 2>/dev/null
		for url in "${TERMUX_PKG_SRCURL[@]}"; do
			echo "Downloading ${url}" >&2
			dl_tmpdir="$(mktemp -d "${TMPDIR-/tmp}/termux.src.dl.XXXXXXXX")"

			if [[ -d "${dl_tmpdir}" ]]; then
				if ! curl --fail --location --retry 3 --output "${dl_tmpdir}/source-bundle" "$url" >&2; then
					rm -rf "${dl_tmpdir}"
				fi

				if [[ -f "${dl_tmpdir}/source-bundle" ]]; then
					sha256sum "${dl_tmpdir}/source-bundle" | awk '{ print $1 }'
				fi

				rm -rf "${dl_tmpdir}"
			fi
		done
	)

	# Did we manage to calculate new checksums?
	(( ${#new_checksum[@]} )) || {
		echo
		echo "${package_dir}: failed to calculate the new checksum"
		continue
		exit 1
	}

	# Replace old SHA-256.
	if (( ${#new_checksum[@]} > 1 )); then
		# If there's more than 1 it's an array.
		# Meaning it's probably multi-line, so use -z
		checksum="(\n$(printf '\\t%s\\n' "${new_checksum[@]}"))"
		sed -zi "s/\(TERMUX_PKG_SHA256=\)([^)]*)/\1${checksum}/g" "${buildsh_path}"
	else
		# Otherwise it's a standard string
		checksum="${new_checksum[0]}"
		sed -i "s/\(TERMUX_PKG_SHA256=\).*/\1${checksum}/g" "${buildsh_path}"
	fi

	# Delete the revision as it shouldn't be present if the package was updated.
	sed -i "/TERMUX_PKG_REVISION=/d" "${buildsh_path}"

	# If we are on Git repository, prompt for committing changes.
	if [[ "${IS_GIT_REPOSITORY}" == "true" ]]; then
		echo
		echo "You are about to commit these changes:"
		echo
		echo "--------------------"
		git --no-pager diff --patch "${buildsh_path}"
		echo "--------------------"
		echo
		echo "bump(${repo}/${package_dir}): $(
			# shellcheck source=/dev/null
			source "${buildsh_path}"
			# $TERMUX_PKG_VERSION may be an array.
			# Make it explicit that we are basing the version in the commit message
			# on the first version in the variable.
			# ${TERMUX_PKG_VERSION[0]} also works fine on non-array variables.
			echo "${TERMUX_PKG_VERSION[0]}" | cut -d: -f2-
		)"
		echo
		read -re -p "Do you want to commit changes ? (y/n) " CHOICE
		echo
		case "${CHOICE}" in
			y|Y)
				git add "${buildsh_path}"
				git commit -m "bump(${repo}/${package_dir}): $(
					# shellcheck source=/dev/null
					source "${buildsh_path}"
					echo "${TERMUX_PKG_VERSION[0]}" | cut -d: -f2-
				)"
			;;
			*) echo "Not committing to Git!";;
		esac
		echo
	fi
done
