#!/usr/bin/env bash
# set -x # uncomment for debug
# Builds packages from ABS recursively. It tries to find dependencies that
# aren't built or need update and then makepkg them in order.

# TODO: fullpkg-find should find packages wich depend on the
#       package to be build, so we can avoid "missing $name.so errors"

# Get repo name. Asumes ${ABSROOT}/repo/package/PKGBUILD
guess_repo() {
	basename $(dirname $(pwd))
}

# This function is stolen from makechrootpkg.
# That probably has some copyright/licensing implications.
copy_files() {

	local copydir="$build_dir/${pkgbase:-${pkgname[0]}}"
	mkdir -p "$copydir"

	# Copy PKGBUILD and sources
	cp PKGBUILD "$copydir"
	(
		load_PKGBUILD
		for file in "${source[@]}"; do
			file="${file%%::*}"
			file="${file##*://*/}"
			if [[ -f $file ]]; then
				cp "$file" "$copydir/"
			elif [[ -f $SRCDEST/$file ]]; then
				cp "$SRCDEST/$file" "$copydir/"
			fi
		done

		# Find all changelog and install files, even inside functions
		for i in 'changelog' 'install'; do
			while read -r file; do
				# evaluate any bash variables used
				eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
				[[ -f $file ]] && cp "$file" "$copydir"
			done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD)
		done
	)
}

# Checks ABSROOT and look for target pkg deps. Adds them if not built or outdated.
find_deps() {
	# Check this level
	load_PKGBUILD

	local repo="${repo:-$(guess_repo)}"
	local pkgbase="${pkgbase:-${pkgname[0]}}"

	if ! pkgbuild-check-nonfree > /dev/null 2> /dev/null; then
		if [ "$?" -eq 15 ]; then
			error "pkgbase" has nonfree issues
			return 15
		fi
	fi

	# Checking any package built, since otherwise e.g. kdebase would
	# be always considered outdated: there is no package built named kdebase.
	# TODO: maybe check for the package requested in case of recursive calls,
	# instead of the first one listed?
	if is_built "${pkgname[0]}" "$(get_full_version "${pkgname[0]}")"; then
		exit 0 # pkg is built and updated
	fi

	# greater levels are built first
	echo "${LEVEL}:${pkgbase}" >>"$build_dir/BUILDORDER"
	# PKGBUILD is already there
	if [ -d "${build_dir}/${pkgbase}" ]; then
		exit 0
		# Copy dir to build_dir
	else
		copy_files

		# to identify repo later
		echo "repo=$repo" > "${build_dir}/${pkgbase}/.INFO"
	fi

	# current package plus a space for every level
	msg2 "%${LEVEL}s${pkgbase}-$(get_full_version)"

	## Check next levels
	declare -i next_level=$LEVEL+1

	# All deps in separate line, only once, without version.
	deps=($(echo "${depends[@]} ${makedepends[@]}" | \
		sed "s/[=<>]\+[^ ]\+//g" | \
		tr ' ' "\n" | \
		sort -u))

	for _dep in ${deps[@]}; do

		local found=false
		# May fail, e.g. since abslibre-mips64el doesn't include
		# arch=any packages.
		local pkgdir=$(toru -p ${_dep}) || true

		if [ -n "$pkgdir" -a -d "${pkgdir}" ]; then
			found=true

			pushd "${pkgdir}" > /dev/null
			# runs itself on dep's PKGBUILD dir
			$0 -l ${next_level} ${build_dir} || return $?
			popd > /dev/null
		fi

		if ! (( found )); then
			echo "dep_not_found:$_dep" >>$build_dir/log
		fi

	done

	## End variable block

	unset next_level dir
}

. libremessages
. $(librelib conf.sh)
load_files makepkg

LEVEL=0
MAXLEVEL=20
CLEANFIRST='false'
UPDATEDB='true'

usage() {

	echo ""
	echo "cd to a dir containing a PKGBUILD and run:"
	echo "$(basename $0) [options] <build_dir>"
	echo ""
	echo "This script will create a build_dir for recursive building"
	echo "it tries to find dependencies that aren't built or need update."
	echo ""
	echo "If no <build_dir> is specified, the script works on a tempdir"
	echo ""
	echo "OPTIONS:"
	echo " -h : this message."
	echo " -A <absroot> : use this ABSROOT."
	echo " -c : clean <build_dir> before working."
	echo " -m <max_level> : check deps until this level"
	echo " -n : don't update pacman db."
	echo ""
	exit 1

}

while getopts 'hA:l:cmn' arg; do
	case "$arg" in
		h) usage ;;
		A) ABSROOT="$OPTARG" ;;
		l) LEVEL="$OPTARG" ;; # hidden option to know dep level.
		c) CLEANFIRST='true' ;;
		m) MAXLEVEL="$OPTARG" ;;
		n) UPDATEDB='false' ;;
	esac
done

if [ ! -r PKGBUILD ]; then
	error "This directory doesnt contain a PKGBUILD"
	usage
fi

shift $(( OPTIND - 1 ))
build_dir="${1}"

if [ "$LEVEL" -eq 0 ]; then

	build_dir="${1:-$(mktemp -d /tmp/fullpkg.XXXXXX)}"

	if [ ! -d "$build_dir" ]; then
		mkdir -p "$build_dir"
	elif "$CLEANFIRST"; then
		# Erase files already in dir
		msg "Cleaning up files in dir"
		find "$build_dir" -mindepth 1 -delete
	fi

	if "$UPDATEDB"; then
		msg "Updating pacman db"
		sudo pacman -Sy --noconfirm || true
	fi

	# make files for log and buildorder
	touch "${build_dir}"/{log,BUILDORDER}
	buildorder="${build_dir}/BUILDORDER"

	msg "Checking dependencies"
fi

find_deps

exit 0