
# check for dependencies
check_host_commands() {
	local allok=1
	#echo "*** Checking for $NEEDED_HOST_COMMANDS"
	for de in $NEEDED_HOST_COMMANDS ; do
		if ! path=$(which "$de"); then
			echo "#### Missing '$de' host command"
			allok=0
		fi
	done
	if [ "$allok" -eq "0" ]; then
		echo "##### Please install the missing host commands"
		exit 1
	fi
}

hostcheck_commands() {
	for name in $*; do
		local cmd=$(which $name)
		if [ ! -x "$cmd" ]; then
			echo "### ERROR $PACKAGE needs $name"
			HOSTCHECK_FAILED=1
		fi
	done
}

# split the MINIFS_PATH evn and return all existing directories
# also adding the first parameter to the path
minifs_path_split() {
	for pd in $(echo "$MINIFS_PATH"| tr ":" "\n") ; do
		if [ -d "$pd/$1" ]; then
			echo "$pd/$1"
		fi
	done
}

minifs_locate_config_path() {
	local file=$1
	local flags=${2-0}
	local all=$[ $flags & 1 ]
	local verbose=$[ $flags & 2 ]

	for ro in "$CONF_BASE" $(minifs_path_split ""); do
		for di in distro "board/$MINIFS_BOARD" arch/$TARGET_META_ARCH arch/$TARGET_ARCH ""; do
			for pd in $MINIFS_BOARD_ROLE ""; do
				local try="$ro/$di/$pd/$file"
				try=${try//\/\//\/}
				[[ $verbose != 0 ]] && echo try \"$try\" >&2
				if [ -e "$try" ]; then
					echo $try
					[[ $all == 0 ]] && return 0
				fi
			done
		done
	done
}

# calls an optional function(s)
optional() {
	for f in $*; do
		if declare -F $f >/dev/null; then
			$f "$@"
		fi
	done
}

optional_one_of () {
	for f in $*; do
		if declare -F $f >/dev/null; then
			# echo optional-one-of running $f
			$f
			return $?
		fi
	done
}

optional_role () {
	for r in $MINIFS_BOARD_ROLE; do
		echo "$r-$1"
	done
}

# hash set. hset <key> <value>
hset() {
	local ka="${1//-/}"
	local kb="${2//-/}"
	eval "$ka$kb"='$3'
}
hget() {
	local ka="${1//-/}"
	local kb="${2//-/}"
	# echo GET  $1 $2 1>&2
	eval echo '${'"$ka$kb"'#hash}'
}

get_package_dir() {
	local pack=$1
	local dir=$(hget $pack dir)
	dir=${dir:-$pack}
	if [ "$dir" == "." ]; then
		dir=$BUILD
	fi
	if [ -d "/$dir" ]; then
		echo $dir
	elif [ -d "$BUILD/$dir" ]; then
		echo "$BUILD/$dir"
	else
		echo "get_package_dir($pack) not found ($dir)" >&2
		echo /invalid
	fi
}

package() {
	export MINIFS_PACKAGE="$1"
	export PACKAGE="$1"
	export PACKAGE_DIR=$(get_package_dir $PACKAGE)
	local prefix=$(hget $PACKAGE prefix)
	export PACKAGE_PREFIX=${prefix:-/usr}
	pushd "$PACKAGE_DIR" >/dev/null
}
end_package() {
	#echo "#### Building $PACKAGE DONE"
	PACKAGE=""
	LOGFILE="._stray.log"
	popd  >/dev/null
}

configure() {
	local turd="._conf_$PACKAGE"
	LOGFILE="$turd.log"
	if [ ! -f $turd ]; then
		echo "     Configuring $PACKAGE"
		rm -f $turd
		echo "$@" >$LOGFILE
		if "$@" >>$LOGFILE 2>&1 ; then
			touch $turd
		else
			echo "#### ** ERROR ** Configuring $PACKAGE"
			echo "     Check " $(get_package_dir $PACKAGE)/$LOGFILE
			exit 1
		fi
	fi
}

compile() {
	local turd="._compile_$PACKAGE"
	LOGFILE="$turd.log"
	if [ ! -f $turd -o "._conf_$PACKAGE" -nt $turd ]; then
		echo "     Compiling $PACKAGE"
		rm -f $turd
		echo "$@" >$LOGFILE
		if "$@" >>$LOGFILE 2>&1 ; then
			touch $turd
		else
			echo "#### ** ERROR ** Compiling $PACKAGE"
			echo "     Check " $(get_package_dir $PACKAGE)/$LOGFILE
			exit 1
		fi
	fi
}

log_install() {
	local turd="._install_$PACKAGE"
	LOGFILE="$turd.log"
	if [ ! -f $turd -o "._compile_$PACKAGE" -nt $turd ]; then
		echo "     Installing $PACKAGE"
		rm -f $turd
		echo "$@" >$LOGFILE
		if "$@" >>$LOGFILE 2>&1 ; then
			touch $turd
		else
			echo "#### ** ERROR ** Installing $PACKAGE"
			echo "     Check " $(get_package_dir $PACKAGE)/$LOGFILE
			exit 1
		fi
	fi
}

deploy() {
	local turd="._deploy_$PACKAGE"
	LOGFILE="$turd.log"
	if [ -f "._install_$PACKAGE" ]; then
		local deployme=$(hget $PACKAGE deploy)
		if ! ${deployme:=true} ; then return 0; fi
		echo "     Deploying $PACKAGE"
		{
			rm -f $turd
			echo "$@" >$LOGFILE
			"$@" && touch $turd
		} >>$LOGFILE 2>&1 || {
			echo "#### ** ERROR ** Deploying $PACKAGE"
			echo "     Check " $(get_package_dir $PACKAGE)/$LOGFILE
			exit 1
		}
	fi
}

remove_package() {
	pack=$1
	if [ ! -d "$BUILD"/$pack ]; then
		echo Not removing $pack - was not installed anyway
		return
	fi
	if [ -f "$BUILD/$pack/._dist_$pack.log" ]; then
		echo $pack was installed in staging, trying to remove
		cat "$BUILD/$pack/._dist_$pack.log" | \
			awk -v pp="$STAGING" \
'
{
	if ($2=="open" && match($3,pp)) print $3;
	if ($2=="rename" && match($4,pp)) print $4;
}' | 	xargs rm -f
	fi
	rm -rf "$BUILD"/$pack
	echo Looks like $pack was removed. good luck.
}

# This parses the ._dist file generated by installwatch
# and return all pathnames that contains $1 as a regexp, while
# removing any occurance of $2 from them, if present
get_installed_stuff() {
	local dir=$(get_package_dir $pack)
	if [ -f "$dir/._dist_$PACKAGE.log" ]; then
		cat "$dir/._dist_$PACKAGE.log" | \
		awk -v pp="$1" -v ss="$2" \
'
function ppr(s) {
	if (substr(s, length(s)) == "#") return;
	if (ss != "") gsub(ss,"",s);
	print s;
}
{
	if (($2=="open" || $2=="fopen64") && match($3,pp)) l[$3]=$3;
	if ($2=="rename" && match($4,pp)) { delete l[$3]; l[$4]=$4; }
	if ($2=="symlink" && match($4,pp)) { l[$4]=$4; }
}
END { for (p in l) ppr(p); }
'
	fi
}

get_installed_binaries() {
	get_installed_stuff "^$STAGING.*/s?bin/"
	get_installed_stuff "^$STAGING.*/libexec/"
}
# same as previous, without the STAGING path at the front
get_installed_short_binaries() {
	get_installed_stuff "^$STAGING.*/s?bin/" "^$STAGING/?"
	get_installed_stuff "^$STAGING.*/libexec/" "^$STAGING/?"
}
get_installed_etc() {
	get_installed_stuff "^$STAGING.*/etc/"
}

deploy_binaries() {
	local tmpf="$TMPDIR/minifs-$MINIFS_BOARD/install-$PACKAGE.lst"
	{
		set -x
		mkdir -p $TMPDIR/minifs-$MINIFS_BOARD/
		get_installed_short_binaries >$tmpf
		(cd $STAGING; rsync -av --files-from=$tmpf ./ $ROOTFS/ ) >"$tmpf.log"
		set +x
	} || {
		echo $0 $PACKAGE failed; exit 1
	}
}

deploy_staging_path() {
	local src=$1
	local param=$2
	local usr=${param:-/usr}
	echo usr=$usr
	shift 2
	mkdir -p "$ROOTFS/$src/"
	rsync "$@" --delete -av "$STAGING$usr/$src/" "$ROOTFS/$src/"
}

dump_depends() {
	{
	echo 'digraph G { rankdir=LR; node [shape=rect]; '
	local all="$PACKAGES crosstools"
	for pack in $all; do
		deps=$(hget $pack depends)
		echo \"$pack\"
		for d in $deps; do
			echo "\"$pack\" -> \"$d\""
		done
	done
	echo '}'
	} >minifs_deps.dot
	dot -Tpdf -ominifs_deps.pdf minifs_deps.dot
}

package_set_group() {
	local v=$1
	PACKAGE_ORDER=$((v * 1000))
#	echo GROUP $PACKAGE_ORDER
}

package_register() {
	PACKAGES+=" $1"
	hset $1 order $PACKAGE_ORDER
	echo $1 $PACKAGE_ORDER
	let PACKAGE_ORDER=PACKAGE_ORDER+1
}

# these are tools that are needed even before we start decompressing stuff

host-setup() {
	unset CC CXX GCC LD CFLAGS CXXFLAGS CPPFLAGS LDFLAGS ACLOCAL LIBTOOL;
	unset PKG_CONFIG_PATH PKG_CONFIG_LIBDIR LD_LIBRARY_PATH INSTALL;
	export INSTALL=/usr/bin/install
}

hset host-patch url "http://ftp.de.debian.org/debian/pool/main/p/patch/patch_2.7.6.orig.tar.xz"
hset host-patch name "patch"

build-patch() {
	./configure --prefix=$STAGING_TOOLS &&
		make all &&
		make install
}

compile-host-tools() {
#	set -x
	for tool in patch; do
		local url=$(hget host-$tool url)
		local name=$(hget host-$tool name)
		local old_url=$(cat $BUILD/host-$name/._url_$name 2>/dev/null)
		if [ "$old_url" != "$url" ]; then
			echo "** Hosts '$name' need building"
			rm -rf "$STAGING_TOOLS"/bin/$tool \
				$BUILD/host-$name
		fi
		if [ -x "$STAGING_TOOLS"/bin/$tool ]; then
			continue
		fi
		base=${url/*\//}
		if [ ! -f "$BASE/download/$base" ]; then
			echo "** Downloading $base"
			$WGET "$url" -O "$BASE"/download/$base || \
				exit 1
		fi
		rm -rf $BUILD/host-$name && mkdir -p $BUILD/host-$name
		tar xf "$BASE"/download/$base --strip 1  -C $BUILD/host-$name || exit 1
		echo "** Building host $name"
		(
			host-setup
			pushd $BUILD/host-$name
			echo $url >._url_$name
			build-$name
		) >$BUILD/host-$name/._compile_$tool.log 2>&1
	done
	set +x
}
