#!/bin/sh
####
# Script to checkout/update base sources from both trunk (ToT) and the current
# release tag (as determined by the base/config/RELEASE_URL file) and a ports
# tree from trunk (ToT), and then export and sync all of them to the
# ${RSYNCROOT} location, wherefrom the rsync modules are fed to the `sync'
# and `selfupdate' routines in port(1). Read the base/portmgr/rsync.repos
# file for more information on both the necessary rsync modules and filesystem
# level paths, which this script bootstraps.
#
# Whatever server uses this script to mirror the MacPorts rsync repositories
# should simply adapt the ${RSYNCROOT} path variable as necessary (keeping it
# in sync with the equally named variable in base/portmgr/rsync.repos) and
# install it on cron/launchd with a suitable periodicity, previously discussed
# with the portmgr@ team (macports-mgr@lists.macosforge.org). Repositories
# themselves are detailed & served by base/portmgr/rsync.repos, as stated above
# (that is, no manual intervention what-so-ever is needed, other than installing
# this script and adding the repositories detailed in base/portmgr/rsync.repos
# to a local rsyncd.conf file).
#
# Lastly, it is required of every 3rd party mirrors to keep track of this script
# and the base/portmgr/rsync.repos file and always maintain local copies in as
# close sync as possible.
#
#
# Created by fkr@opendarwin.org, jberry@macports.org and yeled@macports.org,
# Updated by jmpp@macports.org
# $Id: mprsyncup 105085 2013-04-09 18:46:31Z snc@macports.org $
####

set -e
set -x

# Commands we need:
SVN="/opt/local/bin/svn -q --non-interactive"
CLEANUP="/opt/local/bin/svn --non-interactive cleanup"
RSYNC="/opt/local/bin/rsync -q"
RM="/bin/rm"
MKDIR="/bin/mkdir"
LN="/bin/ln"
TAR="/usr/bin/tar"
OPENSSL="/usr/bin/openssl"

# Paths we'll work on:
ROOT=/var/tmp/macports
PREFIX=${ROOT}/opt/local
TCLPKG=${PREFIX}/lib/tcl
SVNROOT=/var/tmp/macports
TBASE=${SVNROOT}/trunk/base
RBASE=${SVNROOT}/release/base
PORTS=${SVNROOT}/release/ports
RSYNCROOT=/rsync/macports
PORTINDEX=${PREFIX}/bin/portindex

PATH=${PREFIX}/bin:/bin:/usr/bin:/usr/sbin:/opt/local/bin

# platforms we generate indexes for
PLATFORMS="8_powerpc 8_i386 9_powerpc 9_i386 10_i386 11_i386 12_i386"

# Sources information:
SVNURL=https://svn.macports.org/repository/macports
RELEASE_URL_FILE=config/RELEASE_URL

# private key to use for signing
# XXX set real path
PRIVKEY=""

# cleanup up the working copy if it is locked
if [ -f ${TBASE}/.svn/lock ]; then
    ${CLEANUP} ${TBASE}
fi

# Update/checkout trunk's base, export and rsync it to the rsync repos location (${RSYNCROOT}):
if [ -d ${TBASE}/.svn ]; then
    ${SVN} update ${TBASE}
else
    ${SVN} checkout ${SVNURL}/trunk/base ${TBASE}
fi

if [ ! -d ${RSYNCROOT}/trunk/base ]; then
    ${MKDIR} -p ${RSYNCROOT}/trunk
fi
${RSYNC} -aIC --delete ${TBASE}/ ${RSYNCROOT}/trunk/base

# Read what tag we're releasing from, switch to/checkout a copy, export and rsync it to ${RSYNCROOT}/release/base:
read RELEASE_URL < ${TBASE}/${RELEASE_URL_FILE}
if [ ! -n ${RELEASE_URL} ]; then
    echo "no RELEASE_URL specified in svn trunk, bailing out!"
    exit 1
fi
if [ -d ${RBASE}/.svn ]; then
    ${SVN} switch ${RELEASE_URL} ${RBASE}
else
    ${SVN} checkout ${RELEASE_URL} ${RBASE}
fi

if [ ! -d ${RSYNCROOT}/release/base ]; then
    ${MKDIR} -p ${RSYNCROOT}/release/base
fi
${RSYNC} -aIC --delete ${RBASE}/ ${RSYNCROOT}/release/base

# clean up the working copy if it is locked
if [ -f ${PORTS}/.svn/lock ]; then
      ${CLEANUP} ${PORTS}
fi

# Update/checkout the ports tree, export it and rsync it to ${RSYNCROOT}/release/ports:
if [ -d ${PORTS}/.svn ]; then
    ${SVN} update ${PORTS}
else
    ${SVN} checkout ${SVNURL}/trunk/dports ${PORTS}
fi

# generate platform-specific indexes
pushd ${PORTS} >> /dev/null
# build MP trunk in a private location for indexing
pushd ${TBASE} >> /dev/null
${MKDIR} -p ${TCLPKG}
./configure \
    --prefix=${PREFIX} \
    --with-tclpackage=${TCLPKG}
make clean
make
make install
popd

for PLATFORM in $PLATFORMS; do
	$PORTINDEX -p macosx_${PLATFORM} -o PortIndex_darwin_${PLATFORM};
done

popd

if [ ! -d ${RSYNCROOT}/release/ports ]; then
    ${MKDIR} -p ${RSYNCROOT}/release/ports
fi
${RSYNC} -aIC --delete ${PORTS}/ ${RSYNCROOT}/release/ports

# symlink trunk ports to release ports since we only have 1 set of ports
cd ${RSYNCROOT}
if [ ! -h trunk/dports ]; then
    cd trunk
    ${RM} -rf dports && ${LN} -s ../release/ports dports
fi

# generate and sign tarballs of base and dports
# the signature always needs to match, so we try to make this look atomic to
# clients by switching a symlink target

TAR_CURDIR=${RSYNCROOT}/release/tarballs_current
${MKDIR} -p ${TAR_CURDIR}
cp -pR ${TAR_CURDIR} ${RSYNCROOT}/release/tarballs_old
${LN} -sfh tarballs_old ${RSYNCROOT}/release/tarballs
${TAR} -C ${RSYNCROOT}/release/ -cf ${TAR_CURDIR}/base.tar base
${TAR} --exclude 'PortIndex*' -C ${RSYNCROOT}/release/ -cf ${TAR_CURDIR}/ports.tar ports
cp -pR ${RSYNCROOT}/release/ports/PortIndex_* ${TAR_CURDIR}
# XXX needs PRIVKEY to be set above
#${OPENSSL} dgst -ripemd160 -sign ${PRIVKEY} -out ${TAR_CURDIR}/base.tar.rmd160 ${TAR_CURDIR}/base.tar
#${OPENSSL} dgst -ripemd160 -sign ${PRIVKEY} -out ${TAR_CURDIR}/ports.tar.rmd160 ${TAR_CURDIR}/ports.tar
for index in ${TAR_CURDIR}/PortIndex_*/PortIndex; do
    #${OPENSSL} dgst -ripemd160 -sign ${PRIVKEY} -out ${index}.rmd160 ${index}
done
${LN} -sfh tarballs_current ${RSYNCROOT}/release/tarballs
${RM} -rf ${RSYNCROOT}/release/tarballs_old
