#!/bin/bash
# godist.sh is a template build script for golang applications.
#
# Copyright (c) 2016, The godist.sh Author(s)
#
# Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
#  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
#  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
#  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#  PERFORMANCE OF THIS SOFTWARE.
#

set -eu

DIST_DIR=./_dist

EXTRA_FILES=(
	nmdc-webfrontend.conf.SAMPLE
)

get_package_name() {
	# Binaries are named after the containing folder.
	pwd | tr / $'\n' | tail -n1
}

check_dependencies() {
	# `set -e` will take care of killing the application if the dependency
	# goes unresolved.
	which 7z > /dev/null
	which php > /dev/null
}

get_platform_description() {
	if [[ $GOOS == windows ]] ; then
		echo -n "win"
	else
		echo -n "${GOOS}"
	fi
	
	if [[ $GOARCH == 386 ]] ; then
		echo -n 32
	elif [[ $GOARCH == amd64 ]] ; then
		echo -n 64
	else
		echo -n "-${GOARCH}"
		if [[ -v $GOARM ]] ; then
			echo -n "v${GOARM}"
		fi
	fi
}

pathfix() {
	if [[ $(uname -o) == Cygwin ]] ; then
		cygpath -w "$1"
	else
		echo "$1"
	fi
}

single_build() {
	local version="$1"

	# Determine build output name
	local bin_name=''
	if [[ $GOOS == windows ]] ; then
		local_bin_name="$(get_package_name).exe"
	else
		local_bin_name="$(get_package_name)"
	fi
	
	if [[ -f ./$local_bin_name ]] ; then
		rm -f "./$local_bin_name"
	fi
	
	local tmpdir=$(mktemp -d)
	
	# Platform identifier
	local platform="$(get_platform_description)"
	echo "[INFO] Building ${version} for ${platform}..."
	
	# Build.
	# GOARCH/GOOS supplied in function env
	go build \
		-a \
		-ldflags '-s -w' \
		-gcflags "-trimpath=${GOPATH}" \
		-asmflags "-trimpath=${GOPATH}" \
		-o "$(pathfix "${tmpdir}/${local_bin_name}")"
	
	# Archive.
	if [[ ! -d $DIST_DIR ]] ; then
		mkdir "$DIST_DIR"
	fi
	local archive_name="${DIST_DIR}/$(get_package_name)-${version}-${platform}"
	if [[ $GOOS == windows ]] ; then
		archive_name="${archive_name}.7z"
		7z a -mx9 "$archive_name" "${tmpdir}/${local_bin_name}" "${EXTRA_FILES[@]}" >/dev/null
	else
		archive_name="${archive_name}.tar.xz"
		XZ_OPT='-9' tar caf "$archive_name" -C "${tmpdir}" "${local_bin_name}" -C "$(pwd)" "${EXTRA_FILES[@]}" --owner=0 --group=0 >/dev/null
	fi
	
	# Cleanup
	rm -f "${tmpdir}/${local_bin_name}"
	rmdir "$tmpdir"
	
}

datestamp() {
	( TZ=UTC date +%Y%m%d%H%M%SZ )
}

usage() {
	cat <<EOD
Usage: ./godist.sh [-v VERSION]
EOD
	exit 0
}

main() {

	check_dependencies
	
	if [[ ! -v GOPATH ]] ; then
		echo "Please set GOPATH." >&2
		exit 1
	fi
	if [[ ! -d $GOPATH ]] ; then
		echo "Invalid GOPATH set." >&2
		exit 1
	fi

	local version=""
	while getopts ':v:' flag ; do
		case "$flag" in
			v)
				version="$OPTARG"
			;;
			*)
				usage
			;;
		esac
	done

	if [[ $version == "" ]] ; then
		read -p "Enter version string (blank for timestamp)> " version
		if [[ $version == "" ]] ; then
			version=$(datestamp)
		fi
	fi
	
	if [[ -f ./bindata.go ]] ; then
		rm ./bindata.go
	fi
	go-bindata -nomemcopy -prefix client client
	
	GOARCH=amd64 GOOS=windows single_build "$version"
	GOARCH=386   GOOS=windows single_build "$version"
	GOARCH=amd64 GOOS=linux   single_build "$version"
	GOARCH=386   GOOS=linux   single_build "$version"
	
	# Also make source tarball
	
	local SOURCE_FILES=(
		client/
		build.sh
		Config.go
		main.go
		nmdc-webfrontend.conf.SAMPLE
	)
	XZ_OPT='-9' tar caf "_dist/$(get_package_name)-${version}-src.tar.xz" "${SOURCE_FILES[@]}" --owner=0 --group=0 >/dev/null
	
	echo "[INFO] Build complete."
}

main "$@"
