#! /usr/bin/env sh
# This script is part of the eix project and distributed under the
# terms of the GNU General Public License v2.
#
# Author and Copyright (c):
#   Martin V\"ath <vaeth@mathematik.uni-wuerzburg.de>
#
# It can be used to fetch the "standard" overlay data and add it to the
# eix database. (eix 0.13.3).

. '/usr/bin/functions-eix.sh'
read_functions

[ -n "${OVERLAYPARENT}" ] || OVERLAYPARENT="/usr/portage/local"
EIXCACHESNAME="eix-caches.tbz2"

Sanitize () {
	READLINK='' NormalizeNames OVERLAYPARENT \
		|| die '$OVERLAYPARENT must not be empty'
	[ -z "${RELATIVE}" ] || die '$OVERLAYPARENT must start with /'
}
Sanitize

Usage () {
	echo "Usage: ${0##*/} [options] command [FILE]
Handle some remote updates for eix 0.13.3
The following commands are provided:

update: Fetch the eix-caches of some layman overlays into a temporary file
        resp. into FILE and add them to the eix database.
        To keep this data across update-eix calls, you might want to set
        KEEP_VIRTUALS=true in /etc/eixrc (or in ~/.eixrc)
fetch:  Only fetch the overlays into FILE
add:    Only add the overlays from FILE to the eix database.
remove: Remove all temporarily added virtual overlays from the eix database;
        this is similar to
        	KEEP_VIRTUALS=false update-eix
        but faster (without actual updating where possible).

It is strongly recommended to use the update/fetch commands with very limited
permissions. Permissions are dropped when run as root or with the \"-u nobody\"
option. Don't use \"-u root\".

For \"update\" and \"add\" all corresponding local overlay paths are excluded
from the current database to avoid confusion. The local paths are determined
by prefixing the path
	${OVERLAYPARENT}
You can modify this value by setting the environment variable \$OVERLAYPARENT
or with the -o option. If you do not want this feature, set \$OVERLAYPARENT
to some path not containing any overlays.

Options:
	-O x    Extract from the cache files within FILE only overlay Nr. x,
	        i.e. use cache method eix*:...:x for reading these cache files.
	        Default for x is * (which means all overlays in each files)
	        See \"man eix\" for details on cache method eix*.
	-u USER Call wget as USER. Defaults to \"nobody\" if called as root.
	-o PATH Use PATH as \$OVERLAYPARENT
	-v      Verbose (default)
	-q      Quiet"
	EXITCODE=${1:-1}
	exit ${EXITCODE}
}

OVERLAYNR='*'
VERBOSE=true
FETCHUSER=''
OPTIND=1
while getopts 'O:vqu:o:?hH' OPTION; do
	case "${OPTION}" in
		O) OVERLAYNR="${OPTARG}";;
		v) VERBOSE=true;;
		q) VERBOSE=false;;
		u) FETCHUSER="${OPTARG}";;
		o) OVERLAYPARENT="${OPTARG}"; Sanitize;;
		*) Usage 0;;
	esac
done
[ ${OPTIND} -gt 1 ] && shift "`expr ${OPTIND} - 1`"

NEED_ARG=false
FILENAME=''
GetFilename () {
	[ ${#} -gt 1 ] && Usage
	if [ ${#} -lt 1 ]; then
		${NEED_ARG} && die "Filename argument is mandatory"
		return
	fi
	FILENAME="${1}"
	[ -n "${FILENAME}" ] || die "Filename argument must be nonempty"
	case "${FILENAME}" in
		/*|'~'*) :;;
		*) FILENAME="`pwd`/${FILENAME}";;
	esac
}

CalcSuCmd () {
	if [ -z "${FETCHUSER}" ]; then
		[ -n "${UID}" ] || UID="`id -u`"
		if [ "${UID}" -ne 0 ]; then
			Push -c SUCMD "${@}"
			return
		fi
		FETCHUSER=nobody
	fi
	local SHEXEC="${SHELL}"
	if [ -z "${SHEXEC}" ] || ! test -x "${SHELL}"; then
		SHEXEC="`command -v sh`" && test -x "${SHEXEC}" || \
			SHEXEC='/bin/sh'
	fi
	SUCMD=`command -v "${1}"` && test -x "${SUCMD}" || \
		die "${1} cannot be found in $PATH"
	Push -c SUCMD "${SUCMD}"
	shift
	Push SUCMD "${@}"
	Push -c SUCMD '/bin/su' '-s' "${SHEXEC}" '-c' \
		"eval exec ${SUCMD}" "${FETCHUSER}"
}

CdDir () {
	cd -- "${1}" >/dev/null || die "cannot cd to ${1}"
}

TMPDIR=''
EXITCODE=0
Cleanup () {
	cd / >/dev/null
	if [ -n "${TMPDIR}" ]; then
		test -d "${TMPDIR}" && rm -rf -- "${TMPDIR}"
	fi
	TMPDIR=''
	trap - EXIT HUP INT TERM
	exit "${EXITCODE}"
}
MakeTempDir () {
	[ -n "${TMPDIR}" ] && return
	if command -v mktemp >/dev/null 2>&1; then
		TMPDIR=`mktemp -d "/tmp/${0##*/}.XXXXXX"` || \
			die "cannot create temporary directory"
	else
		local COUNT
		COUNT=0
		while true; do
			[ ${COUNT} -eq 9999 ] && \
				die "found no free temp after 10000 attempts"
			COUNT="`expr ${COUNT} + 1`"
			TMPDIR="/tmp/${0##*/}.$$.${RANDOM}.${RANDOM}.${RANDOM}"
			test -e "${TMPDIR}" && continue
			mkdir "${TMPDIR}" || die "cannot create ${TMPDIR}"
			break
		done
	fi
	trap Cleanup EXIT HUP INT TERM
	chmod -- 755 "${TMPDIR}"
	[ -z "${1}" ] || CdDir "${TMPDIR}"
}

TMPSUB=''
MakeTempSub () {
	if [ -z "${TMPSUB}" ]; then
		MakeTempDir
		TMPSUB="${TMPDIR}/1"
		( umask 000; mkdir -- "${TMPSUB}" )
	fi
	[ -z "${1}" ] || CdDir "${TMPSUB}"
}

TMPFILE=''
FetchTemp () {
	local SOURCE
	SOURCE="http://dev.gentooexperimental.org/eix_cache/${EIXCACHESNAME}"
	MakeTempDir cd
	TMPFILE="${TMPDIR}/${EIXCACHESNAME}"
	( umask 000; : >"${TMPFILE}" )
	CalcSuCmd wget -c "${SOURCE}"
	eval "set -- ${SUCMD}"
	RunCommand "Fetching ${EIXCACHESNAME}" "${@}" || \
		die "could not fetch ${SOURCE}"
}

AddArchive () {
	local I NAME VIRTUAL OVERLAYARG
	RunCommand "Unpacking data" tar xjf "${1}" || die "cannot unpack ${1}"
	ClearUpdateEixArgs
	AddLocalMethods
	for I in *
	do
		NAME="${I}"
		Replace -g NAME ':' '_' || mv -- "${I}" "${NAME}"
	done
	if [ -n "${OVERLAYNR}" ]; then
		OVERLAYARG=":${OVERLAYNR}"
	else
		OVERLAYARG=''
	fi
	for I in *
	do
		NAME="${I%.eix}"
		NAME="${NAME#_usr_portage_local_}"
		Replace -g NAME '_' '/'
		VIRTUAL="(${NAME})"
		AddMethod "${VIRTUAL}" "eix*:${2}/${I}${OVERLAYARG}"
		AddOverlays "${VIRTUAL}"
		AddExcludes "${OVERLAYPARENT}/${NAME}"
	done
	export KEEP_VIRTUALS=true
	CallUpdateEix
}

FetchCopy () {
	GetFilename "${@}"
	FetchTemp
	[ -z "${FILENAME}" ] && return
	(
		[ "${UID}" -eq 0 ] && umask 002
		cp --preserve=timestamps -- "${TMPFILE}" "${FILENAME}"
	)
	[ "${UID}" -eq 0 ] && chown -- portage:portage "${FILENAME}"
}

Fetch () {
	NEED_ARG=true
	FetchCopy "${@}"
}

Add () {
	NEED_ARG=true
	GetFilename "${@}"
	test -r "${FILENAME}" || die "cannot read ${FILENAME}"
	MakeTempDir cd
	AddArchive "${FILENAME}" "${TMPDIR}"
}

Remove () {
	ClearUpdateEixArgs
	AddLocalMethods
	export KEEP_VIRTUALS=false
	CallUpdateEix
}

Update () {
	FetchCopy "${@}"
	MakeTempSub cd
	AddArchive "${TMPFILE}" "${TMPSUB}"
}

MAIN_COMMAND="${1}"
[ ${#} -gt 0 ] && shift

[ -n "${UID}" ] || UID="`id -u`"

case "${MAIN_COMMAND}" in
	update|both)        Update "${@}";;
	fetch*|get|wget)    Fetch "${@}";;
	add*)               Add "${@}";;
	rem*|del*|rm*|sub*) Remove "${@}";;
	*)                  Usage;;
esac

exit 0
