#!/bin/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 <martin@mvath.de>
#
# It can be used to fetch the "standard" overlay data and add it to the
# eix database. (eix 0.30.4).

. '/usr/bin/eix-functions.sh'
ReadFunctions
my_getopts='KvqxXLl:a:kiHh?'

set -f
eval "Push -c opt `eix-update --print EIX_REMOTE_OPTS`"
Push opt "${@}"
eval "set -- ${opt}"

drop_permissions=:
OPTIND=1
while getopts "${my_getopts}" opt
do	case ${opt} in
	K)	drop_permissions=false
		break;;
	k)	drop_permissions=false;;
	i)	drop_permissions=:;;
	*)	:;;
	esac
done
if ${drop_permissions}
then	prg='/usr/bin/eix-drop-permissions'
	me='/usr/bin/eix-remote'
	exec "${prg}" -- "${me}" -K "${@}"
	die "`eval_gettext 'failed to execute ${prg}'`"
fi

addr1='http://gpo.zugaina.org/eix_cache/eix-cache.tbz2'
addr2='http://dev.gentooexperimental.org/eix_cache/eix-caches.tbz2'
ReadVar archive1 EIX_REMOTEARCHIVE1
ReadVar archive2 EIX_REMOTEARCHIVE2
ReadVar local_layman LOCAL_LAYMAN

Usage() {
	n=${0##*/}
	p='eix 0.30.4'
	f1=${archive1}
	f2=${archive2}
	[ -n "${f:+}" ] || f=`gettext 'temporary file'`
	eval_gettext 'Usage: ${n} [options] command
Get data from a remote database for ${p}.
The following commands are provided:

update1 (=update) or update2:
        Fetch the eix-caches of some layman overlays, store them locally in
        EIX_REMOTEARCHIVE1 (${f1}) or
        EIX_REMOTEARCHIVE2 (${f2}),
        respectively and add them to the eix database.
        If EIX_REMOTE1 or EIX_REMOTE2, respectively, is nonempty the output
        goes to that separate database.
        You can use eix -R or eix -Z or set REMOTE_DEFAULT=1 or 2
        to access this alternative database.
        If EIX_REMOTE1 or EIX_REMOTE2 is empty the output is added to
        EIX_CACHEFILE.
        In this case, to keep the remote data across eix-update calls
        you might want to set KEEP_VIRTUALS=true in /etc/eixrc
add1 (=add) or add2:
        Only do the second task (add EIX_REMOTEARCHIVE? without fetching).
        If EIX_REMOTE? is nonempty, it makes sense to call this regularly
        after eix-update so that eix -R? will show synchronized data.
fetch1 (=fetch) or fetch2:
        Only do the first task (fetch eix-caches to EIX_REMOTEARCHIVE).
        If you want to download the most current remote data at every call of
        eix-sync put e.g. the following lines to your /etc/eix-sync.conf:
        @StatusInfo Downloading remote1
        @eix-remote fetch1
remove: Remove all temporarily added virtual overlays from the eix database.
        This makes only sense if EIX_REMOTE? is empty.
        The effect is similar to
        	KEEP_VIRTUALS=false eix-update
        but faster (using previous cachefile where possible).

Options can be specified in the eix (or environment) variable EIX_REMOTE_OPTS.
This data is evalued, so be aware of security risks.
Moreover, "--" in this variable will exclude further command line options.
The following options are available:

-k      Keep permissions: Without this option, eix-drop-permissions is used to
        drop permissions immediately to that of EIX_USER
-K      As -k, but cannot be reset with -i
-X      Exclude remote overlays which are also locally layman. See -L/-l
-x      Exclude local layman overlays which are available remotely. See -L/-l
-L      For -x/-X the "storage" path of layman is found heuristically.
        With -L the path actually used is printed (and eix-remote exits).
        Set LOCAL_LAYMAN or use option -l to override the heuristics.
-l PATH Use PATH as LOCAL_LAYMAN
-a ADDR Use ADDR as remote database address instead of:
        ${addr1}
        ${addr2}
-i      Ignore all previous options (e.g. ignore EIX_REMOTE_OPTS).
-v      Verbose (default)
-H      Suppress status line update
-q      Quiet'
	echo
	exitcode=${1:-1}
	Exit ${exitcode}
}

DefaultOpts() {
	addr=
	verbose=:
	statusline=:
	keep=false
	exclude=
}

DefaultOpts
OPTIND=1
while getopts "${my_getopts}" opt
do	case ${opt} in
	i)	DefaultOpts;;
	[kK])	:;;
	v)	verbose=:;;
	q)	verbose=false;;
	x)	exclude=local;;
	X)	exclude=remote;;
	L)	exclude=debug;;
	l)	local_layman=${OPTARG};;
	a)	addr=${OPTARG};;
	H)	statusline=false;;
	*)	Usage 0;;
	esac
done
[ ${OPTIND} -le 1 ] || shift `Expr ${OPTIND} - 1`
${statusline} || export NOSTATUSLINE=true

SanitizeLocalLayman() {
	normalize_resolve=false NormalizeNames local_layman \
		|| die "`gettext '$LOCAL_LAYMAN must not be empty'`"
	[ -z "${relative:++}" ] || \
		die "`gettext '$LOCAL_LAYMAN must start with /'`"
}

PrintLaymanStorage() {
	printf '%s\n%s\n' 'from layman.config import BareConfig' \
	"print(BareConfig(read_configfile=True)['storage'])" \
		| python -- "${@}" 2>/dev/null
}

PrintLaymanStorageOld() {
	printf '%s\n%s\n' 'from layman.config import Config' \
	"print(Config()['storage'])" | python -- "${@}" 2>/dev/null
}

InitLocalLayman() {
	[ -n "${local_layman:++}" ] && return
	local_layman=`PrintLaymanStorage` || local_layman=
	if [ -z "${local_layman:++}" ]
	then	local_layman=`PrintLaymanStorageOld` || local_layman=
	fi
	for i in \
		"${local_layman}" \
		'/usr/local/portage/layman' \
		"${local_portdir:-/}local/layman/make.conf" \
		"${local_portdir%/*/}/layman/make.conf" \
		'/var/lib/layman'
	do	[ -n "${i:++}" ] && test -d "${i}" && local_layman=${i} \
			&& return
	done
	return 1
}
if [ -n "${exclude:++}" ]
then	InitLocalLayman && SanitizeLocalLayman || {
		ewarn "`gettext 'cannot determine useful $LOCAL_LAYMAN'`"
		if [ "${exclude}" = 'debug' ]
		then	[ -n "${local_layman:++}" ] && Echo "${local_layman}"
			Exit 1
		fi
		exclude=
	}
	if [ "${exclude}" = 'debug' ]
	then	Echo "${local_layman}"
		Exit
	fi
fi

CdDir() {
	cd "${1}" >/dev/null && return
	a=${1}
	die "`eval_gettext 'cannot cd to ${a}'`"
}

tmpdir=
exitcode=0
Cleanup() {
	trap : EXIT HUP INT TERM
	if [ -n "${tmpdir:++}" ]
	then	test -d "${tmpdir}" && rm -rf -- "${tmpdir}"
	fi
	tmpdir=
	trap - EXIT HUP INT TERM
	Exit ${exitcode}
}
MakeTempDir() {
	trap Cleanup EXIT HUP INT TERM
	AssignTemp tmpdir -d
	chmod -- a+rx "${tmpdir}"
}

tmpfile=
FetchTemp() {
	eixcachesname=${addr##*/}
	[ -z "${eixcachesname:++}" ] && die "`gettext
'remote address is not properly set.
Please specify a valid remote file with option -a.
The default should have been set with ./configure --remote-file'`"
	MakeTempDir
	tmpfile="${tmpdir}/${eixcachesname}"
	[ -n "${archive:++}" ] && test -e "${archive}" \
		&& cp -p -- "${archive}" "${tmpfile}" >/dev/null 2>&1
	Statusline "`gettext 'Downloading remote data'`"
	(
		CdDir "${tmpdir}" || die "`gettext 'cannot cd to tempdir'`"
		umask 002
		set -- wget -N
		${verbose} || set -- "${@}" --no-verbose
		set -- "${@}" -- "${addr}"
		if ${verbose}
		then	"${@}"
		else	a=`"${@}" 2>&1` || {
				Echo "${a}" >&2
				false
			}
		fi || die "`gettext 'failed: '` ${*}"
	) || {
		exitcode=${?}
		exit ${exitcode}
	}
}

BugReport() {
	printf '\n\n'
	eval_gettext \
'Probably your eix cachefile was *not* updated successfully.
Unless the above messages suggest another cause or you specified a
wrong filename, the most likely cause of this is that the server uses
another eix version than you or produced broken data. Please check whether
EIX_REMOTEARCHIVE is a valid *.tar.bz2 archive containing eix cachefiles
(you can download it using fetch).
If this is not the case (but was freshly downloaded), please report a bug.
Note that the archive is *not* broken if only the cachefile format versions
differ: In that case only report a bug if the eix cachefile format versions
in the downloaded file are *older* than that of the most current ~x86 eix
version in the portage tree (but first retry after several days before
reporting such a bug to give the server maintainers a chance to upgrade
after a version bump of eix).
Conversely, if the downloaded versions are even newer than that supported by
your eix, you will have to upgrade to the most current ~x86 version of eix
to use eix-remote: This inconvenience cannot be avoided and is not a bug!'
}

AddArchive() {
	a=${1}
	CdDir "${2}"
	RunCommand "`gettext 'Unpacking data'`" tar xjf "${a}" || {
		msg=`eval_gettext 'cannot unpack ${a}'`
		msg=${msg}`BugReport`
		die "${msg}"
	}
	ClearUpdateArgs
	AddLocalMethods
	Push -c eixoverlay
	Push -c method
	Statusline "`gettext 'Analyzing'`"
	set +f
	chmod a+r *
	for i in *
	do	n=${i%.eix}
		while :
		do	case ${n} in
			_*)
				n=${n#_};;
			*_*_*_*)
				n=${n#*_};;
			*)
				break;;
			esac
		done
		Replace -g n '_' '?'
		n="*/${n}"
		p="${2}/${i}"
		Replace -g p '\' '\\'
		Replace -g p ':' '\:'
		Push eixoverlay "-f${p}" "-o${n}"
		Push method "eix*:${p}:${n}"
	done
	set -f
	sep=mAgIcsEp
	eval "set -- ${eixoverlay}"
	eixoverlay=`eix-header -s"${sep}" "${@}"` || exitcode=1
	eval "set -- ${method}"
	for i
	do	l=${eixoverlay%%${sep}*}
		eixoverlay=${eixoverlay#*${sep}}
		name=${eixoverlay%%${sep}*}
		eixoverlay=${eixoverlay#*${sep}}
		[ -n "${l}${name}" ] || {
			exitcode=1
			continue
		}
		name=${name##*/}
		[ "${exclude}" = 'remote' ] && \
			test -r "${local_layman}/${name}" && continue
		virtual="layman/${name}"
		printf '%s -> %s\n' "${virtual}" "${l:-no repo-name}"
		AddMethod "${virtual}" "${i}"
		AddOverlays "${virtual}"
		[ -n "${l:++}" ] && AddRepoName "${virtual}" "${l}"
		[ "${exclude}" = 'local' ] && \
			AddExcludes "${local_layman}/${name}"
	done
	msg=
	[ ${exitcode} -ne 0 ] && \
		msg=`eval_gettext 'could not read all eix cachefiles of ${a}'`
	die_on_update_failure=false
	ReadVar ${eix_remote_var} ${eix_remote_var}
	eval eix_remote=\${${eix_remote_var}}
	(
		if [ -n "${eix_remote:++}" ]
		then	einfo "`eval_gettext \
				'Output to remote database ${eix_remote}'`"
			AddUpdateArgs '-o' "${eix_remote}"
			umask 002
		fi
		KEEP_VIRTUALS=true
		export KEEP_VIRTUALS
		CallUpdate
	) || {
		exitcode=${?}
		msg=`gettext 'eix-update failed'; \
			[ -n "${msg:++}" ] && printf '\n%s' "${msg}"`
	}
	[ -z "${msg:++}" ] && return
	msg=${msg}`BugReport`
	die "${msg}"
}

CheckTemp() {
	[ -n "${archive:++}" ] || die "`gettext \
			'A temporary file makes only sense for update mode'`"
}

FetchFile() {
	FetchTemp
	file=${archive}
	if [ -z "${file:++}" ]
	then	file=${tmpfile}
		return
	fi
	cp -p -- "${tmpfile}" "${file}" || die "`eval_gettext \
		'cannot copy temporary file to ${file}'`"
}


Fetch() {
	CheckTemp
	FetchFile
}

Add() {
	CheckTemp
	test -r "${archive}" || \
		die "`eval_gettext 'cannot read ${archive}'`"
	MakeTempDir
	AddArchive "${archive}" "${tmpdir}"
}

Remove() {
	ClearUpdateArgs
	AddLocalMethods
	export KEEP_VIRTUALS=false
	CallUpdate
}

Update() {
	FetchFile
	if [ -z "${tmpdir:++}" ]
	then	MakeTempDir
		tmpsup=${tmpdir}
	else	tmpsub="${tmpdir}/1"
		mkdir -m 700 -- "${tmpsub}" \
			|| die "`eval_gettext 'mkdir ${tmpsub} failed'`"
	fi
	AddArchive "${file}" "${tmpsub}"
}

number=1
case ${1} in
*2)
	number=2;;
esac
[ -n "${addr:++}" ] || eval addr=\${addr${number}}
eval archive=\${archive${number}}
eix_remote_var=EIX_REMOTE${number}

case ${1-} in
update|update[12])
	Update;;
fetch|fetch[12])
	Fetch;;
add|add[12])
	Add;;
remove)
	Remove;;
*)
	Usage;;
esac

Exit 0
