#!/usr/bin/env bash

# Copyright (C) 2013-2015 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/>.

default_libdir=/usr/lib/xbs

. "$(librelib messages)"
. "$(librelib conf)"

errusage() {
	if [[ $# -gt 0 ]]; then
		error "$@"
	fi
	usage >&2
	exit 1
}

usage() {
	print 'Usage: %s [-b BUILDSYSTEM|-h] COMMAND [ARGUMENTS]' "${0##*/}"
	print 'Tool for working with arbitrary ABS-like build systems'
	echo
	prose 'This is a pluggable tool.  The BUILDSYSTEM it uses is
	       configured in:'
	bullet '/etc/xbs.conf'
	bullet '${XDG_CONFIG_HOME}/xbs.conf'
	bullet 'with the `-b` flag'
	prose 'Later items take precedence over earlier ones.'
	echo
	prose 'It looks for a helper programs named helper-${BUILDSYSTEM}, in
	       the directory `%q` by default, but this directory can be changed
	       with the environmental variable XBS_LIBDIR.' "$default_libdir"
	echo
	print 'Options:'
	flag "-b $(_ BUILDSYSTEM)" 'Use BUILDSYSTEM instead of the one
	                            configured in xbs.conf' \
	     '-h'                  'Show this message'
	echo
	prose "Whether a command is intended for use on a developer's box or on
	       the server is indicated by (dev), (srv), or (any) before the
	       command"
	echo
	print 'Commands:'
	flag "$(_ '(dev) status')" \
		'Are there uncommitted changes in `.`?' \
	     "$(_ '(dev) download')" \
		'Download or update the tree' \
	     "$(_ '(dev) release-client REPO ARCH')" \
		'Release `.` (for developer boxes)' \
	     "$(_ '(srv) release-server REPO ARCH')" \
		'Release `.` (for server boxes)' \
	     "$(_ '(srv) unrelease PKGBASE REPO ARCH')" \
		'Unrelease a pkgbase' \
	     "$(_ '(srv) move FROMREPO TOREPO PKGBASE')" \
		'Move a pkgbase from one repo to another' \
	     "$(_ '(srv) releasepath PKGBASE REPO ARCH')" \
		'Print the path to the staged version of pkgbase, or exit with
		 non-zero if not released' \
	     "$(_ '(any) name')" \
		'Print a human-friendly version of the BUILDSYSTEM name' \
	     "$(_ '(any) help')" \
		'Show this message'
}

status() {
	if [[ ! -f PKGBUILD ]]; then
		error 'PKGBUILD not found'
		# Though in this file in general it doesn't matter, in
		# this case it does: Using "exit" instead of "return"
		# is imporant because it prevents flow returning to
		# release-client.
		exit 1
	fi
	"$HELPER" status "$@"
}

download() {
	"$HELPER" download "$@"
}

release-client() {
	if ! status; then
		error 'You have not committed your changes yet!'
		exit 1
	fi
	"$HELPER" release-client "$@"
}

release-server() {
	if [[ ! -f PKGBUILD ]]; then
		error 'PKGBUILD not found'
		exit 1
	fi
	"$HELPER" release-server "$@"
}

unrelease() {
	"$HELPER" unrelease "$@"
}

move() {
	"$HELPER" move "$@"
}

releasepath() {
	"$HELPER" releasepath "$@"
}

help() {
	usage
}

name() {
	"$HELPER" name "$@"
}

main() {
	BUILDSYSTEM=''
	while getopts 'b:h' arg; do
		case $arg in
			b) BUILDSYSTEM=$OPTARG;;
			h) usage; return 0;;
			*) errusage;;
		esac
	done
	shift $((OPTIND - 1))

	if [[ -z $BUILDSYSTEM ]]; then
		load_files xbs || return 1
		check_vars xbs BUILDSYSTEM || {
			prose 'or specify the `-b` flag.' >&2
			return 1
		}
	fi
	
	if [[ -z $XBS_LIBDIR ]]; then
		export XBS_LIBDIR=$default_libdir
	fi

	HELPER="${XBS_LIBDIR}/helper-${BUILDSYSTEM}"
	if [[ ! -x "$HELPER" ]]; then
		error 'No helper for build system found: %s' "$BUILDSYSTEM"
		return 1;
	fi

	if [[ $# -lt 1 ]]; then
		errusage "Must specify a command"
	fi

	if [[ -w / ]]; then
		error 'Run as a normal user'
	fi

	local cmd=$1; shift
	case "$cmd" in
		status|download|name|help)
			[[ $# -eq 0 ]] || errusage 'bad number of argments'
			"$cmd" "$@"
			;;
		release-client|release-server)
			[[ $# -eq 2 ]] || errusage 'bad number of argments'
			"$cmd" "$@"
			;;
		move|unrelease|releasepath)
			[[ $# -eq 3 ]] || errusage 'bad number of argments'
			"$cmd" "$@"
			;;
		*) errusage 'unknown command: %s' "$cmd";;
	esac
}

main "$@"
