#!/usr/bin/env bash

# Copyright (C) 2012-2017 Luke Shumaker <lukeshu@sbcglobal.net>
#
# License: GNU GPLv2+
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

. "$(librelib messages)"
setup_traps
set -u

lockarch() {
	local arch=$1
	lock 9 "${ABSLIBREDEST}/${arch}.lock" \
		"Waiting for a lock on the ABSLibre release directory for %s" "${arch}"
}

unlockarch() {
	lock_close 9
}

checkgit() {
	if [[ ! -d "${ABSLIBREDEST}/${arch}/.git" ]]; then
		error 'Not a git repository: %s' "${ABSLIBREDEST}/${arch}"
		exit 1
	fi
}

conf() {
	. "$(librelib conf)"
	load_files libretools
	check_vars libretools "$@" || exit 1
}

################################################################################

# Operates on the `abslibre` format[0].  On the client/developer side,
# release-client *copies* files from the `abslibre` tree to an
# `abstree`[1] tree located at `devbox:${ABSLIBREDEST}/${arch}`.  On
# the server side, after those `abstree`s have been uploaded
# (ssh/rsync), release-server *copies* them out of the `abstree` into
# a different `abslibre` on the server, similarly located at
# `repobox:${ABSLIBREDEST}/${arch}`.
#
# [0]: https://projects.parabola.nu/packages/pbs-tools.git/tree/docs/format-abslibre.md
# [1]: https://projects.parabola.nu/packages/pbs-tools.git/tree/docs/format-abstree.md

# The number of arguments and CWD constraints are enforced by the main
# XBS program, no need to check those things here!

# Args: none
# CWD: a directory with a PKGBUILD, in an 'abslibre' tree.
status() {
	[[ -z $(git status -s .) ]]
}

# Args: none
# CWD: anywhere
# Host: developer box
download() {
	conf WORKDIR ABSLIBRERECV ABSLIBRESEND

	gitget -f -p "$ABSLIBRESEND" checkout "$ABSLIBRERECV" "$WORKDIR/abslibre"
}

# Args: REPO ARCH
# CWD: a directory with a PKGBUILD, in an 'abslibre' tree.
# Host: developer box
release-client() {
	local repo=$1
	local arch=$2

	conf ABSLIBREDEST
	local pkgbase pkgdir
	pkgbase="$(load_PKGBUILD >/dev/null; printf '%s\n' "${pkgbase:-${pkgname}}")"
	pkgdir="${ABSLIBREDEST}/${arch}/${repo}/${pkgbase}"
	lockarch "$arch"

	if [[ -e $pkgdir ]]; then
		rm -rf -- "$pkgdir"
	fi

	mkdir -p -- "$pkgdir"
	git ls-files -z | xargs -0 -I{} cp -- {} "$pkgdir"
}

# Args: REPO ARCH
# CWD: a directory with a PKGBUILD, outside of ${ABSLIBREDEST}
# Host: repo
release-server() {
	local repo=$1
	local arch=$2

	conf ABSLIBREDEST
	local pkgbase pkgdir
	pkgbase="$(load_PKGBUILD >/dev/null; printf '%s\n' "${pkgbase:-${pkgname}}")"
	pkgdir="${ABSLIBREDEST}/${arch}/${repo}/${pkgbase}"
	lockarch "$arch"
	checkgit

	if [[ -e $pkgdir ]]; then
		rm -rf -- "$pkgdir"
	fi

	mkdir -p -- "$pkgdir"
	cp -- * "$pkgdir"

	cd "$pkgdir"
	git add .
	git commit -q -m "xbs-abslibre: Release ${repo}/${pkgbase} for ${arch} (by $(id -un))"
}

# Args: PKGBASE REPO ARCH
# CWD: anywhere
# Host: repo
unrelease() {
	local pkgbase=$1
	local repo=$2
	local arch=$3

	conf ABSLIBREDEST
	local pkgdir="${ABSLIBREDEST}/${arch}/${repo}/${pkgbase}"
	lockarch "$arch"
	checkgit

	if [[ -f "${pkgdir}/PKGBUILD" ]]; then
		git rm -qrf -- "$pkgdir"
		git commit -q -m "xbs-abslibre: Remove ${repo}/${pkgbase} from ${arch} (by $(id -un))"
	fi
}

# Args: FROMREPO TOREPO PKGBASE
# CWD: anywhere
# Host: repo
move() {
	local repo_from=$1
	local repo_to=$2
	local pkgbase=$3

	conf ABSLIBREDEST ARCHES

	# Execute each iteration in a subshell so that 'checkgit'
	# bailing for an architecture doesn't abort the entire thing.
	local arch
	for arch in "${ARCHES[@]}" any; do (
		lockarch "$arch"
		checkgit

		local dir_from="${ABSLIBREDEST}/${arch}/${repo_from}/${pkgbase}"
		local dir_to="${ABSLIBREDEST}/${arch}/${repo_to}/${pkgbase}"

		if [[ -f "${dir_from}/PKGBUILD" ]]; then
			if [[ -e "${dir_to}" ]]; then
				git rm -qrf -- "$dir_to"
			fi
			mkdir -p -- "${dir_to%/*}"
			git mv -- "$dir_from" "$dir_to"
			git commit -q -m "xbs-abslibre: Move ${pkgbase} from ${repo_from} to ${repo_to} on ${arch} (by $(id -un))"
		fi
		unlock arch
	) done
}

# Args: PKGBASE REPO ARCH
# CWD: anywhere
# Host: repo
releasepath() {
	local pkgbase=$1
	local repo=$2
	local arch=$3

	conf ABSLIBREDEST
	local pkgdir="${ABSLIBREDEST}/${arch}/${repo}/${pkgbase}"

	lockarch "$arch"

	if [[ -f "${pkgdir}/PKGBUILD" ]]; then
		printf '%s\n' "$pkgdir"
		return 0
	fi

	return 1
}

name() {
	echo ABSLibre
}

case "$1" in
	status|download|release-client|release-server|unrelease|move|releasepath|name) "$@" || exit;;
	*) exit 127;;
esac
