#!/bin/bash
# xgensum [-f] [-c] [-i] [-a arch] [-H hostdir] TEMPLATES ... - update SHA256 sums in templates

usage() {
	echo 'Usage: xgensum [-f] [-c] [-i] [-a arch] [-H hostdir] TEMPLATES ...' >&2
	exit 1
}

target_is_native() {
	tgt="$1"
	host="$(uname -m)"
	case "$host" in
		x86_64)
			case "$tgt" in
				i686*|x86_64*) return 0 ;;
			esac
			;;
		aarch64)
			case "$tgt" in
				armv7*|aarch64*) return 0 ;;
			esac
			;;
	esac
	return 1
}

gensum_template() {
	local template="$1"

	. "$template"

	if [ -z "$FLAG_a" ]; then
		# pick the first supported arch. This is required for packages unavailable for
		# the host arch
		if ! "$XBPS_DISTDIR/xbps-src" show-avail "$pkgname" ; then
			FLAG_a="-a $("$XBPS_DISTDIR/xbps-src" show "$pkgname" | sed -En -e 's/archs:[[:space:]]*([.*]*)/\1/p' | sed -e 's/\*$//' | grep -v -e '^~' | head -n1 )"
		fi
	fi

	# Try to source the build-style as well. This is required for R-cran packages.
	if [ -f "${XBPS_DISTDIR}/common/environment/build-style/${build_style}.sh"  ]; then
		. "${XBPS_DISTDIR}/common/environment/build-style/${build_style}.sh"
	fi

	XBPS_SRCDISTDIR=$("$XBPS_DISTDIR/xbps-src" $FLAG_h show-var XBPS_SRCDISTDIR | tail -1)
	srcdir="$XBPS_SRCDISTDIR/$pkgname-$version"

	if [ -n "$FLAG_f" ]; then
		for f in $distfiles; do
			curfile="${f#*>}"
			curfile="${curfile##*/}"
			distfile="$srcdir/$curfile"
			rm -vf "$distfile"
		done
		"$XBPS_DISTDIR/xbps-src" $FLAG_h -I clean $pkgname
	fi

	"$XBPS_DISTDIR/xbps-src" $FLAG_h $FLAG_a -I fetch $pkgname

	ret=0
	sums=""
	for f in $distfiles; do
		curfile="${f#*>}"
		curfile="${curfile##*/}"
		distfile="$srcdir/$curfile"
		if [ -n "$FLAG_c" ];then
			sum="@"
			case ${distfile} in
			*tar.lzma|*.tar|*.txz|*.tar.xz|*.tbz|*.tar.gz)
				sum+=$(xbps-uhelper digest <(tar xf "$distfile" --to-stdout)) || ret=1
				;;
			*.gz)
				sum+=$(xbps-uhelper digest <(gunzip -c "$distfile")) || ret=1
				;;
			*.tar.bz2|*.bz2)
				sum+=$(xbps-uhelper digest <(bunzip2 -c "$distfile")) || ret=1
				;;
			*.zip)
				if command -v unzip &>/dev/null; then
					sum+=$(xbps-uhelper digest <(unzip -p "$distfile"))
					if [ $? -ne 0 ]; then
						echo "$pkgver: extracting $curfile to pipe."
						ret=1
					fi
				else
					echo "$pkgver: cannot find unzip bin for extraction."
					ret=1
				fi
				;;
			*.rpm)
				if command -v rpmextract &>/dev/null; then
					sum+=$(xbps-uhelper digest <(rpm2cpio "$distfile" | bsdtar xf - --to-stdout))
					if [ $? -ne 0 ]; then
						echo "$pkgver: extracting $curfile to pipe."
						ret=1
					fi
				else
					echo "$pkgver: cannot find rpmextract for extraction."
					ret=1
				fi
				;;
			*.7z)
				if command -v 7z &>/dev/null; then
					sum+=$(xbps-uhelper digest <(7z x -o "$distfile"))
					if [ $? -ne 0 ]; then
						echo "$pkgver: extracting $curfile to pipe."
						ret=1
					fi
				else
					echo "$pkgver: cannot find 7z bin for extraction."
					ret=1
				fi
				;;
			*.txt|*.patch|*.diff)
				sum+=$(xbps-uhelper digest "$distfile") || ret=1
				;;
			*)
				sum=$(xbps-uhelper digest "$distfile") || ret=1

			esac
		else
			sum=$(xbps-uhelper digest "$distfile") || ret=1
		fi
		sums+="${sum%  *}\n "
	done

	sed $FLAG_i -e "/^checksum=/,/^[^ \t]/{
			/^[ \t]/d
			s/^checksum=.*/checksum=\"${sums%\n }\"/
			/^checksum=\"[^ ]*\"/s/\"//g
		}" "$template" || ret=1

	return $ret
}

ARCH=

while getopts fciH:a:h flag; do
	case $flag in
		a) ARCH="$OPTARG" ;;
		f) FLAG_f=1 ;;
		c) FLAG_c=1 ;;
		i) FLAG_i='-i' ;;
		H) FLAG_h="-H $OPTARG" ;;
		h|?) usage ;;
	esac
done

shift $(( OPTIND - 1 ))

XBPS_DISTDIR=$(xdistdir) || exit 1

if [ -n "$ARCH" ]; then
	if target_is_native "$ARCH"; then
		FLAG_a="-A $ARCH"
		XBPS_TARGET_MACHINE="$ARCH"
		if [ "$ARCH" = "${ARCH%-*}" ]; then
			XBPS_TARGET_LIBC="glibc"
		else
			XBPS_TARGET_LIBC="${ARCH#*-}"
		fi
	else
		FLAG_a="-a $ARCH"
		if [ -f "${XBPS_DISTDIR}/common/cross-profiles/${ARCH}.sh" ]; then
			. "${XBPS_DISTDIR}/common/cross-profiles/${ARCH}.sh"
		fi
	fi
fi

rv=0

for template; do
	if [ -f "$template" ]; then
		:
	elif [ -f "$template/template" ]; then
		template="$template/template"
	elif [ -f "$XBPS_DISTDIR/srcpkgs/$template/template" ]; then
		template="$XBPS_DISTDIR/srcpkgs/$template/template"
	else
		echo "xgensum: could not find template: $template" >&2
		rv=$(( rv + 1 ))
		continue
	fi

	( gensum_template "$template" ) || rv=$(( rv + 1 ))
done

exit $rv
