# "build" command
#
# Copyright (C) 2014  Patrick "P. J." McDermott
#
# This file is part of the ProteanOS Development Kit.
#
# The ProteanOS Development Kit 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 3 of the
# License, or (at your option) any later version.
#
# The ProteanOS Development Kit 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 the ProteanOS Development Kit.  If not, see
# <http://www.gnu.org/licenses/>.

use profile
use chroot
use rand
use package
use control

cmd_build_old_opkbuild=
cmd_build_opkbuild_package=
cmd_build_opkbuild_version=

cmd_build_main()
{
	local root=
	local opkbuild_plat_opt=
	local opkbuild_optstring=
	local arch=
	local plat=
	local first_arg=
	local prev_arg=
	local arg=
	local dir=
	local uname_s=
	local build_deps=
	local f=

	if [ ${#} -lt 2 ]; then
		print_cmd_usage 'build' >&2
		exit 1
	fi

	root="${1}"
	shift 1

	# opkbuild's platform option will be changing from -P to -p.  Detect
	# either, depending on the version of opkbuild installed.
	cmd_build_old_opkbuild=true
	parse_control "${root}/var/lib/opkg/status" \
		cmd_build_opkbuild_field_cb cmd_build_opkbuild_para_cb \
		'Package Version'
	if ${cmd_build_old_opkbuild}; then
		opkbuild_plat_opt='P'
		opkbuild_optstring='bBASFT:a:P:DdCcr:hV'
	else
		opkbuild_plat_opt='p'
		opkbuild_optstring="$(cat \
			"${root}/usr/share/opkbuild/optstring")"
	fi
	arch="$(cat "${root}/etc/proteanos_arch")"
	plat="$(cat "${root}/etc/proteanos_plat")"
	while getopts "${opkbuild_optstring}" opt 2>/dev/null; do
		case "${opt}" in
			a)
				arch="${OPTARG}"
				;;
			${opkbuild_plat_opt})
				plat="${OPTARG}"
				;;
		esac
	done

	first_arg=true
	prev_arg=
	for arg in "${@}"; do
		if ${first_arg}; then
			set --
			first_arg=false
		else
			set -- "${@}" "${prev_arg}"
		fi
		prev_arg="${arg}"
	done

	. "${root}/etc/os-release"
	profile_set "${ID}"

	if ! [ -d "${prev_arg}" ]; then
		error 2 "$(get_msg 'cmd_build_not_a_dir')"
	fi
	package_init "${prev_arg}"
	package_set_substvars "${arch}" "${plat}"

	rand
	dir="/prokit/build.${rand_x}"
	uname_s="$( (uname -s) 2>/dev/null)" || uname_s='unknown'
	mkdir -p "${root}${dir}/pkg"
	case "${uname_s}" in
		'Linux')
			mount -o bind "${prev_arg}" "${root}${dir}/pkg"
			;;
	esac

	build_deps="$(package_get_build_deps "${arch}" "${plat}")"
	if [ "x${build_deps}" != 'x' ]; then
		mkdir -p "${root}${dir}/builddeps/control" \
		"${root}${dir}/builddeps/data"
		cmd_build_make_deps_pkg "${root}${dir}" "${rand_x}" \
			"${build_deps}"
	fi

	chroot_exec "${root}" sh <<-EOF
		cd '${dir}/pkg'
		if [ 'x${build_deps}' != 'x' ]; then
			opkg install ../builddeps.opk
		fi
		opkbuild ${@}
		if [ 'x${build_deps}' != 'x' ]; then
			opkg --autoremove remove prokit-builddeps-${rand_x}
		fi
		EOF

	case "${uname_s}" in
		'Linux')
			umount "${root}${dir}/pkg"
			;;
	esac
	rmdir "${root}${dir}/pkg"
	rm -f "${root}${dir}/builddeps.opk"
	for f in "${root}${dir}/"*; do
		[ -e "${f}" ] || continue
		mv "${f}" "${prev_arg}/.."
	done
	rmdir "${root}${dir}"
}

cmd_build_opkbuild_field_cb()
{
	local name="${1}"
	local value="${2}"

	case "${name}" in
		Package)
			cmd_build_opkbuild_package="${value}"
			;;
		Version)
			cmd_build_opkbuild_version="${value}"
			;;
	esac

	return 0
}

cmd_build_opkbuild_para_cb()
{
	if [ "x${cmd_build_opkbuild_package}" = 'xopkbuild' ]; then
		case "${cmd_build_opkbuild_version}" in
			3.0.0~beta[3-5]-*)
				cmd_build_old_opkbuild=true
				;;
			*)
				cmd_build_old_opkbuild=false
				;;
		esac
		return 1
	fi

	return 0
}

cmd_build_make_deps_pkg()
{
	local build_dir="${1}"
	local build_id="${2}"
	local build_deps="${3}"

	printf '2.0\n' >"${build_dir}/builddeps/debian-binary"
	cat >"${build_dir}/builddeps/control/control" <<-EOF
		Package: prokit-builddeps-${build_id}
		Source: prokit
		Version: 1.0
		Architecture: all
		Platform: all
		Depends: ${build_deps}
		Description: Build dependencies metapackage generated by prokit
		EOF
	(cd "${build_dir}/builddeps/data"; tar -czf ../data.tar.gz .)
	(cd "${build_dir}/builddeps/control"; tar -czf ../control.tar.gz .)
	(cd "${build_dir}/builddeps"; tar -czf ../builddeps.opk \
		'debian-binary' 'data.tar.gz' 'control.tar.gz')
	rm -Rf "${build_dir}/builddeps"
}