#!/bin/sh
#
# INDEX build tinderbox script.  Build an INDEX for all supported FreeBSD branches
# using the latest value of OSVERSION according to the src trees.  If the build
# fails, yowl about it on ${REPORT_ADDRESS}  If not, copy the index to www.freebsd.org so
# that 'make fetchindex' sees it.
#
# When INDEX is broken, assemble the list of committers who touched files
# on the most recent 'svn update', and put those committers "on the hook".
# These committers all stay on the hook until INDEX is buildable again.
#
# MAINTAINER= portmgr@FreeBSD.org
#

# --------------------------------------------------------
# Change these!

SVN=/usr/local/bin/svn

# Address for success/failure reports
REPORT_ADDRESS=root@localhost

# Address for script errors
ERROR_ADDRESS=root@localhost

# Location of ports tree and source trees
export BASEDIR=/a/tindex
export PORTSDIR=${BASEDIR}/ports
export SRCDIR9=${BASEDIR}/src.9
export SRCDIR10=${BASEDIR}/src.10
export SRCDIR11=${BASEDIR}/src.11
export SRCDIR12=${BASEDIR}/src.12
export OUTDIR=${BASEDIR}/out

# Target architecture if not set in the environment
if [ "${ARCH}" = "" ]; then
	export ARCH=i386
fi

# --------------------------------------------------------

blame() {
  # Find out who is responsible for current version of file $1

  # Fastest way to extract is from svn info
  who=$(${SVN} info $1 2>/dev/null | grep '^Last Changed Author' | awk '{print $4}')

  echo $who
}

indexfail() {
  BRANCH=$1

  # Leave a cookie behind so that we know when the index is fixed
  touch ${PORTSDIR}/broken.${BRANCH}

  (
    echo "INDEX build failed with errors:";
    len=$(wc -l index.out | awk '{print $1}')
    if [ "$len" -gt "40" ]; then
      head -20 index.out
      echo "[...]"
      tail -20 index.out
    else
      cat index.out
    fi

    len=$(wc -l index.err | awk '{print $1}')
    if [ "$len" -gt "40" ]; then
      head -20 index.err
      echo "[...]"
      tail -20 index.err
    else
      cat index.err
    fi

    # Find out which committers are on the hook

    commits=$(grep ^U ${PORTSDIR}/svn.log | grep -v INDEX | awk '{print $2}')
    for i in ${commits}; do
	blame $i >> ${PORTSDIR}/hook
    done
    sort -u ${PORTSDIR}/hook > ${PORTSDIR}/hook.new
    mv ${PORTSDIR}/hook.new ${PORTSDIR}/hook
    echo
    echo "Committers on the hook:"
    tr -s '\n' ' ' < ${PORTSDIR}/hook
    echo
    echo 
    echo "Most recent SVN update was:";
    grep -v '/work$' svn.log | grep -v '^\?'
  ) | mail -s "INDEX build failed for ${BRANCH}" ${REPORT_ADDRESS}
  exit 1
}

checkfixed() {
  BRANCH=$1

  # If the cookie exists that means that this is the first build for which the
  # INDEX succeeded, so announce this.
  if [ -e ${PORTSDIR}/broken.${BRANCH} ]; then
    rm -f ${PORTSDIR}/broken.${BRANCH}
    mail -s "INDEX now builds successfully on ${BRANCH}" ${REPORT_ADDRESS} < /dev/null
  fi
}

# Sanitize the environment so that the indexes aren't customized by the
# local machine settinge
export __MAKE_CONF=/dev/null
export PORT_DBDIR=/nonexistent
export PKG_DBDIR=/nonexistent
export LOCALBASE=/nonexistent
export INDEX_PRISTINE=1
export INDEX_JOBS=3
export INDEX_QUIET=1

# First update the source trees to get current OSVERSION
${SVN} -q up ${SRCDIR9}/sys/sys
OSVERSION9=$(awk '/^#define[[:blank:]]__FreeBSD_version/ {print $3}' < ${SRCDIR9}/sys/sys/param.h)

${SVN} -q up ${SRCDIR10}/sys/sys
OSVERSION10=$(awk '/^#define[[:blank:]]__FreeBSD_version/ {print $3}' < ${SRCDIR10}/sys/sys/param.h)

${SVN} -q up ${SRCDIR11}/sys/sys
OSVERSION11=$(awk '/^#define[[:blank:]]__FreeBSD_version/ {print $3}' < ${SRCDIR11}/sys/sys/param.h)

${SVN} -q up ${SRCDIR12}/sys/sys
OSVERSION12=$(awk '/^#define[[:blank:]]__FreeBSD_version/ {print $3}' < ${SRCDIR12}/sys/sys/param.h)

cd ${PORTSDIR}
rm -f INDEX-9 INDEX-9.bz2 INDEX-10 INDEX-10.bz2 INDEX-11 INDEX-11.bz2 INDEX-12 INDEX-12.bz2
(${SVN} up 2>1 ) > svn.log
if grep -q ^C svn.log ; then
  (echo "svn update failed with conflicts:";
    grep ^C svn.log) | mail -s "Ports svn up failed" ${ERROR_ADDRESS}
    exit 1
fi

for branch in 9.x 10.x 11.x 12.x; do
    release=$(echo $branch | sed -e 's,.x,,')

    eval _osver=\$OSVERSION${release}
    eval _uname_r="$(( ${_osver} / 100000 )).0-RELEASE"
    export OSVERSION=${_osver}
    export UNAME_r=${_uname_r}

    if [ "${release}" = "9" ]; then
        MAKE_CMD=fmake
    else
        MAKE_CMD=make
    fi
    echo "Building INDEX for ${branch} with OSVERSION=${OSVERSION}"
    cd ${PORTSDIR}
    ((${MAKE_CMD} index 2> index.err) > index.out) || indexfail ${branch}
    if [ -s index.err ]; then
        indexfail ${branch}
    fi
    checkfixed ${branch}

    bzip2 -kf ${PORTSDIR}/INDEX-${release}
    mv ${PORTSDIR}/INDEX-${release} ${PORTSDIR}/INDEX-${release}.bz2 ${OUTDIR}
done

# All indexes built successfully, clear the hook
rm -f ${PORTSDIR}/hook
