#!/bin/sh
# Package generator
# Install binary set on working dir
# Upgrade ports
#usr var tmp
set -eu
DEST_DIR="/media/disk2/package_gen"
FTP_MIRROR="ftp.fr.freebsd.org"
FBSD_RELEASE="8.2-RELEASE"
ARCH=`uname -m`
PORT_NAME=""
PORT_OPTION=""
COMMAND=""

check_clean() {
    __a=`mount | grep ${DEST_DIR} | awk '{print length($3), $3;}' | sort -rn | awk '{$1=""; print;}`
    if [ -n "$__a" ]; then
        echo "unmounting $__a"
        umount $__a
    fi
	#`'
	#dummy comment for fixing syntax colorization in vim
}

create_working_dirs () {
	DIR_LIST='
rootfs/usr
rootfs/tmp
rootfs/var
rootfs/dev
downloads
rootfs/usr/ports/distfiles
rootfs/usr/ports/packages
'
	for dirname in ${DIR_LIST}; do
		if ! [ -d ${DEST_DIR}/${dirname} ]; then
			if ! mkdir -p ${DEST_DIR}/${dirname}; then
				echo "ERROR, can't create ${DEST_DIR}/${dirname}"
				exit 1
			fi
		fi
	done
}

download_fbsd () {
	if [ -d ${DEST_DIR}/downloads/src ]; then
		echo "Detect directory: ${DEST_DIR}/downloads/src... skip downloading"
		return 0
	fi
	if [ -f /$USER/.netrc ]; then
		mv /$USER/.netrc /$USER/.netrc.bak
	fi

	cat << EOF > /$USER/.netrc
machine ${FTP_MIRROR}

macdef init
prompt off
cd /pub/FreeBSD/releases/${ARCH}/${FBSD_RELEASE}
$ getdir base lib32 src
quit

macdef getdir
! mkdir \$i
mget \$i/*

EOF
	if ! (cd ${DEST_DIR}/downloads; ftp -a ftp://${FTP_MIRROR}); then
		echo "ERROR: Can't download FreeBSD sets from ftp://${FTP_MIRROR}//pub/FreeBSD/releases/${ARCH}/${FBSD_RELEASE}"
		exit 1
	fi
}

install_fbsd () {
	if [ -d ${DEST_DIR}/rootfs/boot/kernel ]; then
		echo "Detect folder ${DEST_DIR}/rootfs/boot... skiping base installation"
	else
		if ! (cd ${DEST_DIR}/downloads/base; echo y | env DESTDIR=${DEST_DIR}/rootfs sh ./install.sh); then
			echo "ERROR: Can't install base into ${DEST_DIR}/rootfs"
			exit 1
		fi
	fi
	if [ -d ${DEST_DIR}/rootfs/usr/lib32 ]; then
		echo "Detect lib32 folder... skiping lib32 lib installation"
	else
		if ! (cd ${DEST_DIR}/downloads/lib32; env DESTDIR=${DEST_DIR}/rootfs sh ./install.sh); then
			echo "ERROR: Can't install lib32 into ${DEST_DIR}/rootfs"
			exit 1
		fi
	fi
	if [ -f ${DEST_DIR}/rootfs/usr/src/sys/kern/bus_if.m ]; then
		echo "Detect src folder... skiping src installation"
	else
		if ! (cd ${DEST_DIR}/downloads/src; env DESTDIR=${DEST_DIR}/rootfs sh ./install.sh all); then
			echo "ERROR: Can't install src into ${DEST_DIR}/rootfs"
			exit 1
		fi
	fi
	return 0
}

update_ports () {
	portsnap fetch update
}

generate_pkg () {
	if [ -z ${PORT_OPTION} ]; then
            BUILD_OPTION=""
        else
            BUILD_OPTION="-m \"${PORT_OPTION}\""
        fi

	# TO DO: Need to add a TRAP condition that unmount unionfs and devfs if error meet during package generation
    if ! mount -t unionfs -o noatime /usr/ports ${DEST_DIR}/rootfs/usr/ports; then
		echo "ERROR: Can't unionfs mount ${DEST_DIR}/rootfs/usr/ports"
		exit 1
	fi
    if ! mount -t devfs devfs ${DEST_DIR}/rootfs/dev; then
		echo "ERROR: Can't devfs mount ${DEST_DIR}/rootfs/dev"
		exit 1
	fi
    cp /etc/resolv.conf ${DEST_DIR}/rootfs/etc/resolv.conf
	# This script use portmaster, install it
	if ! [ -f ${DEST_DIR}/rootfs/usr/local/sbin/portmaster ]; then
        if ! chroot ${DEST_DIR}/rootfs/ /bin/sh -exc 'make -C /usr/ports/ports-mgmt/portmaster BATCH=yes install clean'; then
			echo "ERROR: Can't install portmaster"
			check_clean
			exit 1
		fi
    fi

	# Now install the port, need to start in an eval "", mandatory for using the ${PORT_NAME} variable into chroot
	if [ "${COMMAND}" = "upgrade" ]; then
		if [ -z "${PORT_NAME}" ]; then
			eval "
				chroot ${DEST_DIR}/rootfs /bin/sh -exc \
                	'FORCE_PKG_REGISTER=true; export FORCE_PKG_REGISTER; portmaster --local-packagedir=/usr/ports/packages --no-confirm --packages-local -d -g -B ${BUILD_OPTION} --packages-build -a'
				"
		else
			eval "
				chroot ${DEST_DIR}/rootfs /bin/sh -exc \
					'FORCE_PKG_REGISTER=true; export FORCE_PKG_REGISTER; portmaster --local-packagedir=/usr/ports/packages --no-confirm --packages-local -d -g -B ${BUILD_OPTION} --packages-build -r ${PORT_NAME}'
			"
		fi
		chroot ${DEST_DIR}/rootfs /bin/sh -exc \
                'portmaster -y --clean-packages'
	elif [ "${COMMAND}" = "generate" ]; then
		# If a port have NO_PACKAGE, comment-it
    	if grep -q NO_PACKAGE ${DEST_DIR}/rootfs/usr/ports/${PORT_NAME}/Makefile; then
        	mv ${DEST_DIR}/rootfs/usr/ports/${PORT_NAME}/Makefile ${DEST_DIR}/rootfs/usr/ports/${PORT_NAME}/Makefile.backuped
        	sed 's/NO_PACKAGE/\#NO_PACKAGE/g' ${DEST_DIR}/rootfs/usr/ports/${PORT_NAME}/Makefile.backuped > ${DEST_DIR}/rootfs/usr/ports/${PORT_NAME}/Makefile
    	fi
		eval "
			chroot \${DEST_DIR}/rootfs /bin/sh -exc \
				'portmaster	--local-packagedir=/usr/ports/packages --no-confirm --packages-local -d -g -B ${BUILD_OPTION} --packages-build ${PORT_NAME}'
		"
	elif [ "${COMMAND}" = "replace" ]; then
		if [ ${PORT_NAME} ]; then
            eval "
                chroot ${DEST_DIR}/rootfs /bin/sh -exc \
					'FORCE_PKG_REGISTER=true; export FORCE_PKG_REGISTER; portmaster --local-packagedir=/usr/ports/packages --no-confirm --packages-local -d -g --packages-build -o ${PORT_NAME} ${PORT_OPTION}'
                "
		else
			echo "ERROR: replace need to have a port name"
		fi
	elif [ "${COMMAND}" = "delete" ]; then
		eval "
		chroot ${DEST_DIR}/rootfs /bin/sh -exc \
                'pkg_delete -f ${PORT_NAME}'
		"
	elif [ "${COMMAND}" = "cmd" ]; then
        eval "
        chroot ${DEST_DIR}/rootfs /bin/sh -exc \
                '${PORT_NAME}'
        "

	fi
	rm ${DEST_DIR}/rootfs/etc/resolv.conf
	check_clean
}

usage () {
	echo "Package generator usage:"
	echo "$0 COMMAND [familly/port-name] [build-option]"
	echo "Where COMMAND can be:"
	echo " generate [familly/port-name] [build-option]"
	echo " upgrade [port-name] [build-option]"
	echo " replace familly/port-name familly/port-name"
	echo " delete [familly/port-name]"
	echo "examples:"
	echo "$0 generate sysutils/tmux				: Generate tmux package"
	echo "$0 generate editors/vim-lite -DWITHOUT_X11	: Generate vim-lite package without X11 stuffs"
	echo "$0 generate editors/libreoffice LOCALIZED_LANG=fr		: Generate french libreoffice"
	echo "$0 upgrade					: Upgrade all packages previously generated"
	echo "$0 delete editors/vim-lite			: Delete vim-lite"
	echo "$0 cmd \"pkg_info -R tidy\*\"           : Send customized command"
}
# Main

if [ $# -lt 1 ] ; then
        usage
		exit
fi

if [ $# -ge 1 ] ; then
	COMMAND="$1"
fi

if [ $# -ge 2 ] ; then
	PORT_NAME="$2"
	if [ "${COMMAND}" = "generate" ]; then
		if ! [ -d /usr/ports/${PORT_NAME} ]; then
    		echo "Didn't found /usr/ports/${PORT_NAME}"
    		exit
		fi
	fi
fi

if [ $# -ge 3 ]; then
	PORT_OPTION="$3"
	if [ "${COMMAND}" = "replace" ]; then
        if ! [ -d /usr/ports/${PORT_OPTION} ]; then
            echo "Didn't found /usr/ports/${PORT_OPTION}"
            exit
        fi
    fi
fi

check_clean
create_working_dirs
download_fbsd
install_fbsd
update_ports
generate_pkg
echo "Done"


