#!/bin/bash
#(echo "db-update:: STAGING=${STAGING}"; ls -l "${STAGING}"/extra) | tee /scratch


set -eE -o pipefail
. "$(dirname "$(readlink -e "$0")")/config"
. "$(dirname "$(readlink -e "$0")")/db-functions"

if (( $# >= 1 )); then
	warning "Calling %s with a specific repository is no longer supported" "${0##*/}"
	exit 1
fi

pushd "${STAGING}" >/dev/null
while read -d '' -r file; do
	pub="${FTP_BASE}/${file}"
	if [[ -f "$pub" ]]; then
		if cmp -s -- "$pub" "$file"; then
			rm -vf -- "$file"
		else
			warning "file already exists: %s" "$file"
		fi
	else
		mkdir -p --mode=2775 -- "${pub%/*}"
		mv -vn "$file" "$pub"
	fi
done < <(find other sources -type f -print0 2>/dev/null)
popd >/dev/null

# Find repos with packages to release
mapfile -t -d '' repos < <(
	for f in "${STAGING}"/**/*${PKGEXTS}; do
		repo=${f%/*}
		repo=${repo##*/}
		if in_array "$repo" "${PKGREPOS[@]}"; then
			printf '%s\0' "$repo"
		fi
	done | sort -uz
)

# TODO: this might lock too much (architectures)
for repo in "${repos[@]}"; do
	for pkgarch in "${ARCHES[@]}"; do
		repo_lock "${repo}" "${pkgarch}" || exit 1
	done
done

# check if packages are valid
for repo in "${repos[@]}"; do
	if ! check_repo_permission "${repo}"; then
		die "You don't have permission to update packages in %s" "$repo"
	fi
	pkgs=($(getpkgfiles "${STAGING}/${repo}/"*${PKGEXTS}))
	if (( $? == 0 )); then
		for pkg in "${pkgs[@]}"; do
			if [[ -h ${pkg} ]]; then
				# As a special hack for
				#  1. inheriting arch=(any) packages between db-import
				#     upstreams, and
				#  2. re-adding previously removed binaries that have not been
				#     cleaned up yet,
				# allow symlinks that point to packages under ${FTP_BASE}/pool/.
				if [[ -f ${pkg} && "$(readlink -f -- "$pkg")" = "${FTP_BASE}"/pool/*${PKGEXTS} ]]; then
					continue
				fi
				die "Package %s is a symbolic link" "$repo/${pkg##*/}"
			fi
			if ! check_pkgfile "${pkg}"; then
				die "Package %s is not consistent with its meta data" "$repo/${pkg##*/}"
			fi
# FIXME: $ pacman-key --verify ~/staging/libre/shiboken6-6.8.0.1-2.parabola1-x86_64.pkg.tar.zst.sig                      ==> ERROR: You do not have sufficient permissions to run this command.
#          ==> ERROR: You do not have sufficient permissions to run this command.
#          ==> Use 'pacman-key --init' to correct the keyring permissions.
#			if ! pacman-key -v "${pkg}.sig" >/dev/null 2>&1; then
      if ! gpg --homedir /etc/pacman.d/gnupg/ "${pkg}.sig" >/dev/null 2>&1; then


# DEBUG BEGIN
echo -e "db-update::DEBUG BEGIN\ndb-update:: die \"Package %s does not have a valid signature\""
echo    "db-update::DEBUG whoami=$(whoami) UID=${UID} EUID=${EUID} pwd=$(pwd)" # repo 10001 10001 /
echo    "db-update::DEBUG   $ pacman-key -v \"${pkg}.sig\"" ; pacman-key -v "${pkg}.sig" ;
echo    "db-update::DEBUG   $ gpg --homedir /etc/pacman.d/gnupg/ \"${pkg}.sig\"" ; gpg --homedir /etc/pacman.d/gnupg/ "${pkg}.sig" ;
_homedir=$HOME/db-update-debug
_datadir=${_homedir}/$(date +%F_%T)
mkdir -p ${_homedir}
if   mkdir ${_datadir}
then ls "${STAGING}/${repo}/"    > ${_datadir}/staging
     echo "${pkgs[@]}"           > ${_datadir}/pkgs
     pacman-key -v "${pkg}.sig" &> ${_datadir}/verify
     cp ${pkg}* ${_datadir}/
     echo "db-update::DEBUG see debug data in ${_datadir}"

fi ; echo "db-update::DEBUG END" ;
# DEBUG END


				die "Package %s does not have a valid signature" "$repo/${pkg##*/}"
			fi
			if ! check_pkgvcs "${pkg}" "${repo}"; then
				die "Package %s is not consistent with %s repository" "$repo/${pkg##*/}" "$VCS"
			fi
			if ! check_pkgrepos "${pkg}"; then


# DEBUG BEGIN
echo -e "db-update::DEBUG BEGIN\ndb-update:: die \"Package %s already exists in another repository\" \"$repo/${pkg##*/}\""
_pkgname="$(getpkgname "${pkg}")"
_pkgver="$( getpkgver  "${pkg}")"
_pkgarch="$(getpkgarch "${pkg}")"
_pkgtar=${FTP_BASE}/${PKGPOOL}/${_pkgname}-${_pkgver}-${_pkgarch}
if   [[ -n "${FTP_BASE}" && -n "${PKGPOOL}"                     ]] && \
     [[ -n "${_pkgname}" && -n "${_pkgver}" && -n "${_pkgarch}" ]] && \
     ls   ${_pkgtar}* | grep -E  '\.(sig|torrent)$'                && \
     ! ls ${_pkgtar}* | grep -Ev '\.(sig|torrent)$'
then _warning="some metadata files exist without an associated package file"
     _warning+="\nthe repo files and DB may be incongruant"
     _warning+="\nif none of the following files are a package file, they should all be deleted"
     _warning+="\nif any of these files are a package file, then something may be mis-configured"
     error "${_warning}" ; ls ${_pkgtar}* || : ; die ;
     # TODO: (or not) mv {} /home/repo/db-update-rejects/
fi
# DEBUG END


				die "Package %s already exists in another repository" "$repo/${pkg##*/}"
			fi
			if ! check_packager "${pkg}"; then
				if [[ $DBSCRIPTS_CONFIG = *.archlinux32 ]]; then
					warning "Package %s does not have a valid packager" "$repo/${pkg##*/}"
				else
					die "Package %s does not have a valid packager" "$repo/${pkg##*/}"
				fi
			fi
			if ! check_buildinfo "${pkg}"; then
				if [[ $DBSCRIPTS_CONFIG = *.archlinuxarm ]]; then
					warning "Package %s does not have a .BUILDINFO file" "$repo/${pkg##*/}"
				else
					die "Package %s does not have a .BUILDINFO file" "$repo/${pkg##*/}"
				fi
			fi
			if ! check_builddir "${pkg}"; then
				if [[ $DBSCRIPTS_CONFIG = *.archlinuxarm ]] || [[ $DBSCRIPTS_CONFIG = *.archlinux32 ]]; then
					warning "Package %s was not built in a chroot" "$repo/${pkg##*/}"
				else
					die "Package %s was not built in a chroot" "$repo/${pkg##*/}"
				fi
			fi
		done
		if ! check_splitpkgs "${repo}" "${pkgs[@]}"; then
			die "Missing split packages for %s" "$repo"
		fi
	else
		die "Could not read %s" "$STAGING"
	fi
done

checked_ln_s() {
	local target=$1
	local link=$2
	if [[ -d "$link" ]]; then
		link+="/${target##*/}"
	fi

	if [[ -h "$link" ]] && [[ "$(readlink -- "$link")" == "$target" ]]; then
		# noop; nothing to do
		return 0;
	fi
	if [[ -e "$link" ]]; then
		# Provide context for the error that `ln` is about to
		# print...
		stat "$link" >&2
	fi
	ln -sT -- "$target" "$link"
}

for repo in "${repos[@]}"; do
	msg "Updating [%s]..." "$repo"
	any_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*-any${PKGEXTS} 2>/dev/null))
	for pkgarch in "${ARCHES[@]}"; do
		add_pkgs=()
		arch_pkgs=($(getpkgfiles "${STAGING}/${repo}/"*"-${pkgarch}"${PKGEXTS} 2>/dev/null))
		for pkg in "${arch_pkgs[@]}" "${any_pkgs[@]}"; do
			pkgfile="${pkg##*/}"
			msg2 '%s (%s)' "$pkgfile" "$pkgarch"
			# any packages might have been moved by the previous run
			if [[ -f ${pkg} ]]; then
				mv_ln "${pkg}" "$FTP_BASE/${PKGPOOL}"
			fi
			checked_ln_s "../../../${PKGPOOL}/${pkgfile}" "$FTP_BASE/$repo/os/${pkgarch}"
			# also move signatures
			if [[ -f ${pkg}.sig ]]; then
				mv_ln "${pkg}.sig" "$FTP_BASE/${PKGPOOL}"
			fi
			if [[ -f $FTP_BASE/${PKGPOOL}/${pkgfile}.sig ]]; then
				checked_ln_s "../../../${PKGPOOL}/${pkgfile}.sig" "$FTP_BASE/$repo/os/${pkgarch}"
			fi
			add_pkgs+=("${pkgfile}")
		done
		if (( ${#add_pkgs[@]} >= 1 )); then
			arch_repo_modify add "${repo}" "${pkgarch}" "${add_pkgs[@]}"
		fi
	done
done

for repo in "${repos[@]}"; do
	for pkgarch in "${ARCHES[@]}"; do
		repo_unlock "${repo}" "${pkgarch}"
	done
done

find "$STAGING" -depth -mindepth 1 -type d -empty -exec rmdir -- {} \;
