#!/usr/bin/env bash
set -e

log()  { echo "dist/prepare: $*" >&2; }
warn() { log "warning: $*"; }
die()  { log "error: $*"; exit 1; }

usage() {
	echo "Usage: dist/prepare {-D|-O|-d|-h|-m|-o|-v}"
	echo "       dist/prepare -u {arch|dist|host}"
	echo ""
	echo "  -D    print distribution"
	echo "  -O    print GNU ostype"
	echo "  -d    print \$dist"
	echo "  -h    print GNU hosttype"
	echo "  -m    print GNU machtype (\$arch)"
	echo "  -o    print object directory for chosen -u"
	echo "  -u    use given object directory (arch, dist, host)"
	echo "  -v    print all collected information"
	echo ""
	echo "Object directory types:"
	echo "  arch  \"arch.\$MACHTYPE\""
	echo "  dist  \"dist.\$HOSTTYPE-\$(uname)-\$DIST\""
	echo "  host  \"host.\$(hostname)\""
}

test "$MAKE" ||
test "$MAKELEVEL" ||
	cd "${0%/*}/.."

# Collect OS information

# Variables:
#
#   $OSTYPE	- system		- set by default in GNU bash
#					| with fallback $(uname)
#
#   $HOSTTYPE	- architecture		- set by default in GNU bash
#   					| with fallback $(uname -m)
#
#   $MACHTYPE	- arch-company-system	- set by default in GNU bash
#   					| with fallback $HOSTTYPE-$OSTYPE
#
#   $HOSTNAME	- hostname		- set by default in GNU bash
#					| with fallback $(hostname)
#
#   $DIST	- distro		- detected from various sources
#   					| from /etc/os-release $ID
#   					| from /etc/lsb-release $DISTRIB_ID
#					| from distro-specific files
#
#   $DISTTYPE	- arch-kernel-distro	- built from $HOSTTYPE-$(uname)-$DIST

test "$OSTYPE" || {
	warn "system does not set \$OSTYPE"
	OSTYPE="$(uname)"
}

test "$HOSTTYPE" || {
	warn "system does not set \$HOSTTYPE"
	HOSTTYPE="$(uname -m)"
}

test "$MACHTYPE" || {
	warn "system does not set \$MACHTYPE"
	MACHTYPE="$HOSTTYPE-$OSTYPE"
}

test "$DISTTYPE" || {
	if test -e "/etc/os-release"; then
		DIST=$(. /etc/os-release && echo "$ID")
	elif test -e "/usr/lib/os-release"; then
		DIST=$(. /usr/lib/os-release && echo "$ID")
	elif test -e "/etc/lsb-release"; then
		DIST=$(. /etc/lsb-release && echo "$DISTRIB_ID")
	fi
	if test ! "$DIST"; then
		if test -e "/etc/debian_version"; then
			DIST="debian"
		elif test -e "/etc/fedora-release"; then
			DIST="fedora"
		else
			DIST="unknown"
		fi
	fi
	DISTTYPE="$HOSTTYPE-$(uname)-$DIST"
}

test "$HOSTNAME" || {
	warn "system does not set \$HOSTNAME"
	HOSTNAME="$(hostname)"
}

# Parse command line

nofail=n

while getopts 'DdhmOou:v' OPT; do
	case $OPT in
	D) echo "$DIST"; exit;;
	d) echo "$DISTTYPE"; exit;;
	h) echo "$HOSTTYPE"; exit;;
	m) echo "$MACHTYPE"; exit;;
	O) echo "$OSTYPE"; exit;;
	o) RUNOPT=$OPT; nofail=y;;
	u) out=$OPTARG;;
	v) RUNOPT=$OPT; nofail=y;;
	*) usage; exit 2;;
	esac
done

# Locate the build directory

ARCHOBJ="obj/arch.$MACHTYPE"
DISTOBJ="obj/dist.$DISTTYPE"
HOSTOBJ="obj/host.$HOSTNAME"

if test "$out"; then
	case $out in
	a|arch)	OBJDIR="$ARCHOBJ";;
	d|dist)	OBJDIR="$DISTOBJ";;
	h|host)	OBJDIR="$HOSTOBJ";;
	*)	die "invalid \$out value '$out'";;
	esac
else
	if test "$OBJ"; then
		OBJDIR="$OBJ"
	elif test -L "$HOSTOBJ"; then
		OBJDIR="obj/$(readlink "$HOSTOBJ")"
	else
		OBJDIR="$HOSTOBJ"
	fi
fi

# Handle remaining command-line options

case $RUNOPT in
	"o")	echo "${OBJDIR-$HOSTOBJ}"; exit;;
	"v")	echo "ostype:   O=${OSTYPE-?}";
		echo "dist:     D=${DIST-?}";
		echo "hosttype: h=${HOSTTYPE-?}";
		echo "machtype: m=${MACHTYPE-?}";
		echo "disttype: d=${DISTTYPE-?}";
		echo "obj:      o=${OBJDIR-?}";
		exit;;
esac

# If $OBJ is in the environment, consider it a temporary override; do not touch
# the $HOSTOBJ symlink.

if test "$OBJDIR" = "$OBJ"; then
	if test ! -d "$OBJDIR"; then
		log "creating build directory '$OBJDIR'"
		mkdir -p "$OBJDIR"
	fi
	exit
fi

# Create build directory and re-symlink $HOSTOBJ to point to it

if test "$out" || { test "$OBJDIR" && test ! -d "$OBJDIR"; }; then
	if test -L "$HOSTOBJ"; then
		log "removing old symlink '$HOSTOBJ'"
		rm -f "$HOSTOBJ"
	fi

	log "creating build directory '$OBJDIR'"
	mkdir -p "$OBJDIR"

	if test "$OBJDIR" != "$HOSTOBJ"; then
		if test -d "$HOSTOBJ"; then
			log "removing old host directory '$HOSTOBJ'"
			rm -rf "$HOSTOBJ"
		fi

		log "symlinking '$HOSTOBJ' to shared build directory"
		ln -sf "${OBJDIR##*/}" "$HOSTOBJ"
	fi
fi
