#!/bin/bash
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: emerge-webrsync 5154 2006-12-02 08:07:37Z zmedico $
# Author: Karl Trygve Kalleberg <karltk@gentoo.org>
# Rewritten from the old, Perl-based emerge-webrsync script

type portageq > /dev/null || exit $?
eval $(portageq envvar -v FEATURES FETCHCOMMAND GENTOO_MIRRORS \
	PORTAGE_BIN_PATH PORTAGE_INST_UID PORTAGE_INST_GID PORTAGE_NICENESS \
	GENTOO_MIRRORS PORTAGE_INST_UID PORTAGE_INST_GID PORTAGE_NICENESS \
	PORTAGE_TMPDIR PORTDIR)
DISTDIR="${PORTAGE_TMPDIR}/emerge-webrsync"

# If PORTAGE_NICENESS is overriden via the env then it will
# still pass through the portageq call and override properly.
if [ -n "${PORTAGE_NICENESS}" ]; then
	renice $PORTAGE_NICENESS $$ > /dev/null
fi

source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1

if [ ! -d $DISTDIR ] ; then
	mkdir -p $DISTDIR
fi

cd "$DISTDIR"

found=0
if [ "$1" == "-v" ] ; then
	wgetops=
else	
	#this sucks.  probably better to do 1> /dev/null
	#that said, waiting on the refactoring.
	if [ "${FETCHCOMMAND/wget}" != "${FETCHCOMMAND}" ]; then
		wgetops="-q"
	elif [ "${FETCHCOMMAND/curl}" != "${FETCHCOMMAND}" ]; then
		wgetops="-s -f"
	fi
fi

if type -P md5sum > /dev/null; then
	md5_com='md5sum -c "${FILE}.md5sum"'
elif type -P md5 > /dev/null; then
	md5_com='[ "$(md5 -q ${FILE})" == "$(cut -d \  -f 1 ${FILE}.md5sum)" ]'
else
	echo "warning, unable to do md5 verification of the snapshot!"
	echo "no suitable md5/md5sum binary was found!"
	md5_com='true'
fi

sync_local() {
	echo Syncing local tree...
	if type -P tarsync &> /dev/null; then
		# tarsync doesn't take numeric uid/gid so we need to convert them.
		local inst_user="$(python -c "import pwd; print pwd.getpwuid(int('${PORTAGE_INST_UID:-0}'))[0]")"
		local inst_group="$(python -c "import grp; print grp.getgrgid(int('${PORTAGE_INST_GID:-0}'))[0]")"
		if ! tarsync "${FILE}" "${PORTDIR}" -v -s 1 -o ${inst_user} -g ${inst_group} -e /distfiles -e /packages -e /local; then
			echo "tarsync failed; tarball is corrupt?"
			exit 1;
		fi
		rm "${FILE}"
	else
		if ! tar jxf $FILE; then
			echo "Tar failed to extract the image. Please review the output."
			echo "Executed command: tar jxf $FILE"
			exit 1
		fi
		rm -f $FILE
		# Make sure user and group file ownership is ${PORTAGE_INST_UID}:${PORTAGE_INST_GID}
		chown -R ${PORTAGE_INST_UID:-0}:${PORTAGE_INST_GID:-0} portage
		cd portage
		rsync -av --progress --stats --delete --delete-after \
		--exclude='/distfiles' --exclude='/packages' \
		--exclude='/local' . ${PORTDIR%%/}
		cd ..
		echo "cleaning up"
		rm -rf portage
	fi
	if hasq metadata-transfer ${FEATURES} ; then
		echo "transferring metadata/cache"
		emerge --metadata
	fi
	[ -x /etc/portage/bin/post_sync ] && /etc/portage/bin/post_sync
}

echo "Fetching most recent snapshot"

declare -i attempts=0
while (( $attempts <  40 )) ; do
	attempts=$(( attempts + 1 ))

	# The snapshot for a given day is generated at 01:45 UTC on the following
	# day, so the current day's snapshot (going by UTC time) hasn't been
	# generated yet.  Therefore, always start by looking for the previous day's
	# snapshot (for attempts=1, subtract 1 day from the current UTC time).
	daysbefore=$(expr $(date -u +"%s") - 86400 \* ${attempts})
	DATE_ARGS="-d @${daysbefore}"
	# ${USERLAND} is unreliable since the portage tree might be empty, so test
	# success of the -r option to distinguish between gnu and bsd date.
	date -r ${daysbefore} >&/dev/null && DATE_ARGS="-r ${daysbefore}"
	day=$(date ${DATE_ARGS} -u +"%d")
	month=$(date ${DATE_ARGS} -u +"%m")
	year=$(date ${DATE_ARGS} -u +"%Y")

	FILE_ORIG="portage-${year}${month}${day}.tar.bz2"

	echo "Attempting to fetch file dated: ${year}${month}${day}"
		
	got_md5=0

	if [  ! -e "${FILE_ORIG}.md5sum" ]; then
		FILE="${FILE_ORIG}.md5sum"
		for i in $GENTOO_MIRRORS ; do 
			URI="${i}/snapshots/${FILE}"
			if (eval "$FETCHCOMMAND $wgetops") && [ -s "${FILE}" ]; then
				got_md5=1
				break
			fi
		done
	else
		got_md5=1
	fi
	FILE="${FILE_ORIG}"

	if (($got_md5 == 0 )); then
		echo " --- No md5sum present on the mirror. (Not yet available.)"
		continue
	elif [ -s "${FILE}" ]; then
		if eval "$md5_com"; then
			echo " === snapshot $FILE is correct, using it"
			sync_local
			echo
			echo " === Snapshot has been sync'd"
			echo
			exit 0
		else
			rm $FILE
		fi
	fi
	
	for i in $GENTOO_MIRRORS ; do
		URI="${i}/snapshots/$FILE"
		rm -f "$FILE"
		if (eval "$FETCHCOMMAND $wgetops") && [ -s "$FILE" ]; then
			if ! eval "$md5_com"; then
				echo "md5 failed on $FILE"
				rm ${FILE}
				continue
			else
				sync_local
				echo
				echo " *** Completed websync, please now perform a normal rsync if possible."
				echo "     Update is current as of the of YYYYMMDD: ${year}${month}${day}"
				echo
				exit 0
			fi
		fi

	done
done

rm -rf portage

exit 1
