#!/bin/sh

: "${PORTSDIR:=/usr/ports}"

export PKG_OLD_NOWARN=yes

if [ $( id -u ) -ne 0 ]
then
	echo "This program needs to be run as root"
	return 77	# EX_PERM
fi

if [ -f ${PORTSDIR}/Mk/bsd.pkgng.mk ]; then
	pkgng_mk_dir=${PORTSDIR}/Mk
else
	tmp_pkgng_mk_dir=$(mktemp -dt pkg2ng)
	echo "Fetching bsd.pkgng.mk as it is required for converting installed ports"
	if ! fetch -o $tmp_pkgng_mk_dir http://svn.freebsd.org/ports/head/Mk/bsd.pkgng.mk; then
		echo "bsd.pkgng.mk is required, please checkouts ports and specify PORTSDIR"
		exit 1
	fi
	pkgng_mk_dir=$tmp_pkgng_mk_dir
fi

FORCE_POST=$(make _POSTMKINCLUDED=1 -f ${pkgng_mk_dir}/bsd.pkgng.mk -V _FORCE_POST_PATTERNS)

[ -n "$tmp_pkgng_mk_dir" ] && rm -rf $tmp_pkgng_mk_dir

ARCH=$( uname -m )
failed_pkgs=""
MOVED=0
DBDIR="/var/db"
PKGDB="${DBDIR}/pkg"
PKGBAK="${DBDIR}/pkg.bak"

for PKG in $( pkg_info -Ea )
do
	DB="${PKGDB}/${PKG}"

	# Work around lingering portmaster distfiles showing "corruption"
	if [ ! -e "${DB}/+CONTENTS" ] && [ "$(/bin/ls ${DB})" = "distfiles" ]; then
		continue
	fi

	DESC="${DB}/+DESC"
	if [ ! -e "${PKGBAK}" ]; then
		echo "Creating backup pkg_info(1) database directory in ${PKGBAK}."
		mkdir -p ${PKGBAK}
	fi

	ORIGIN=$(pkg_info -qo ${PKG})
	# register a package only if it's not registered already
	if pkg info -e ${ORIGIN}; then
		echo "${PKG} is already registered."
		if [ -e ${DB} ]; then
			mv ${DB} ${PKGBAK}/${PKG}
			MOVED=1
		fi
		continue
	fi
	PREFX=$(pkg_info -qp ${PKG})
	if [ -d ${PORTSDIR}/${ORIGIN} ]; then
		MAINTAINER=$( make -C ${PORTSDIR}/${ORIGIN} -V MAINTAINER )
		CATEGORIES=$( make -C ${PORTSDIR}/${ORIGIN} -V CATEGORIES | sed -e "s/ /,/g")
		LICENSES=$( make -C ${PORTSDIR}/${ORIGIN} -V LICENSE | sed -e "s/ /,/g")
		LICLOGIC=$(make -C ${PORTSDIR}/${ORIGIN} -V LICENSE_COMB )
		OPTIONS=$(make -C ${PORTSDIR}/${ORIGIN} showconfig | awk 'BEGIN{ line=""; }!/^=/ { gsub(/=/,": ",$1); gsub(/:$/,"",$1); line=line" "$1","; } END{print line}')
		USERS=$(make -C ${PORTSDIR}/${ORIGIN} -V USERS | sed -e "s/ /,/g")
		GROUPS=$(make -C ${PORTSDIR}/${ORIGIN} -V GROUPS | sed -e "s/ /,/g")
	else
		MAINTAINER="unknown"
		CATEGORIES=${ORIGIN%/*}
	fi

	# +CONTENTS
	MDIR=$(mktemp -d /tmp/pkg2ngXXXXX)
	test -f ${DB}/+DISPLAY && cp -f ${DB}/+DISPLAY ${MDIR}
	test -f ${DB}/+MTREE_DIRS && cp -f ${DB}/+MTREE_DIRS ${MDIR}
	test -f ${DB}/+DESC && cp -f ${DB}/+DESC ${MDIR}
	MANIFEST=${MDIR}/+MANIFEST
	PLIST=${MDIR}/plist
	cp -f ${DB}/+INSTALL ${MDIR} 2>/dev/null
	echo "name: ${PKG%-*}" >> ${MANIFEST}
	echo "version: ${PKG##*-}" >> ${MANIFEST}
	echo "origin: ${ORIGIN}" >> ${MANIFEST}
	echo "comment: |" >> ${MANIFEST}
	echo -n "  " >> ${MANIFEST}
	cat ${DB}/+COMMENT >> ${MANIFEST}
	echo "maintainer: ${MAINTAINER}" >> ${MANIFEST}
	echo "prefix: ${PREFX##* }" >> ${MANIFEST}
	echo "licenselogic: ${LICLOGIC:-single}" >> ${MANIFEST}
	test -n "${LICENSES}" && echo "licenses: [${LICENSES}]" >> ${MANIFEST}
	echo "deps:" >> ${MANIFEST}
	pkg_info -qr ${PKG} | while read ignore dep; do
		deporigin=$(pkg_info -qo ${dep})
		echo -e "  ${dep%-*}: { origin: \"${deporigin}\", version: \"${dep##*-}\"}" >> ${MANIFEST}
	done
	egrep -v "^@(name|pkgdep|ignore|conflicts|display)" ${DB}/+CONTENTS >> ${PLIST}
	test -n "${CATEGORIES}" && echo "categories: [${CATEGORIES}]" >> ${MANIFEST}
	test -n "${OPTIONS}" && echo "options: {${OPTIONS}}" >> ${MANIFEST}
	test -n "${USERS}" && echo "users: [${USERS}]" >> ${MANIFEST}
	test -n "${GROUPS}" && echo "groups: [${GROUPS}]" >> ${MANIFEST}

	FORCE_POST=$FORCE_POST pkg register -l -m ${MDIR} -f ${PLIST} ${CMD_ARGS}
	if [ $? -ne 0 ]; then
		echo "Registration of ${PKG} failed." >&2
		cat ${MANIFEST}
		failed_pkgs="${failed_pkgs} ${PKG}"
	else
		rm -rf ${MANIFEST}
	fi

	rm -rf ${MDIR}
done

if [ ${MOVED} -eq 1 ]; then
	echo "Moved old package database to ${PKGBAK}."
fi

if [ -n "${failed_pkgs}" ]; then
	echo "" >&2
	echo "!!! Some packages failed to register !!!" >&2
	echo "Please fix them by upgrading them or removing them" >&2
	echo "or rerun \"PERMISSIVE=yes pkg2ng\" if you *really* must" >&2
	echo "Failed packages: ${failed_pkgs}" >&2
else
	for PKG in $( pkg_info -Ea ); do
		DB="${PKGDB}/${PKG}"
		# Ignore package dirs that only have portmaster 'distfiles' in them
		if [ -e ${DB} ] && [ "$(/bin/ls ${DB})" != "distfiles" ]; then
			cp -pr ${DB} ${PKGBAK}/${PKG}
			# Remove only the files documented in
			# pkg_add(1), then remove ${DB} only if empty
			for f in +COMMENT +CONTENTS +DEINSTALL +DESC \
                                 +DISPLAY +INSTALL +MTREE_DIRS \
			         +POST-DEINSTALL +POST-INSTALL  +REQUIRE \
                                 +REQUIRED_BY ;
			do
			    rm -f ${DB}/$f
			done
			rmdir ${DB} 2>/dev/null || true
			MOVED=1
		fi
	done
	echo "Conversion has been successfully finished"
	echo "Your old packages database has been moved to: ${PKGBAK}."
fi

# Delete the portupgrade pkgdb to avoid discrepencies. It will be auto recreated.
rm -f /var/db/pkg/pkgdb.db > /dev/null 2>&1
