#!/bin/sh
signature_key=3683C4B70CFA859F0173F2CCE0DD13EBFC7D5E3E


# Copyright © 2024, 2025  Mattias Andrée (m@maandree.se)
# 
# Copying and distribution of this script, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This script is offered as-is,
# without any warranty.


set -e

fetchinfo () {
	printf '%s\n' "${relpage}" | \
	sed 's/<[^>]*>//g' | \
	sed 's/[[:space:]]\{1,\}/ /g' | \
	sed 's/^ //' | \
	sed 's/ $//' | \
	grep "^$1:" || :
}

readinfo () {
	_line="$(fetchinfo "$@" | cut -d : -f 2- | sed 's/^ //')"
	test "$(printf '%s\n' "${_line}" | wc -l)" = 1 || return 1
	printf '%s\n' "${_line}"
}

readmultiinfo () {
	_line="$(fetchinfo "$@" | cut -d : -f 2- | sed 's/^ //')"
	printf '%s\n' "${_line}"
}

checkhash_ () {
	_file="$1"
	_use="$2"
	_algorithm="$3"
	_expect="$(readmultiinfo "${_algorithm} checksum")"

	test -n "${_expect}" && which "${_use}" >/dev/null || return 1

	_actual="$("${_use}" -- "${_file}" | cut -d ' ' -f 1)"
	test -n "${_actual}" || return 1
	for _known in ${_expect}; do
		if test "${_actual}" = "${_known}"; then
			echo ok
			return 0
		fi
	done
	printf '%s checksum for %s was not recognised\n' "${_algorithm}" "${_file}" >&2
	echo bad
}

checkhash () {
	set +e
	_file="$1"
    	printf '%s %s\n' \
		sha224sum SHA224 \
		sha256sum SHA256 \
		sha384sum SHA384 \
		sha512sum SHA512 \
		sha512-224sum SHA512/224 \
		sha512-256sum SHA512/256 \
		sha3-224sum SHA3-224 \
		sha3-256sum SHA3-256 \
		sha3-384sum SHA3-384 \
		sha3-512sum SHA3-512 \
		b2sum BLAKE2b \
	| (
		_checked=0
		_result=ok
		while read tool name; do
			_result="$(checkhash_ "${_file}" "${tool}" "${name}")"
			if test "${_result}" = ok; then
				_checked=1
			elif test "${_result}" = bad; then
				_checked=1
				_result=bad
				return 1
			else
				: skipped
			fi
		done
		if test "${_checked}" = 0; then
			printf '%s\n' 'No supported checksum found' >&2
			return 1
		fi
		echo "${_result}"
	)
	ret=$?
	set -e
	return $ret
}

signature_key="$(printf '%s\n' "${signature_key}" | tr -d ' ')"

if test $# -lt 1 || test $# -gt 2; then
	printf 'usage: %s package [version]\n' "$0" >&2
	exit 1
fi

set -v

package="$1"
version="$2"

test -n "$package"

if test -z "$version"; then
	version=latest
fi

sigkey="$(curl -L -- "https://maandree.se/.signkey")"
if test ! "${sigkey}" = "${signature_key}"; then
	printf '\n\033[1m%s\033[m,' 'Expected signature keyfile seems to be out of date' >&2
	printf ' %s' 'have a look at https://maandree.se/ to find the newest and verify that it' >&2
	printf ' %s' 'has been signed by the previous key, continue until you find and old key' >&2
	printf ' %s' 'in the signature chain that is signed by '"${signature_key}"' (or older' >&2
	printf ' %s' 'that you trust). Once verified, update `signature_key` at the top of' >&2
	printf ' %s' 'this file to be the newest key, which should be '"${sigkey}"', and' >&2
	printf ' %s' 'import it into your key collection of PGP keys.' >&2
	printf '\n' >&2
	exit 1
fi

relurl="https://maandree.se/rel/${package}/${version}.html"
relpage="$(curl -L -- "${relurl}")"
relpagesig="$(curl -L -- "${relurl}".sig)"

sigtest="$(printf '%s\n' "${relpage}" | (printf '%s\n' "${relpagesig}" | gpg --status-fd=8 --verify - /dev/fd/9) 9<&0 8>&1 1>&2)"
if ! printf '%s\n' "${sigtest}" | grep -q '^\[GNUPG:\] VALIDSIG'" ${sigkey} "; then
	printf '\n\033[1m%s\033[m\n' 'The release metadata page seems to be signed with an unexpected key.' >&2
	exit 1
fi

relversion="$(readinfo 'This version')"
test -n "${relversion}"
test "${version}" = latest || test "${relversion}" = "${version}"
version="${relversion}"

tarurls="$(readmultiinfo 'Tarball')"
tarurls="$(echo "${tarurls}" | grep '\.tar\.gz$' || :)"
test -n "${tarurls}"
unpack='gzip -d | tar -x'
tarext='tar.gz'
tardir="${package}-${version}"
tarfile="${package}-${version}.${tarext}"

if test -f "${tarfile}"; then
	status="$(checkhash "${tarfile}")"
	test -n "${status}"
	test "${status}" = ok
else
	downloaded=0
	for tarurl in ${tarurls}; do
		if ! curl -L -- "${tarurl}" > "${tarfile}"; then
			rm -f -- "${tarfile}"
			continue
		fi
		downloaded=1
		status="$(checkhash "${tarfile}")"
		test -n "${status}"
		test "${status}" = ok
		break
	done
	(( downloaded ))
fi

(fetchinfo 'License' ; fetchinfo '.* dependencies' ; fetchinfo '.* instruction' ; fetchinfo 'News') > new-relmeta
if test -f relmeta; then
	diff -u relmeta new-relmeta
fi
mv new-relmeta relmeta

actualtardir="$(gzip -d < "${tarfile}" | tar -t | head -n 1 | cut -d / -f 1)"
quote () {
	printf '%s\n' | sed "s/'/'"'\\'"''/g" | sed '1s/^/'\'/ | sed '$s/$/'\'/
}
if test ! "${actualtardir}" = "${tardir}"; then
	unpack="${unpack} && mv -- $(quote "${actualtardir}") $(quote "${tardir}")"
fi
unpack="(${unpack})"
reldata="$(printf '%s = %s\n' \
               VERSION "${version}" \
               DVERSION "$(printf '%s\n' "${version}" | tr - .)" \
               TARBALL "${tarfile}" \
               DIRECTORY "${tardir}" \
               UNPACK "${unpack}" \
          )"

if (! test -f release-data.mk) || printf '%s\n' "${reldata}" || diff - release-data.mk >/dev/null; then
	printf '%s\n' "${reldata}" > release-data.mk
fi
