#!/bin/sh
#	$Id: pkg_update,v 2.0 2018/03/25 16:55:32 cvs Exp $
#	$FreeBSD: head/ports-mgmt/pkg_jail/files/pkg_update 465528 2018-03-25 16:57:38Z dinoex $
#
# Copyright (c) 2001-2018 by Dirk Meyer. All rights reserved.
#   Im Grund 4, 34317 Habichtswald, Germany
#   Email: dirk.meyer@dinoex.sub.org
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of the author nor the names of any co-contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# -------------------------------------------------------------------------
#
#

quiet_mkdir() {
	for dir in "${@}"
	do
		if test ! -d "${dir}"
		then
			mkdir "${dir}"
		fi
	done
}
#
# clean all data that is listed in mtree
# Usage: cleanmtree prefix local-temp-directory mtree-file
cleanmtree() {
	prefix="${1}"
	tmplocal="${2}"
	mkdir "${tmplocal}"
	mtree -duqn -p "${tmplocal}" -f "${3}" >> /dev/null
	find -d "${tmplocal}" -type d |
	sed "s=${tmplocal}==" |
	while read name
	do
		rmdir "${tmplocal}/${name}"
		if test -d "${prefix}/${name}"
		then
			rmdir "${prefix}/${name}"
		fi
	done
}

# fiter stdin for dirs already in pkg-plist of a port
plist_dir() {
	while read dir
	do
		dirrm="@dirrm ${dir}"
		if test -f pkg-plist
		then
			if fgrep -q -x "${dirrm}" pkg-plist
			then
				continue
			fi
			if fgrep -q -x "%%PORTDOCS%%${dirrm}" pkg-plist
			then
				continue
			fi
		fi
		echo "${dirrm}"
	done
}

# generate sed command file to reverse PLIST_SUB
plist_sub() {
	subs="${1}"
	echo "s=$(make -V PREFIX)/==g" > "${subs}"
	make -V PLIST_SUB |
	awk -F = '
END {
	for (I=0; I<COUNT; I++) {
		MAXL = 0
		MAXJ = 0
		for (J in LVAL) {
			TEST = length( LVAL[J] )
			if ( TEST > MAXL ) {
				MAXL = TEST
				MAXJ = J
			}
		}
		print "s=" LVAL[ MAXJ ] "=%%" LKEY[ MAXJ ] "%%=g"
		LVAL[MAXJ] = ""
	}
}
{
	QT = "\""
	LINE = $0
	gsub( "[ \t]$", "", LINE )
	while ( LINE != "" ) {
		gsub( "^[ \t]*", "", LINE )
		gsub( ":=", "=", LINE )
		if ( ! match( LINE, "^[A-Z][0-9A-Z_]*=" ) ) {
			print "error:" LINE
			break
		}
		KEY = substr( LINE, RSTART, RLENGTH - 1 )
		LINE = substr( LINE, RSTART + RLENGTH )
		if ( substr( LINE, 1, 1 )  == QT ) {
			LINE = substr( LINE, 2 )
			I = index( LINE, "\"" )
			VAL = substr( LINE, 1, I - 1 )
			LINE = substr( LINE, I + 1 )
		} else {
			I = index( LINE, " " )
			VAL = substr( LINE, 1, I - 1 )
			LINE = substr( LINE, I )
		}
		if ( KEY == "LIB32DIR" )
			continue
		if ( KEY == "XAWVER" )
			continue
		if ( VAL == "" )
			continue
		if ( VAL == "@comment " )
			continue
		if ( VAL == "%D" )
			continue
		gsub( "[.]", "[.]", VAL )
		LVAL[ COUNT ] = VAL
		LKEY[ COUNT ] = KEY
		COUNT++
	}
}' >> "${subs}"
}

read_env_local() {
	local_env=""
	if test -f "${fulldir}/Env.local"
	then
		echo "=== Reading ${fulldir}/Env.local"
		local_env=`tr '\n' ' ' < "${fulldir}/Env.local"`
	fi
}

get_mflavor() {
	if test "${1}" != ""
	then
		echo "FLAVOR=${1}"
	fi
}

get_flavor_dir() {
	case "${1}" in
	*@*)
		echo "${1##*@}"
		;;
	esac
}

add_flavor() {
	if test "${1}" != ""
	then
		echo "@${1}"
	fi
}

run_pkg_add() {
	env ${pkg_env} ${local_env} pkg add "${pkgfile}"
	installed=`pkg query -e "%o == ${dir}" '%o'`
	if test "${installed}" = "${dir}"
	then
		return 0
	fi
	return 1
}

run_pkg_installed() {
	# more then one Flavor can be installed
	installed=`pkg query -e "%o == ${dir}" '%o' | head -1`
	if test "${installed}" = "${dir}"
	then
		echo "#installed:	${pkgname} from ${dir}"
		return 0
	fi
	return 1
}

run_pkg_match() {
	pkgname=`run_pkg_info_installed "${origin}"`
	required_by=`pkg info --required-by "${pkgname}" | wc -l`
	if test "${required_by}" -gt 1
	then
#		echo "${origin} (dependency)"
		return 0
	fi
	echo "${origin}"
	return 0
}

run_pkg_add_missing() {
	pkgname=`make -V PKGNAME`
	pkgfile=`make -V PKGFILE`
	dir="${fulldir##${portsdir}/}"
	dir="${dir##${localdir}/}"
	installed=`pkg query -e "%o == ${dir}" '%o'`
	if test "${installed}" = "${dir}"
	then
		return 1
	fi
	if test ! -e "${pkgfile}"
	then
		return 0
	fi
	if run_pkg_add
	then
		return 1
	fi
	return 0
}

run_pkg_delete() {
	pkgname=`make -V PKGNAME`
	${pkg} delete "${pkgname}"
}

run_pkg_delete_all() {
	installed=`pkg query -e '%p == /usr/local' '%o'; pkg query -e '%p == /compat/linux' '%o';`
	if test "${installed}" = ""
	then
		return
	fi
	${pkg} delete -y -f ${installed}
	return
}

run_pkg_info_installed() {
	${pkg} query -e "%o == ${1}" '%o'
}

run_pkg_info_origin_file() {
	pflavor=`${pkg} info -q --annotations -F "${1}" | grep "^flavor"`
	pflavor="${pflavor##flavor*: }"
	porigin=`${pkg} info -q -o -F "${1}"`
	if test "${pflavor}" = ""
	then
		echo "${porigin}"
	else
		echo "${porigin}@${pflavor}"
	fi
}

run_pkg_info_origin_name() {
	${pkg} info -q -o "${1}"
}

run_pkg_info_origin_all() {
	${pkg} query '%o'
}

run_pkg_info_dependecies() {
	${pkg} info -q --dependencies -F "${1}"
}

run_pkg_info_list() {
	${pkg} info
}

run_pkg_info_requiredby() {
	${pkg} info -q -r "${1}"
}

dependency_is_good() {
	if test ! -d "${fulldir}"
	then
		echo "Directory not found: ${fulldir}"
		echo "Directory not found: ${fulldir}" >> ${tmpupdated}
		return 1
	fi
	dir="${fulldir##${portsdir}/}"
	dir="${dir##${localdir}/}"
	if test "${dir}" = ""
	then
		echo "Directory bad: ${fulldir}"
		echo "Directory bad: ${fulldir}" >> ${tmpupdated}
		return 1
	fi
	pkgname=`cd ${fulldir} && make -V PKGNAME`
	if run_pkg_installed
	then
		return 2
	fi
	pkgfile=`cd ${fulldir} && make -V PKGFILE`
	if test -e ${pkgfile}
	then
		return 0
	fi
	noinstall=`cd "${fulldir}" && make -V NO_INSTALL`
	case "${noinstall}" in
	yes|YES)
		return 2
		;;
	esac
	echo "# missing package: ${pkgname} from ${dir}"
	echo "# missing package: ${pkgname} from ${dir}" >> ${tmpupdated}
	return 3
}

# check dependencies and decides if a ports needs to be rebuild
# Usage: port_uptodate show
# Usage: port_uptodate make
port_uptodate() {
	tmpupdated="/tmp/port-updated.$$"
	tmpfailed="/tmp/port-failed.$$"
	mflavor=`get_mflavor "${2}"`
	add_flavor=`add_flavor ${2}`
	case "${1}" in
	show)
		rm -f "${logdir}/"show*
		;;
	esac
	#
	case "${1}" in
	show*|make*)
		dir="$(make -V PKGORIGIN)"
		base="${portsdir}/${dir}"
		base1=`pwd`
		base2=`cd "${base}" && pwd`
		if test ! "${base1}" = "${base2}"
		then
			echo "# WARNING: PKGORIGIN=${base2} does not match ${base1}"
			echo "# WARNING: using ${base}"
		fi
		echo "## ${base}: port_uptodate ${1} ${2}"
		pkgname=`make -V PKGNAME ${mflavor}`
		pkgfile=`make -V PKGFILE ${mflavor}`
		mainpkg="${pkgname}"
		for=""
		found=""
		mainpkgfile=""
		rm -f "${tmpupdated}" "${tmpfailed}"
		if run_pkg_installed
		then
			found="1"
		else
			if test -e ${pkgfile}
			then
				echo "pkg_add ${pkgfile}"
				mainpkgfile="${pkgfile}"
				found="1"
			fi
		fi
		;;
	*)
		echo "port_uptodate: bad arguments" >&2
		return 64
		;;
	esac
	#
	# creates dependency
	env ${pkg_env} make checksum ${mflavor} >&2
	#
	if test ! -e "${depends}"
	then
		# create empy list
		touch "${depends}"
	fi
	#
	for depdir_flavors in `
	(
		env ${pkg_env} make build-depends-list ${mflavor}
		env ${pkg_env} make package-depends-list ${mflavor} | cut -d " " -f2
	) |
	sed -f "${depends}"`
	do
		fulldir="${depdir_flavors%@*}"
		flavor=`get_flavor_dir "${depdir_flavors}"`
		dir=""
		pkgname=""
		pkgfile=""
		dependency_is_good "${1}"
		err="${?}"
		case "${err}" in
		0) # exist
			echo "dependency_is_good"
			log=`echo "${dir}${add_flavor}" | sed -e 's=/=,=g'`
			case "${1}" in
			xshow*)
				if test ! -f "${logdir}/show,${log}"
				then
					# check dependend package is ok!
					( cd ${fulldir} && port_uptodate ${1}+ ${flavor} )
					touch "${logdir}/show,${log}"
				fi
				;;
			xmake*)
				if test ! -f "${logdir}/check,${log}"
				then
					# check dependend package is ok!
					( cd ${fulldir} && port_uptodate ${1}+ ${flavor} )
					touch "${logdir}/check,${log}"
					if run_pkg_installed
					then
						continue
					fi
				fi
				;;
			esac

			if test "${mainpkgfile}" != ""
			then
				if test "${pkgfile}" -nt "${mainpkgfile}"
				then
					echo "# dependend package newer: ${pkgfile} ${mainpkgfile}"
					echo "# dependend package newer: ${pkgfile} ${mainpkgfile}" >> ${tmpupdated}
				fi
			fi
			echo "#existing package:	${pkgname} from ${dir}${for}"
			echo "pkg_add ${pkgfile}"
			case "${1}" in
			make*)
				if run_pkg_add
				then
					continue
				fi
				echo "pkg_add ${pkgfile} failed, no ${pkgname}!"
				echo "=== dependend package failed to add: ${pkgfile} ${pkgname}" >&2
				echo "=== dependend package failed to add: ${pkgfile} ${pkgname}" >> ${tmpfailed}
				echo "=== dependend package failed to add: ${pkgfile} ${pkgname}" >> ${logdir}/err,${log}
				break
				;;
			esac
			continue
			;;
		1) # abort
			break
			;;
		2) # installed
			continue
			;;
		3) # missing
			log=`echo "${dir}${add_flavor}" | sed -e 's=/=,=g'`
			case "${1}" in
			make*)
				echo "cd ${fulldir} && port_uptodate ${1}+ ${flavor}"
				( cd ${fulldir} && port_uptodate ${1}+ ${flavor} )
				if run_pkg_installed
				then
					continue
				fi
				echo "=== package ${pkgname} error dependency" >&2
				echo "=== package ${pkgname} error dependency" >> ${tmpfailed}
				echo "=== package ${pkgname} error dependency" >> ${logdir}/err,${log}
				break
				;;
			esac
			;;
		esac
	done
	pkgname="${mainpkg}"
	mflavor=`get_mflavor "${2}"`
	if test -e "${tmpfailed}"
	then
		fulldir=`pwd`
		dir="${fulldir##${portsdir}/}"
		dir="${dir##${localdir}/}"
		echo "=====================================" >&2
		echo "=== package ${pkgname} missing dependency" >&2
		cat ${tmpfailed} >&2
		echo "=====================================" >&2
		if test "${dir}" != ""
		then
			log=`echo "${dir}${add_flavor}" | sed -e 's=/=,=g'`
			cat ${tmpfailed} >> ${logdir}/err,${log}
		fi
		rm -f "${tmpfailed}" "${tmpupdated}"
		return 1
	fi
	if test "${found}" = "" -o -e "${tmpupdated}"
	then
		rm -f "${tmpupdated}"
		dir="${base##${portsdir}/}"
		dir="${dir##${localdir}/}"
		log=`echo "${dir}${add_flavor}" | sed -e 's=/=,=g'`
		local_env=""
		if test -f "${base}/Env.local"
		then
			echo "=== Reading ${base}/Env.local"
			local_env=`tr '\n' ' ' < "${base}/Env.local"`
		fi
		prefix="/usr/local"
		if test ! -d "${prefix}"
		then
			mkdir -p "${prefix}"
		fi
		echo "cd ${base} && env ${pkg_env} ${local_env} make package ${mflavor} > ${logdir}/err,${log} 2>&1"
		case "${1}" in
		make*)
			( cd "${base}" && env ${pkg_env} ${local_env} make package ${mflavor} </dev/null >> "${logdir}/err,${log}" 2>&1 )
			pkgfile=`cd "${base}" && make -V PKGFILE`
			if test -e "${pkgfile}"
			then
				if test -f "${logdir}/build,${log}"
				then
					mv -f "${logdir}/build,${log}" "${logdir}/last,${log}"
				fi
				( cd ${base} && env ${pkg_env} make stage-qa check-orphans check-sanity </dev/null >> "${logdir}/err,${log}" 2>&1 )
				mv -f "${logdir}/err,${log}" "${logdir}/build,${log}"
				( cd ${base} && env ${pkg_env} make clean NOCLEANDEPENDS=yes ${mflavor} )
				if run_pkg_installed
				then
					return 0
				fi
				noinstall=`cd "${base}" && make -V NO_INSTALL`
				case "${noinstall}" in
				yes|YES)
					return 0
					;;
				esac
				nostage=`cd "${base}" && make -V NO_STAGE`
				case "${nostage}" in
				yes|YES)
					echo "=====================================" >&2
					echo "=== package ${pkgname} was not installed" >&2
					echo "=====================================" >&2
					echo "=== package ${pkgname} was not installed" \
						>> ${logdir}/err,${log}
					return 2
					;;
				*)
					# install staged package
					pkgfile=`cd "${base}" && make -V PKGFILE`
					if run_pkg_add
					then
						return 0
					fi
					echo "=====================================" >&2
					echo "=== pkg_add ${pkgfile}, no ${pkgname}!" >&2
					echo "=====================================" >&2
					echo "=== package ${pkgname} can not be installed" \
						>> ${logdir}/err,${log}
					return 2
				esac
			fi
			pkgfile=`cd "${base}" && make -V PKGFILE`
			if test -e "${pkgfile}"
			then
				if test -f "${logdir}/build,${log}"
				then
					mv -f "${logdir}/build,${log}" "${logdir}/last,${log}"
				fi
				mv -f "${logdir}/err,${log}" "${logdir}/build,${log}"
				( cd ${base} && env ${pkg_env} make clean NOCLEANDEPENDS=yes )
				return 0
			else
				echo "=====================================" >&2
				echo "=== package ${pkgname} was not build" >&2
				echo "=====================================" >&2
				echo "=== package ${pkgname} was not build" \
					>> ${logdir}/err,${log}
				return 2
			fi
			;;
		show*)
			echo "if test ! -e \"${pkg_dbdir}/${mainpkg}/+CONTENTS\""
			echo "then"
			echo "  echo \"=====================================\" >&2"
			echo "  echo \"=== package ${pkgname} was not build\" >&2"
			echo "  echo \"=====================================\" >&2"
			echo "  exit 2"
			echo "fi"
			echo "mv -f \"${logdir}/err,${log}\" \"${logdir}/build,${log}\""
			return 1
			;;
		esac
	else
		rm -f "${tmpupdated}"
		if test "${found}" = "1"
		then
			echo "#ok"
			return 0
		fi
		echo "#not made"
		return 1
	fi
}

# make all packages to build a port in a clean jail
# Usage: make_packages_in_dir directory
make_packages_in_dir() {
	tmpshow="/tmp/check-package.$$"
	dir="${1%@*}"
	main_flavor=`get_flavor_dir "${1}"`
	if test "${dir}" = ""
	then
		return
	fi
	if test ! -d "${dir}"
	then
		dir="${portsdir}/${dir}"
	fi
	if test -d "${dir}"
	then
		(
		echo ""
		echo "# checking: ${dir} ${main_flavor}"
		cd "${dir}" || return 69

		wrkdir=`make -V WRKDIRPREFIX`
		prefix="/usr/local"
		if ! test "${wrkdir}" = ""
		then
			rm -rf "${wrkdir}"/*
			run_pkg_delete_all
			rm -rf "${prefix}"/*
		fi

		port_uptodate show ${main_flavor} > "${tmpshow}"
		err="${?}"

		case "${err}" in
		1)
			port_uptodate make ${main_flavor}
			err="${?}"
			if test "${err}" != "0"
			then
				echo "port_uptodate: aborted!"
				return
			fi

			env ${pkg_env} make deinstall
			run_pkg_delete_all
			if test -f ${localdir}/data/badfiles
			then
				grep -v "^#" ${localdir}/data/badfiles |
				while read bad
				do
					if test -f "${bad}"
					then
						rm -f "${bad}"
					fi
					if test -L "${bad}"
					then
						rm -f "${bad}"
					fi
				done
			fi
			if test -f ${localdir}/data/baddirs
			then
				grep -v "^#" ${localdir}/data/baddirs |
				while read bad
				do
					if test -d "${bad}"
					then
						rmdir "${bad}"
					fi
				done
			fi
			plistlog="${logdir}/plist,$(make -V PKGORIGIN | sed -e 's=/=,=')${add_flavor}"
			subs="${plistlog}.sed"
			plist_sub "${subs}"
			echo -n "" > "${plistlog}"
			if test -d /root/GNUstep
			then
				find -d /root/GNUstep -type f >> "${plistlog}"
				find -d /root/GNUstep -type d |
				sed -e 's=^=@dirrm =' >> "${plistlog}"
				rm -rf /root/GNUstep
			fi
			if test -d "${prefix}"
			then
				find -d "${prefix}" -type f -or -type l |
				sort |
				sed -f "${subs}" >> "${plistlog}"
				if test -f "${portsdir}/Templates/BSD.local.dist"
				then
					cleanmtree "${prefix}" /tmp/local \
						"${portsdir}/Templates/BSD.local.dist"
				else
					cleanmtree "${prefix}" /tmp/local \
						"/etc/mtree/BSD.local.dist"
				fi
				if test -d "${prefix}"
				then
					find -d "${prefix}" -type d |
					sort -r |
					sed -f "${subs}" |
					plist_dir >> "${plistlog}"
				fi
			fi
			rm -f "${subs}"
			if test ! -s "${plistlog}"
			then
				rm -f "${plistlog}"
			fi
			;;
		esac
		rm -f "${tmpshow}"
		)
	else
		case "${dir}" in
		'')
			;;
		*nonexistent)
			;;
		*)
			echo "## dir does not exist: ${dir}"
			echo "## dir does not exist: ${dir}" \
				>> ${localdir}/make-packages.errlog
			;;
		esac
	fi
}
#
# make all packages to build and install a port to a host
# Usage: add_packages_in_dir directory
add_packages_in_dir() {
	tmpshow="/tmp/check-package.$$"
	fulldir="${1%@*}"
	main_flavor=`get_flavor_dir "${1}"`
	if test "${fulldir}" = ""
	then
		return
	fi
	case "${fulldir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${fulldir}"
	then
		xdir="${portsdir}/${dir}"
		if test ! -d "${xdir}"
		then
			echo "## dir does not exist: ${fulldir}"
			return
		fi
		fulldir="${xdir}"
	fi

	(
	echo "# checking: ${fulldir}"
	cd "${fulldir}" || return 69

	port_uptodate show ${main_flavor} > "${tmpshow}"
	err="${?}"
	case "${err}" in
	0)
		if run_pkg_add_missing
		then
			exit 1
		fi
		;;
	1)
		port_uptodate make ${main_flavor}
		;;
	esac
	rm -f "${tmpshow}"
	)
}
#
# install the existing packages from a port to a host
# Usage: install_packages_in_dir directory
install_packages_in_dir() {
	fulldir="${1%@*}"
	main_flavor=`get_flavor_dir "${1}"`
	if test "${fulldir}" = ""
	then
		return
	fi
	case "${fulldir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${fulldir}"
	then
		xdir="${portsdir}/${fulldir}"
		if test ! -d "${xdir}"
		then
			movedto=`get_new_origin "${fulldir}"`
			if test "${movedto}" = "nonexistent"
			then
				echo "## port removed: ${fulldir}"
				return
			fi
			if test "${movedto}" = "${dir}"
			then
				echo "## dir does not exist: ${fulldir}"
				return
			fi
			echo "## dir moved: ${dir} -> ${movedto}"
			xdir="${portsdir}/${movedto}"
			if test ! -d "${xdir}"
			then
				echo "## dir does not exist: ${movedto}"
				return
			fi
		fi
		fulldir="${xdir}"
	fi

#	echo "# checking: ${dir}"
	(
	cd "${fulldir}" || return 69
	if run_pkg_add_missing
	then
		echo "## package does not exist: ${pkgfile}"
		echo "(cd ${fulldir} && make package ${main_flavor})"
	fi
	)
}
#
# show the existing packages from a port to a host
# Usage: show_packages_in_dir directory
show_packages_in_dir() {
	fulldir="${1%@*}"
	main_flavor=`get_flavor_dir "${1}"`
	if test "${fulldir}" = ""
	then
		return
	fi
	case "${fulldir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${fulldir}"
	then
		xdir="${portsdir}/${dir}"
		if test ! -d "${xdir}"
		then
			echo "## dir does not exist: ${fulldir}"
			return
		fi
		fulldir="${xdir}"
	fi

	(
#	echo "# checking: ${fulldir}"
	cd "${fulldir}" || return 69
	if run_pkg_add_missing
	then
		echo "## package does not exist: ${pkgfile}"
		echo "(cd ${dir} && make package ${main_flavor})"
	fi
	)
}
#
# delete the existing packages on this host
# Usage: deinstall_packages_in_dir directory
deinstall_packages_in_dir() {
	fulldir="${1}"
	if test "${fulldir}" = ""
	then
		return
	fi
	case "${fulldir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${fulldir}"
	then
		xdir="${portsdir}/${fulldir}"
		if test ! -d "${xdir}"
		then
			echo "## dir does not exist: ${dir}"
			return
		fi
		fulldir="${xdir}"
	fi

	(
#	echo "# checking: ${fulldir}"
	cd "${fulldir}" || return 69
	run_pkg_delete "${pkgname}"
	)
}
#
#
# show the existing packages from a port to a host
# Usage: show_missing_packages_in_dir directory
show_missing_packages_in_dir() {
	dir="${1}"
	if test "${dir}" = ""
	then
		return
	fi
	case "${dir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${dir}"
	then
		xdir="${portsdir}/${dir}"
		if test ! -d "${xdir}"
		then
			echo "## dir does not exist: ${dir}"
			return
		fi
		dir="${xdir}"
	fi

	(
#	echo "# checking: ${dir}"
	cd "${dir}" || return 69
	pkgfile=`make -V PKGFILE`
	if test -f "${pkgfile}"
	then
		return
	fi
	echo "## package does not exist: ${pkgfile}"
	echo "(cd ${dir} && make package)"
	)
}
#
# fetch the distfiles for a port
# Usage: fetch_distfiles_in_dir directory
fetch_distfiles_in_dir() {
	dir="${1}"
	if test "${dir}" = ""
	then
		return
	fi
	case "${dir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${dir}"
	then
		xdir="${portsdir}/${dir}"
		if test ! -d "${xdir}"
		then
			echo "## dir does not exist: ${dir}"
			return
		fi
		dir="${xdir}"
	fi

	(
	echo "# checking: ${dir}"
	cd "${dir}" || return 69

	make fetch
	)
}
#
# fetch the distfiles for a port
# Usage: fetch_recursive_distfiles_in_dir directory
fetch_recursive_distfiles_in_dir() {
	dir="${1}"
	if test "${dir}" = ""
	then
		return
	fi
	case "${dir}" in
	*nonexistent)
		return
		;;
	esac
	if test ! -d "${dir}"
	then
		xdir="${portsdir}/${dir}"
		if test ! -d "${xdir}"
		then
			echo "## dir does not exist: ${dir}"
			return
		fi
		dir="${xdir}"
	fi

	(
	echo "# checking: ${dir}"
	cd "${dir}" || return 69

	make fetch-recursive
	)
}
#
#
#
move_dependent_away() {
	local incache
	grep -l -r "^${1}"'$' "${pkginfo_cache}/" |
	while read incache
	do
		file="${incache#${pkginfo_cache}/}"
		move_away "${file}"
		if test -f "${incache}"
		then
			# obsolte cache file
			rm -f "${incache}"
		fi
	done
}
#
# move outdated package int seperate dir for cleanup
# usage: move_away package
move_away() {
	if test -d "${pkgold}" -a -f "${1}"
	then
		# move it if the "Old" directory exists.
		mv -f "${1}" "${pkgold}/${1}"
		file="${1##*/}"
		saved="${pkginfo_cache}/${file}"
		if test -f "${saved}"
		then
			rm -f "${saved}"
		fi
		move_dependent_away "${file%${ext}}"
	fi
}
#
# cache pkg_info -r
# usage: pkg_info_dependecies  package
pkg_info_dependecies()
{
	file="${1##*/}"
	saved="${pkginfo_cache}/${file}"
	if test "${saved}" -nt "${1}"
	then
		cat "${saved}"
		return
	fi
	run_pkg_info_dependecies "${1}" |
	tee "${saved}"
}

#
# check all packages in ${PACKAGES}/All/
# Usage: clean_package_all
clean_package_all() {
	(
	cd ${pkgall} || exit 69
	for i in *
	do
		# is the package already moved away?
		if test ! -f "${i}"
		then
			continue
		fi
		case "${i}" in
		digests.txz|meta.txz|packagesite.txz)
			continue
			;;
		esac
		# ist this package up to date?
		origin_flavors=`run_pkg_info_origin_file "${i}"`
                origin="${origin_flavors%@*}"
                flavor=`get_flavor_dir "${origin_flavors}"`
                mflavor=`get_mflavor "${flavor}"`
		if test "${origin}" = ""
		then
			echo "${i}: missing origin"
			move_away ${i}
			continue
		fi
		depdir="${portsdir}/${origin}"
		if test ! -d "${depdir}"
		then
			echo "${i}: missing ports dir => ${depdir}"
			move_away ${i}
			continue
		fi
		pnew=`cd "${depdir}" && make -V PKGFILE ${mflavor}`
		if test ! "${pnew}" = "${pkgall}/${i}"
		then
			if test ! "${pnew}" = ""
			then
				echo "${i}: is obsolete => ${pnew}"
			else
				echo "${i}: missing or defunt Makefile in dir => ${depdir}"
			fi
			move_away ${i}
			continue
		fi
		ptarget="${pnew}"
		#
		# check each depended package
		pkg_info_dependecies "${ptarget}" |
		while read dep
		do
			pmade="${dep}${ext}"
			if test -f "${pkgall}/${pmade}"
			then
				#
				# find matching port directory (origin)
				origin_flavors=`run_pkg_info_origin_file "${pmade}"`
				origin="${origin_flavors%@*}"
				flavor=`get_flavor_dir "${origin_flavors}"`
				mflavor=`get_mflavor "${flavor}"`
				if test "${origin}" = ""
				then
					echo "${i}: missing origin"
					move_away ${i}
					break
				fi
				depdir="${portsdir}/${origin}"
				if test ! -d "${depdir}"
				then
					echo "${i}: dependency ${pmade} missing ports dir => ${depdir}"
					move_away ${i}
					break
				fi
				pnew=`cd "${depdir}" && make -V PKGFILE ${mflavor}`
				if test "${pnew}" = "${pkgall}/${pmade}"
				then
					if test "${pmade}" -nt "${ptarget}"
					then
						echo "${i}: dependend package ${pmade} newer"
						move_away ${i}
						break
					fi
					#
					# up to date
					continue
				fi
				echo "${i}: dependency ${pmade} is obsolete => ${pnew}"
				move_away ${i}
				break
			else
#				noinstall=`cd "${depdir}" && make -V NO_INSTALL`
#				case "${noinstall}" in
#				yes|YES)
#					continue
#					;;
#				esac
				echo "${i}: dependency ${pmade} missing!"
				move_away ${i}
				break
			fi
		done
	done
	)
}
#
# check all packages in ${PACKAGES}/All/ and move if port uses openssl
# Usage: clean_package_openssl
clean_package_openssl() {
	(
	cd ${pkgall} || exit 69
	for i in *
	do
		origin_flavors=`run_pkg_info_origin_file "${i}"`
		origin="${origin_flavors%@*}"
		flavor=`get_flavor_dir "${origin_flavors}"`
                mflavor=`get_mflavor "${flavor}"`
		if test "${origin}" = ""
		then
			continue
		fi
		depdir="${portsdir}/${origin}"
		if test ! -d "${depdir}"
		then
			continue
		fi
		openssl=`cd "${depdir}" && make -V USE_OPENSSL ${mflavor}`
		if test "${openssl}" =  ""
		then
			continue
		fi
		echo "${i}: depends on openssl!"
		move_away ${i}
	done
	)
}
#
# check all links in ${PACKAGES}/
# Usage: clean_package_links
clean_package_links() {
	#
	# find all links
	find ${packages} -type l |
	while read link
	do
		if test -s "${link}"
		then
			#
			# it results in a real file
			continue
		fi
		#
		# remove stale link
		rm -f "${link}"
	done
}
#
# check fort obsolte distfiles
# Usage: clean_distfiles
clean_distfiles() {
	tmp1="/tmp/all-distinfo"
	tmp2="/tmp/all-distfiles"
	rm -f "${tmp2}"
	find "${tmp1}" -type f -mtime +6h -exec rm -f {} \;
	if ! test -f "${tmp1}"
	then
		echo "Processing ... distinfo"
		find ${portsdir}/ -type f -name "distinfo*" -exec \
		cut -d " " -f2 "{}" ";" |
		tr -d '()' |
		sort -u > "${tmp1}"
	fi
	if ! test -f "${tmp2}"
	then
		echo "Processing ... distfiles"
		find ${distdir}/ -type f |
		grep -v "${old}/" |
		sed -e "s=${distdir}/==" |
		sort -u > "${tmp2}"
	fi
	echo "Processing ... differences"
	comm -13 "${tmp1}" "${tmp2}" |
	while read name
	do
		dir="/${name}"
		dir="${dir%/*}"
		echo "${dir}" "${name}"
		if test ! -d "${old}${dir}"
		then
			echo \
			mkdir -p "${old}${dir}"
			mkdir -p "${old}${dir}"
		fi
		if test -f "${old}/${name}"
		then
			if ! diff -qs "${distdir}/${name}" "${old}/${name}"
			then
				for i in `jot 99`
				do
					if test -f "${old}/${name}.${i}"
					then
						continue
					fi
					echo \
					mv -i "${distdir}/${name}" "${old}/${name}.${i}"
					mv -i "${distdir}/${name}" "${old}/${name}.${i}"
					break
				done
				if test -f "${distdir}/${name}"
				then
					echo "ignored: ${distdir}/${name}"
				fi
				continue
			fi
			echo \
			rm -f "${distdir}/${name}"
			rm -f "${distdir}/${name}"
			continue
		fi
		echo \
		mv -i "${distdir}/${name}" "${old}/${name}"
		mv -i "${distdir}/${name}" "${old}/${name}"
	done
}
#
# Sync distfiles with a mirror
# Usage: merge_distfiles
merge_distfiles() {
	if test ! -d "${mergedistdir}"
	then
		echo "${mergedistdir}: no such Directory" >&2
		return
	fi
	find "${distdir}" -type f |
	sort > /tmp/distfiles.1
	find "${mergedistdir}" -type f |
	sed -e "s=${mergedistdir}=${distdir}=" |
	sort > /tmp/distfiles.2
	#diff -u /tmp/distfiles.2 /tmp/distfiles.1
	comm -23 /tmp/distfiles.1 /tmp/distfiles.2 |
	while read name
	do
		dir="${name%/*}"
		xfile="${name##*/}"
		dir="${dir#${distdir}}"
		if test -f "${mergedistdir}/${dir}${xfile}"
		then
			continue
		fi
		case "${dir}" in
		/Old/*)
			echo "${mergedistdir}${dir#/Old}${xfile}"
			if test -f "${mergedistdir}${dir#/Old}${xfile}"
			then
				continue
			fi
			;;
		*)
			echo "${mergedistdir}/Old${dir}${xfile}"
			if test -f "${mergedistdir}/Old${dir}${xfile}"
			then
				continue
			fi
			;;
		esac
		if test ! -d "${mergedistdir}${dir}"
		then
			echo \
			mkdir -p "${mergedistdir}${dir}"
			mkdir -p "${mergedistdir}${dir}"
		fi
		echo \
		cp -pi "${name}" "${mergedistdir}${dir}/"
		cp -pi "${name}" "${mergedistdir}${dir}/"
	done
}
#
# update origin ins installed package when ports has been moved
# Usage: update_origin installed origin
update_origin() {
	installed="${1}"
	origin="${2}"
	echo "${installed} ${origin}"
	if ! fgrep -q "${origin}|" "${portsdir}/MOVED"
	then
		fgrep "${origin}" "${cache}"
		return
	fi
	movedto=`fgrep "${origin}|" "${portsdir}/MOVED" |
		tail -1 |
		cut -d "|" -f2`
	if test "${origin}" = "${movedto}"
	then
		return
	fi
	echo "Updating: ${origin} -> ${movedto}"
	${pkg} set -o "${origin}:${movedto}"
}
#
# write new package state
make_version_list() {
	if test ! -s "${cache}"
	then
		echo "pkg_version -v -L ="
		${pkg} version -v -L = | grep -v bsdpan- > "${cache}"
	fi
}
#
# update origin ins installed package when ports has been moved
# Usage: fix_moved_ports
fix_moved_ports() {
	make_version_list
	if grep -q "orphaned" "${cache}"
	then
		grep "orphaned" "${cache}" |
		while read installed flag status origin
		do
			update_origin "${installed}" "${origin}"
		done
	fi
	if egrep -q "Comparison failed" "${cache}"
	then
		egrep "Comparison failed" "${cache}" |
		while read installed flag status failed
		do
			origin=`run_pkg_info_origin_name "${installed}"`
			if test "${origin}" = ""
			then
				continue
			fi
			update_origin "${installed}" "${origin}"
		done
	fi
}
#
# check recursive for deinstall
delete_dependent_package() {
	local installed
	installed="${1}"
	run_pkg_info_requiredby "${installed}" |
	while read requiredby
	do
		delete_dependent_package "${requiredby}"
	done
	seenflag="${seen}/${installed}"
	if test -e "${seenflag}"
	then
		return
	fi
	origin=`run_pkg_info_origin_name "${installed}"`
	echo "pkg delete ${installed}"
	add_to_file "${todolist}" "${origin}" quiet
	touch "${seenflag}"
}
#
# generate orderd list to deinstall all old packages on a host
make_deinstall_list() {
	quiet_mkdir "${seen}"
	rm -f "${seen}/"*
	(
		echo "#!/bin/sh"
		cat "${cache}" |
		while read installed flag status origin
		do
			case "${flag}" in
			'<')
				delete_dependent_package "${installed}"
				;;
			esac
		done
	) > "${deinstall}"
	rm -f "${seen}/"*
}
#
# remove_from_file file line quiet
remove_from_file( ) {
	edit="${1}"
	pattern="${2}"
	if test ! -e "${edit}"
	then
		return
	fi
	if test `fgrep -x "${pattern}" "${edit}" | wc -l` -ge 1
	then
		if test "${quiet}" = ""
		then
			echo "remove: ${pattern} from ${edit}"
		fi
		cp -p "${edit}" "${edit}.bak"
		fgrep -v -x "${pattern}" "${edit}.bak" > "${edit}"
		rm -f "${edit}.bak"
	fi
}
#
# add_to_file file line quiet
add_to_file( ) {
	edit="${1}"
	pattern="${2}"
	if test -e "${edit}"
	then
		if test `fgrep -x "${pattern}" "${edit}" | wc -l` -gt 1
		then
			remove_from_file "${edit}" "${pattern}"
		fi
	else
		touch "${edit}"
	fi
	if ! fgrep -q -x "${pattern}" "${edit}"
	then
		if test "${quiet}" = ""
		then
			echo "register: ${pattern} in ${edit}"
		fi
		echo "${pattern}" >> "${edit}"
	fi
}
#
# get_moved_origin origin
get_new_origin() {
	local origin
	origin="${1}"
	if test -d "${portsdir}/${origin}"
	then
		echo "${origin}"
		return
	fi
	movedto=`fgrep "${origin}|" "${portsdir}/MOVED" |
		tail -1 |
		cut -d "|" -f2`
	if test "${movedto}" = ""
	then
		echo "nonexistent"
		return
	fi
	echo "${movedto}"
}
#
# parse_default $#
#	global: defaultdata
#	global: target
parse_default() {
	if test "${1}" -lt 1
	then
		if test ! -f "${defaultdata}"
		then
			usage
		fi
		exec /bin/sh "${0}" "${target}" "${defaultdata}"
		echo "error in path: ${0}" >&2
		exit 64
	fi
}
#
next_target() {
	if test "${#}" -lt 2
	then
		return
	fi
	shift
	exec /bin/sh "${0}" "${@}"
}
#
# make sure /etc/make.conf is set up
validate_make_conf() {

	use_packges=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V USE_PACKAGE_DEPENDS`
	if test "${use_packges}" = ""
	then
		echo "### Please add to your /etc/make.conf ####" >&2
		echo "USE_PACKAGE_DEPENDS=yes" >&2
		exit 65
	fi

	depends_target=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V DEPENDS_TARGET`
	case "${depends_target}" in
	'package install')
		;;
	*)
		echo "### Please add to your /etc/make.conf ####" >&2
		echo "DEPENDS_TARGET=package install" >&2
		exit 65
		;;
	esac
}
#
# update pkg tools
update_pkg() {
	if test -f "${pkg}"
	then
		${pkg} delete -y -a -f
		env "PKG_DBDIR=/var/db/pkgng" ${pkg} delete -y -a -f
	fi
	/etc/rc.d/ldconfig start
	( cd "${portsdir}/ports-mgmt/pkg" && env "FORCE_PKG_REGISTER=yes" "PKG_DBDIR=/var/db/pkgng" make clean deinstall PREFIX=/usr/pkgng PKGNAMESUFFIX=-pkgng package install )
	if test ! -L /usr/sbin/pkg
	then
		mv -f /usr/sbin/pkg /usr/sbin/pkg.orig
		ln -s "${pkg}" /usr/sbin/pkg
	fi
	( cd "${portsdir}/ports-mgmt/pkg" && env "FORCE_PKG_REGISTER=yes" make clean package install )
	${pkg} delete -y -f pkg
}
#
#
# update if pkg tools have changed
check_update_pkg() {
	defaultdata="${localdir}/data/make-packages.${hostname}"
	if test ! -f "${defaultdata}"
	then
		return
	fi
	if test -f "${pkg}"
	then
		old=`env "PKG_DBDIR=/var/db/pkgng" ${pkg} query -e '%p == /usr/pkgng' %n-%v`
		pkgname=`cd "${portsdir}/ports-mgmt/pkg" && make PKGNAMESUFFIX=-pkgng -V PKGNAME`
		if test "${old}" = "${pkgname}"
		then
			if test ! -L /usr/sbin/pkg
			then
				mv -f /usr/sbin/pkg /usr/sbin/pkg.orig
				ln -s "${pkg}" /usr/sbin/pkg
			fi
			return
		fi
	fi
	update_pkg
}
#
# check if we run in build jail
check_buildjail() {
	defaultdata="${localdir}/data/make-packages.${hostname}"
	if test ! -f "${defaultdata}"
	then
		echo "${defaultdata}: no such file, aborted." >&2
		echo "!!WARNNING!! Such a file should only exist for your build jail" >&2
		echo "!!WARNNING!! This will uninstall all packages." >&2
		echo "!!WARNNING!! This will delete your config in /usr/local." >&2
		exit 64
	fi
}
#
# inform usage
usage() {
	echo "Usage:" >&2
	echo "    ${0##*/} update-pkg" >&2
	echo "    ${0##*/} repo" >&2
	echo "    ${0##*/} make-packages [port] [...]" >&2
	echo "    ${0##*/} add-packages [port] [...]" >&2
	echo "    ${0##*/} install-packages [port] [...]" >&2
	echo "    ${0##*/} show-packages [port] [...]" >&2
	echo "    ${0##*/} show-missing-packages [port] [...]" >&2
	echo "    ${0##*/} clean-packages ..." >&2
	echo "    ${0##*/} clean-openssl-packages ..." >&2
	echo "    ${0##*/} clean-distfiles ..." >&2
	echo "    ${0##*/} merge-distfiles ..." >&2
	echo "    ${0##*/} fetch-distfiles [port] [...]" >&2
	echo "    ${0##*/} fetch-recursive-distfiles [port] [...]" >&2
	echo "    ${0##*/} fix-moved-ports ..." >&2
	echo "    ${0##*/} list-installed-ports" >&2
	echo "    ${0##*/} make-version-list ..." >&2
	echo "    ${0##*/} show-version-list ..." >&2
	echo "    ${0##*/} make-deinstall-list ..." >&2
	echo "    ${0##*/} show-missing-reinstall" >&2
	echo "    ${0##*/} show-missing-installed" >&2
	echo "    ${0##*/} check-reinstall" >&2
	echo "    ${0##*/} reinstall" >&2
	echo "    ${0##*/} clean-reinstall" >&2
	echo "    ${0##*/} clean ..." >&2
	echo "    ${0##*/} check-installed-ports [port]" >&2
	echo "    ${0##*/} update-ports ..." >&2
	echo "    ${0##*/} full-update-jail [retry] ..." >&2
	echo "    ${0##*/} check-update ..." >&2
	exit 64
}
#
# check empty call
if test $# -lt 1
then
	usage
fi
#
hostnames=`hostname -s`
localdir="${PKG_UPDATE_DIR:-/usr/ports/local/update}"
logdir="${PKG_UPDATE_LOGDIR:-${localdir}/log-${hostnames}}"
hostname=`hostname`
depends="${localdir}/data/depends.${hostname}"
cache="${localdir}/version-list.${hostname}"
deinstall="${localdir}/deinstall.${hostname}"
todolist="${localdir}/data/todo.${hostname}"
seen="/tmp/deinstall-seen"
required="/tmp/required-seen"
inrequired="/tmp/inrequired-seen"
pkginfo_cache="/var/tmp/pkginfo_cache"
pkg_prefix="/usr/pkgng"
pkg_env="PKG_DEPENDS= PKG_PREFIX=${pkg_prefix} PKG_BIN=${pkg_prefix}/sbin/pkg-static"
pkg_env="${pkg_env} DEPENDS_SHOW_FLAVOR="
#
#	get all path information from /etc/make.conf
nowarn="COMMENT=0 CATEGORIES=0 PORTVERSION=0"
portsdir=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V PORTSDIR`
pkg_dbdir=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V PKG_DBDIR`
packages=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V PACKAGES`
defaultdata="${localdir}/data/make-packages.${hostname}"
if test ! -f "${defaultdata}"
then
	pkg="pkg"
else
	pkg="${pkg_prefix}/sbin/pkg"
fi
quiet_mkdir "${pkginfo_cache}"
#
target="${1}"
case "${target}" in
update-pkg)
	check_buildjail
	update_pkg
	;;
repo)
	shift
	mv "${packages}/Old" "${packages}-Old"
	${pkg} repo "${packages}"
	mv "${packages}-Old" "${packages}/Old"
	next_target "${@}"
	;;
make-packages)
	shift
	check_buildjail
	validate_make_conf
	check_update_pkg
	parse_default "${#}"
	quiet_mkdir "${localdir}/data" "${logdir}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				make_packages_in_dir "${dir}"
			done
		else
			make_packages_in_dir "${i}"
		fi
	done
	next_target dummy repo
	;;
add-packages)
	shift
	defaultdata="${localdir}/data/install-packages.${hostname}"
	parse_default "${#}"
	quiet_mkdir "${localdir}/data" "${logdir}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				add_packages_in_dir "${dir}"
			done
		else
			add_packages_in_dir "${i}"
		fi
	done
	;;
install-packages)
	shift
	defaultdata="${localdir}/data/install-packages.${hostname}"
	parse_default "${#}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				install_packages_in_dir "${dir}"
			done
		else
			install_packages_in_dir "${i}"
		fi
	done
	;;
show-packages)
	shift
	defaultdata="${localdir}/data/install-packages.${hostname}"
	parse_default "${#}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				show_packages_in_dir "${dir}"
			done
		else
			show_packages_in_dir "${i}"
		fi
	done
	;;
deinstall-packages)
	shift
	defaultdata="${localdir}/data/install-packages.${hostname}"
	parse_default "${#}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				deinstall_packages_in_dir "${dir}"
			done
		else
			deinstall_packages_in_dir "${i}"
		fi
	done
	;;
show-missing-packages)
	shift
	defaultdata="${localdir}/data/install-packages.${hostname}"
	parse_default "${#}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				show_missing_packages_in_dir "${dir}"
			done
		else
			show_missing_packages_in_dir "${i}"
		fi
	done
	;;
fetch-distfiles)
	shift
	defaultdata="${localdir}/data/make-packages.${hostname}"
	parse_default "${#}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				fetch_distfiles_in_dir "${dir}"
			done
		else
			fetch_distfiles_in_dir "${i}"
		fi
	done
	;;
fetch-recursive-distfiles)
	shift
	defaultdata="${localdir}/data/make-packages.${hostname}"
	parse_default "${#}"
	for i in "${@}"
	do
		if test -f "${i}"
		then
			for dir in `grep -v "^#" "${i}"`
			do
				fetch_recursive_distfiles_in_dir "${dir}"
			done
		else
			fetch_recursive_distfiles_in_dir "${i}"
		fi
	done
	;;
clean-packages)
	ext=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V PKG_SUFX`
	pkgall="${packages}/All"
	pkgold="${packages}/Old"
	quiet_mkdir "${pkgold}"
	check_update_pkg
	#
	# save pwd
	(
		clean_package_all
		clean_package_links
	)
	next_target dummy repo
	next_target "${@}"
	;;
clean-openssl-packages)
	pkgall="${packages}/All"
	pkgold="${packages}/Old"
	quiet_mkdir "${pkgold}"
	check_update_pkg
	#
	# save pwd
	(
		clean_package_openssl
		clean_package_links
	)
	next_target dummy repo
	next_target "${@}"
	;;
clean-distfiles)
	distdir=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V DISTDIR`
	old="${distdir}/Old"
	quiet_mkdir "${old}"
	#
	clean_distfiles
	next_target "${@}"
	;;
merge-distfiles)
	distdir=`make -f /usr/share/mk/bsd.port.mk ${nowarn} -V DISTDIR`
	mergedistdir="${MERGEDISTDIR-/media/distfiles}"
	old="${distdir}/Old"
	#
	merge_distfiles
	next_target "${@}"
	;;
fix-moved-ports)
	fix_moved_ports
	next_target "${@}"
	;;
list-installed-ports)
	run_pkg_info_origin_all
	next_target "${@}"
	;;
show-version-list)
	make_version_list
	cat "${cache}"
	next_target "${@}"
	;;
make-version-list)
	rm -f "${cache}"
	make_version_list
	next_target "${@}"
	;;
make-deinstall-list)
	make_version_list
	quiet="1"
	make_deinstall_list
	next_target "${@}"
	;;
show-missing-reinstall)
	grep -v '^#' "${todolist}" |
	while read origin dummy
	do
		movedto=`get_new_origin "${origin}"`
		if test ! -d "${portsdir}/${movedto}"
		then
			echo "error   ${package} has lost portsdir ${movedto}"
			continue
		fi
		pkgfile=`cd "${portsdir}/${movedto}" && make -V PKGFILE`
		if test ! -f "${pkgfile}"
		then
			echo "	${movedto} no new package"
			continue
		fi
		pkgname=`cd "${portsdir}/${movedto}" && make -V PKGNAME`
		if test -d "${pkg_dbdir}/${pkgname}"
		then
			echo "new     ${pkgname} installed"
			continue
		fi
		installed=`run_pkg_info_installed "${origin}"`
		if test "${installed}" != ""
		then
			echo "old     ${origin} installed"
			continue
		fi
		installed=`run_pkg_info_installed "${movedto}"`
		if test "${installed}" != ""
		then
			echo "old     ${movedto} installed"
			continue
		fi
		echo "	${movedto} package not installed"
	done
	;;
check-reinstall)
	grep -v '^#' "${todolist}" |
	while read origin dummy
	do
		movedto=`get_new_origin "${origin}"`
		if test ! -d "${portsdir}/${movedto}"
		then
			echo "error   ${package} has lost portsdir ${movedto}"
			continue
		fi
		pkgfile=`cd "${portsdir}/${movedto}" && make -V PKGFILE`
		if test ! -f "${pkgfile}"
		then
			echo "	${movedto} no new package"
			continue
		fi
	done
	;;
clean-reinstall)
	quiet="1"
	grep -v '^#' "${todolist}" |
	while read origin dummy
	do
		movedto=`get_new_origin "${origin}"`
		if test ! -d "${portsdir}/${movedto}"
		then
			echo "error   ${origin} has lost portsdir ${movedto}"
			continue
		fi
		pkgname=`cd "${portsdir}/${movedto}" && make -V PKGNAME`
		if test -d "${pkg_dbdir}/${pkgname}"
		then
			remove_from_file "${todolist}" "${origin}"
			continue
		fi
		installed=`run_pkg_info_installed "${origin}"`
		if test "${installed}" != ""
		then
			remove_from_file "${todolist}" "${origin}"
			continue
		fi
		pkgfile=`cd "${portsdir}/${movedto}" && make -V PKGFILE`
		if test ! -f "${pkgfile}"
		then
			echo "	${movedto} no new package"
			continue
		fi
		echo "	${origin} package not installed"
	done
	;;
show-missing-installed)
	env ${pkg_env} ${local_env} pkg version -qo -Rl '?'
	;;
reinstall)
	exec /bin/sh "${0}" install-packages "${todolist}"
	echo "error in path: ${0}" >&2
	exit 64
	;;
clean)
	rm -f "${cache}" "${deinstall}"
	next_target "${@}"
	;;
check-installed-ports)
	shift
	tmp1="/tmp/check-listed.$$"
	tmp2="/tmp/check-installed.$$"
	quiet_mkdir "${localdir}/data"
	defaultdata="${localdir}/data/install-packages.${hostname}"
	if test ! -f "${defaultdata}"
	then
		/bin/sh "${0}" "list-installed-ports" | sort > "${defaultdata}"
	fi
	parse_default "${#}"
	(
		for i in "${@}"
		do
			if test -f "${i}"
			then
				grep -v "^#" "${i}"
			else
				echo "${i}"
			fi
		done
	) |
	sed -e 's=^/usr/ports/==' |
	sort -u > "${tmp1}"
	run_pkg_info_origin_all |
	sort -u > "${tmp2}"
	obsolete=`comm -23 "${tmp1}" "${tmp2}"`
	if test "${obsolete}"
	then
		echo "#    not installed, but listed:"
		echo "${obsolete}" |
		while read origin
		do
			if test ! -d "${portsdir}/${origin}"
			then
				echo "${origin} (no origin)"
				continue
			fi
			echo "${origin}"
		done
		echo ""
	fi
	obsolete=`comm -13 "${tmp1}" "${tmp2}"`
	if test "${obsolete}"
	then
		echo "#    installed, but not listed:"
		echo "${obsolete}" |
		while read origin
		do
			if test ! -d "${portsdir}/${origin}"
			then
				echo "${origin} (no origin)"
				continue
			fi
			pkgname=`cd "${portsdir}/${origin}" && make -V PKGNAME 2>/dev/null`
			run_pkg_match
		done
		echo ""
	fi
	rm -f "${tmp1}" "${tmp2}"
	;;
update-ports)
	(cd ${portsdir} && make update)
	next_target "${@}"
	;;
full-update-jail)
	cd ${localdir} || exit 69
	defaultdata="${localdir}/data/make-packages.${hostname}"
	#
	shift
	case "${1}" in
	retry)
		shift
		;;
	*)
		/bin/sh "${0}" update-ports
		;;
	esac
	/bin/sh "${0}" clean-distfiles
	/bin/sh "${0}" clean-packages
	rm -f "${logdir}/"err,*
	/bin/sh "${0}" make-packages
	next_target "${@}"
	;;
check-update)
	/bin/sh "${0}" check-installed-ports
	/bin/sh "${0}" show-missing-packages
	/bin/sh "${0}" show-missing-installed
	next_target "${@}"
	;;
diff)
	diff -u "${portsdir}/ports-mgmt/pkg_jail/files/pkg_update" "${0}"
	;;
*)
	usage
esac
#
exit 0
#
# eof
