#!/bin/sh

# usage: $0 ARCH BRANCH BUILDID CHROOT [-noclean] [-norestr] [-noplistcheck] [-distfiles] [-fetch-original] [-trybroken] PKGNAME.tgz DIRNAME [DEPENDENCY.tgz ...]

mount_fs()
{
    fs=$1
    mntpt=$2
    master=$3

    if [ ${disconnected} = 1 ]; then
	mount -t nullfs -r ${fs} ${mntpt}
    else
	mount_nfs -o ro -3 -i ${master}:${fs} ${mntpt}
    fi
}

copypkg()
{
    pb=$1
    host=$2
    from=$3
    to=$4
    http_proxy=$5

    if [ ${host} = $(hostname) ]; then
	cp ${pb}/${arch}/${branch}/packages/All/${from} ${to}
    else
	if [ ! -z "${http_proxy}" ]; then
	    env HTTP_PROXY=${http_proxy} fetch -m -o ${to} http://${host}/errorlogs/${arch}-${branch}-packages-latest/All/${from}
	else
	    fetch -m -o ${to} http://${host}/errorlogs/${arch}-${branch}-packages-latest/All/${from}
	fi
    fi
}

bailout()
{
  chroot=$1
  clean=$2
  error=$3
  pkgname=$4

  echo -n "$pkgname failed unexpectedly on $(hostname) at "
  date

  exit $error
}

# configurable variables
pb=/var/portbuild

arch=$1
branch=$2
buildid=$3
chroot=$4
shift 4

# Default niceness value
nice=0

. ${pb}/${arch}/portbuild.conf
. ${pb}/${arch}/portbuild.$(hostname)
. ${pb}/scripts/buildenv

buildroot=${scratchdir}
error=0

clean=1
if [ "x$1" = "x-noclean" ]; then
  clean=0
  shift
fi
norestr=0
if [ "x$1" = "x-norestr" ]; then
  norestr=1
  export NO_RESTRICTED=1
  shift
fi
noplistcheck=0
if [ "x$1" = "x-noplistcheck" ]; then
  noplistcheck=1
  export NOPLISTCHECK=1
  shift
fi
nodistfiles=1
if [ "x$1" = "x-distfiles" ]; then
  export ALWAYS_KEEP_DISTFILES=1
  nodistfiles=0
  shift
fi
if [ "x$1" = "x-fetch-original" ]; then
  export FETCH_ORIGINAL=1
  shift
fi
if [ "x$1" = "x-trybroken" ]; then
  export TRYBROKEN=1
  shift
fi

ED=$1
PD=$2
FD=$3
BD=$4
RD=$5

builddir=${pb}/${arch}/${branch}/builds/${buildid}
buildenv ${pb} ${arch} ${branch} ${builddir}

# Want to use the /etc/make.conf in the chroot
unset __MAKE_CONF

pkgname=$(basename $6 ${PKGSUFFIX})
dirname=$7
shift 2

echo $pkgname
echo $dirname

export WRKDIRPREFIX=/work
export DISTDIR=/tmp/distfiles
export PACKAGES=/tmp/packages

# to catch missing dependencies
#export DEPENDS_TARGET=/usr/bin/true

# don't pass -j, -k etc. to sub-makes
unset MAKEFLAGS
unset PORTSDIR
export SRCBASE=/usr/src

# wait 2 hours before killing build with no output
export TIMEOUT=7200

# to prevent runaway processes -- 400 meg file size limit, 2 hours CPU limit
ulimit -f 819200
ulimit -t 7200

# directories to clean
cleandirs="${LOCALBASE} /compat /var/db/pkg"

# 15 minutes
export FTP_TIMEOUT=900
export HTTP_TIMEOUT=900

export PATH=/sbin:/bin:/usr/sbin:/usr/bin:${LOCALBASE}/sbin:${LOCALBASE}/bin

echo "building $pkgname in $chroot"

bindist=${buildroot}/${branch}/${buildid}/tarballs/bindist.tar
bindistlocal=${buildroot}/${branch}/${buildid}/tarballs/bindist-$(hostname).tar

if [ -f ${chroot}/.notready ]; then
  tar -C ${chroot} -xpf ${bindist}
  if [ -f ${bindistlocal} ]; then
    tar -C ${chroot} -xpf ${bindistlocal}
  fi

  # to be able to run certain kernel-dependent binaries
  # inside the chroot area
  cp -p /rescue/mount /rescue/umount ${chroot}/sbin
  cp -p /rescue/ps ${chroot}/bin

  rm ${chroot}/.notready
  touch ${chroot}/.ready
fi

if [ "${use_jail}" = "1" ]; then
  # Figure out jail IP addr
  chrootpid=$(basename ${chroot})
  ipbase=$((${chrootpid}+2))
  ip1=$(($ipbase /(256*256)))
  ip2=$((($ipbase - ($ip1*256*256)) /256))
  ip3=$((($ipbase - ($ip1*256*256) - ($ip2*256))))
fi

# Set up desired uname version
echo ${OSREL}-${BRANCH} > ${chroot}/usr/bin/UNAME_VERSION

trap "bailout ${chroot} ${clean} ${error} ${pkgname}" 1 2 3 9 10 11 15

rm -rf ${chroot}/tmp/*
cd ${chroot}/tmp
mkdir -p depends distfiles packages

echo "building ${pkgname} on $(hostname)" | tee ${chroot}/tmp/${pkgname}.log
echo "in directory ${chroot}" | tee -a ${chroot}/tmp/${pkgname}.log

# intentionally set up ${PORTSDIR} with symlink to catch broken ports
mkdir -p ${chroot}/a/ports
rm -rf ${chroot}/usr/ports

# Don't build in a world-writable standard directory because some ports
# hardcode this path and try to load things from it at runtime, which is
# bad for user security
rm -rf ${chroot}/${WRKDIRPREFIX}
mkdir -p ${chroot}/${WRKDIRPREFIX}

if [ ! -z "${ccache_dir}" ]; then
  mkdir -p ${chroot}/root/.ccache/
  if [ "${ccache_dir_nfs}" = "1" ]; then
    mount_nfs -o rw -T -3 ${ccache_dir} ${chroot}/root/.ccache/
  else
    mount -o rw -t nullfs ${ccache_dir} ${chroot}/root/.ccache/
  fi
fi

mount_fs ${builddir}/ports ${chroot}/a/ports ${master}
ln -sf ../a/ports ${chroot}/usr/ports

mkdir -p ${chroot}/usr/src 

mount_fs ${builddir}/src ${chroot}/usr/src ${master}

mount -t devfs foo ${chroot}/dev
umount -f ${chroot}/compat/linux/proc > /dev/null 2>&1

# just in case...
for dir in ${cleandirs}; do
  if ! rm -rf ${chroot}${dir} >/dev/null 2>&1; then
    chflags -R noschg ${chroot}${dir}
    rm -rf ${chroot}${dir} >/dev/null 2>&1
  fi
done

rm -rf ${chroot}/var/db/pkg/*

mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.root.dist -p ${chroot} \
  >/dev/null 2>&1
mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.var.dist -p ${chroot}/var \
  >/dev/null 2>&1
mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.usr.dist -p ${chroot}/usr \
  >/dev/null 2>&1
mkdir -p ${chroot}${LOCALBASE}
mtree -deU -f ${chroot}/a/ports/Templates/BSD.local.dist -p ${chroot}${LOCALBASE} \
  >/dev/null 2>&1

if [ ${arch} = "i386" -o ${arch} = "amd64" ]; then
  # JDK ports need linprocfs :(
  mkdir -p ${chroot}/compat/linux/proc
  mount -t linprocfs linprocfs ${chroot}/compat/linux/proc
fi

_ldconfig_dirs="/lib /usr/lib /usr/lib/compat"
ldconfig_dirs=""
for i in ${_ldconfig_dirs}; do
  if [ -d ${chroot}/${i} ]; then
    ldconfig_dirs="${ldconfig_dirs} ${i}"
  fi
done
chroot ${chroot} /sbin/ldconfig ${ldconfig_dirs}
if [ ${arch} = "i386" ]; then
	chroot ${chroot} /sbin/ldconfig -aout /usr/lib/aout /usr/lib/compat/aout
fi

set x $ED $FD $PD $BD $RD
shift 1
while [ $# -gt 0 ]; do
  if [ ! -f ${chroot}/tmp/depends/$1 ]; then
    echo "copying package $1 for ${pkgname}"
    copypkg ${pb} ${master} $1 ${chroot}/tmp/depends "${http_proxy}"

    # Test for copy failure and bail
    if [ ! -f ${chroot}/tmp/depends/$1 ]; then
      echo "ERROR: Couldn't copy $1" | tee -a ${chroot}/tmp/${pkgname}.log
      bailout ${chroot} ${clean} 255 ${pkgname}
    fi
  fi
  shift
done

cp -p ${pb}/scripts/buildscript ${chroot}
cp -p ${pb}/scripts/pnohang.${arch} ${chroot}/pnohang

# phase 1, make checksum
# Needs to be chroot not jail so that port can be fetched
chroot ${chroot} /buildscript ${dirname} 1 "$ED" "$PD" "$FD" "$BD" "$RD" 2>&1 | tee -a ${chroot}/tmp/${pkgname}.log
if [ -f ${chroot}/tmp/status ]; then
  error=$(cat ${chroot}/tmp/status)
else
  error=255
fi

if [ "${error}" = 0 ]; then
# make checksum succeeded
# phase 2, make package
  ln -sf ${pkgname}.log2 ${chroot}/tmp/make.log

  if [ "${use_jail}" = 1 ]; then
    ifconfig lo0 alias 127.${ip1}.${ip2}.${ip3}/32
    jail -J ${chroot}/tmp/jail.id ${chroot} jail-${chrootpid} 127.${ip1}.${ip2}.${ip3} /usr/bin/env JAIL_ADDR=127.${ip1}.${ip2}.${ip3} HTTP_PROXY=${http_proxy} /usr/bin/nice -n $nice /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1
    ifconfig lo0 delete 127.${ip1}.${ip2}.${ip3}
  else
    chroot ${chroot} /usr/bin/nice -n $nice /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1
  fi

  grep pnohang ${chroot}/tmp/${pkgname}.log2
  cat ${chroot}/tmp/${pkgname}.log2 >> ${chroot}/tmp/${pkgname}.log
  rm ${chroot}/tmp/${pkgname}.log2
  error=$(cat ${chroot}/tmp/status)
fi

rm -rf ${chroot}/${WRKDIRPREFIX}

# Record build completion time for ganglia
echo "${arch} ${branch} ${buildid}" > ${buildroot}/stamp/${pkgname}

exit $error
