#! /bin/bash

###############################################################################
#
# $Id$ $Name$
#
# The contents of this file are subject to the AAF SDK Public Source
# License Agreement Version 2.0 (the "License"); You may not use this
# file except in compliance with the License.  The License is available
# in AAFSDKPSL.TXT, or you may obtain a copy of the License from the
# Advanced Media Workflow Association, Inc., or its successor.
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.  Refer to Section 3.3 of the License for proper use
# of this Exhibit.
#
# WARNING:  Please contact the Advanced Media Workflow Association,
# Inc., for more information about any additional licenses to
# intellectual property covering the AAF Standard that may be required
# to create and distribute AAF compliant products.
# (http://www.amwa.tv/policies).
#
# Copyright Notices:
# The Original Code of this file is Copyright 1998-2009, licensor of the
# Advanced Media Workflow Association.  All rights reserved.
#
###############################################################################

# This is used in the help message, hence it is defined here.
SF_SHELL_HOST=shell.sourceforge.net
SF_LOG_DIR=/home/groups/a/aa/aaf/htdocs/build/AutoMake.logs
SF_LOG_SCP_DST=${SF_SHELL_HOST}:${SF_LOG_DIR}

TMPCODIR=AAFSDKBuild
AAFSDKBUILD_H=ref-impl/include/AAFSDKBuild.h

short_usage()
{
    echo "Usage `basename $0` [-basedir] [-copylogs] [-release] [-update]"
    echo "                [-noregtests] [-nocvsco] [-nocvslog] [-nobuild]"
    echo "                [-h|-help]"
}

usage()
{
    short_usage
    #    0         1         2         3         4         5         6         7
    #    01234567890123456789012345678901234567890123456789012345678901234567890123456789
    echo ""
    echo "-basedir directory"
    echo "	Set the directory where the cvs checkout command will write the\n"
    echo "	AAF directory, or where it already exists. The default value is the"
    echo "	current working directory."
    echo ""
    echo "-copylogs"
    echo "      Copy the make logs to aaf.sourceforge.net.  Both the full and filtered"
    echo "      logs are copied.  The logs are copied to aaf.sourceforge.net using"
    echo "      scp.  A directory named identically to the build tag is created (if"
    echo "      nonexistant) to store the logs.  The user of this script must ensure"
    echo "      ssh is configured properly to access ${SF_SHELL_HOST}."
    echo "      The scp destination is:"
    echo "      ${SF_LOG_SCP_DST}"
    echo ""
    echo "-release"
    echo "	Perform a release build.  The default is a debug build."
    echo ""
    echo "-update"
    echo "	Update an existing cvs sandbox rather than performing a checkout."
    echo "      There is little reason to use this. It was useful when the script"
    echo "      was under development, and is now deprecated."
    echo ""
    echo "-noregtests"
    echo "      Do not run regression tests."
    echo ""
    echo "-nocvsco"
    echo "	Don't run a cvs checkout (or update) command.  This assumes an AAF"
    echo "	source tree exists in the base directory. This overrides -update."
    echo ""
    echo "-nocvslog"
    echo "	Skip the cvs log command required used to determine the age of the"
    echo "	most recent build tag.  If this option is specified, the result of"
    echo "	a previous cvs log command is used.  This is of very limited utility"
    echo "	under normal circumstances."
    echo ""
    echo "-nobuild"
    echo "	Do not build the source tree (i.e. execute make).  Subsequent make log"
    echo "	filtering is still performed, hence, a previous make log should exist."
    echo "	This is of limited utility under normal circumstances.  One use is as an"
    echo "	an means to experiment with the FilterLog_{i686Linux,*} scripts."
    echo ""

    echo "`basename $0` automates the following build processing operations:"
    echo ""
    echo "1. Checkout or update the AAF source tree using CVS."
    echo "2. Optionally bump the build number. (Edit AAFSDKBuild.h and tag the tree.)"
    echo "3. Determine and report the most recent build tag, the date the tag was"
    echo "   applied, and the current date."
    echo "4. Run \"make everything\" and log the results."
    echo "5. Filter the make log to identify unexpected build log messages"
    echo "   (i.e. errors)."
    echo "6. Copy the build logs to aaf.sourceforge.net."
    echo "7. Run regression tests, and copy the results to aaf.sourceforge.net."
    echo ""
    echo "If CVSROOT is not set, then it is assigned the default value:"
    echo ""
    echo "      :pserver:anonymous@cvs.aaf.sourceforge.net:/cvsroot/aaf"
    echo ""
    echo "The AAFTARGET environment variable may be used as an alternative to the"
    echo "-release option.  AAFTARGET must be either \"Release\" or \"Debug\"."
    echo ""

    exit 1;
}

CVS_RUN_CO_COMMAND=1
CVS_RUN_LOG_COMMAND=1
CVS_UPDATE_ONLY=0
BUILD_RUN_COMMAND=1
BUMP_BUILD_TAG=0
COPY_LOGS=0
BASE_DIR=.
AAFTARGET=${AAFTARGET:=Debug}
RUN_REG_TESTS=1

until [ $# == 0 ]
do

	case $1 in
		-basedir    ) BASE_DIR=$2 ; shift ;;
		-bump       ) echo "Build Number not longer supported (replaced by human-edited patchlevel"; exit 1 ;;
		-copylogs   ) COPY_LOGS=1 ;;
		-release    ) AAFTARGET=Release ;;
		-update     ) CVS_UPDATE_ONLY=1 ;;
		-noregtests ) RUN_REG_TESTS=0 ;;
		-nocvsco    ) CVS_RUN_CO_COMMAND=0 ;;
		-nocvslog   ) CVS_RUN_LOG_COMMAND=0 ;;
		-nobuild    ) BUILD_RUN_COMMAND=0 ;;
		-h          ) usage ;;
		-help       ) usage ;;
		*	    ) echo Unrecognized option $1 ; short_usage; exit 1 ;;
	esac

	shift
done

cd $BASE_DIR
if [ $? -ne 0 ]; then
    echo Failed to change to base directory: $BASE_DIR
    exit 1
fi

#
# Set default CVSROOT value.
# Assume that CVS_RSH is set correctly if CVSROOT is set.
#

CVSROOT=${CVSROOT:=:pserver:anonymous@cvs.aaf.sourceforge.net:/cvsroot/aaf}
export CVSROOT

#
# Create the required ~/tmp directory.
#
mkdir -p ~/tmp
if [ $? -ne 0 ]; then
    echo Failed to change to mkdir: ~/tmp
    exit 1
fi

BUILD_TAG_CO=HEAD

# Check out or update the source tree.

CVS_CO_LOG_FILENAME=~/tmp/cvs.co.log
CVS_UPDATE_LOG_FILENAME=~/tmp/cvs.update.log

if [ $CVS_RUN_CO_COMMAND -eq 1 ]; then

	if [ $CVS_UPDATE_ONLY -eq 1 ]; then
		echo cvs update -d
		echo cvs log file is: $CVS_UPDATE_LOG_FILENAME
		cd AAF
		RepeatUntil 0 100 cvs update > $CVS_UPDATE_LOG_FILENAME 2>&1
		CVS_STATUS=$?
		cd ..
	else

		echo cvs -z3 co -r${BUILD_TAG_CO} AAF
	        echo CVSROOT = $CVSROOT
		echo cvs log file is: $CVS_CO_LOG_FILENAME
		RepeatUntil 0 100 cvs -z3 co -r${BUILD_TAG_CO} AAF > $CVS_CO_LOG_FILENAME 2>&1
		CVS_STATUS=$?

	fi

	if [ $CVS_STATUS -ne 0 ]; then
		echo cvs failed with exit status $CVS_STATUS
		exit $CVS_STATUS
	fi
fi

cd AAF
if [ $? -ne 0 ]; then
    echo Failed to change directory to AAF directory.
    exit 1
fi

#
# Fetch the current version info.  Report when the build tag was
# applied, and the current date.
#
AAF_PATCH_LEVEL=`grep "define AAF_PATCH_LEVEL" ${AAFSDKBUILD_H} | awk '{print $3}'`;
BUILD_TAG=`printf "Build-%04d" $AAF_PATCH_LEVEL`

CVS_LOG_OUTPUT_FILENAME=~/tmp/cvs.log.log

# FIXME: Needs to use Major.Minor.Tertiary.PatchLevel or date for logging
if [ $CVS_RUN_LOG_COMMAND -eq 1 ]; then

    echo cvs log -r${BUILD_TAG} ${AAFSDKBUILD_H}
    echo cvs log files are: ${CVS_LOG_OUTPUT_FILENAME} and ${CVS_LOG_OUTPUT_FILENAME}.error
    RepeatUntil 0 100 cvs log -r${BUILD_TAG} ${AAFSDKBUILD_H} > ${CVS_LOG_OUTPUT_FILENAME} 2>&1
    CVS_STATUS=$?
    if [ $CVS_STATUS -ne 0 ]; then
        mv ${CVS_LOG_OUTPUT_FILENAME} ${CVS_LOG_OUTPUT_FILENAME}.error
	echo cvs failed with exit status $CVS_STATUS
	exit 1
    fi

fi

if [ ! -f ${CVS_LOG_OUTPUT_FILENAME} ]; then
    echo ${CVS_LOG_OUTPUT_FILENAME} not found
    exit 1
fi

BUILD_TAG_DATE=`grep date: $CVS_LOG_OUTPUT_FILENAME | awk '{print $2, $3}' | sed s/\;//`
CURRENT_DATE=`date -u "+%Y/%m/%d %H:%M:%S %Z"`

# This version of the date is compatible with cp and scp (i.e. no / or : characters.)
CURRENT_DATE_FOR_FILENAME=`echo $CURRENT_DATE | sed s/\ /_/g | sed sx/x-xg | sed s/:/-/g`
#
# Make everything
#

LOG_SUFFIX=${BUILD_TAG}.`sh build/aafplatform.sh`.${AAFTARGET}.${CURRENT_DATE_FOR_FILENAME}

MAKE_LOG_LINK=make.log.${AAFTARGET}

if [ $BUILD_RUN_COMMAND -eq 1 ]; then

    MAKE_LOG_FILENAME=make.log.${LOG_SUFFIX}

    MAKE_INFO_HEADER=~/tmp/make.header.log

    echo Building the entire source tree.
    echo Build type is: $AAFTARGET
    echo Build log is: $MAKE_LOG_FILENAME

    cat /dev/null > $MAKE_LOG_FILENAME
    rm -f $MAKE_LOG_LINK
    rm -f $MAKE_LOG_LINK.filtered
    ln -s $MAKE_LOG_FILENAME $MAKE_LOG_LINK

    cat /dev/null > $MAKE_INFO_HEADER
    printf "Last build tag:\t\t${BUILD_TAG}\n"              >> $MAKE_INFO_HEADER
    printf "${BUILD_TAG} date:\t${BUILD_TAG_DATE}\n"   >> $MAKE_INFO_HEADER
    printf "Host date:\t\t${CURRENT_DATE}\n"           >> $MAKE_INFO_HEADER
    printf "\n"                                        >> $MAKE_INFO_HEADER
    printf "Build type: ${AAFTARGET}\n"                >> $MAKE_INFO_HEADER
    printf "Host type: `uname -sr`\n"                  >> $MAKE_INFO_HEADER
    printf "Compiler version: `make ccversion`\n"      >> $MAKE_INFO_HEADER
    printf "\n"                                        >> $MAKE_INFO_HEADER

    cat $MAKE_INFO_HEADER
    cat $MAKE_INFO_HEADER >> $MAKE_LOG_FILENAME

    printf "======================================================================\n\n" >> $MAKE_LOG_FILENAME

    printf "Files that differ from ${BUILD_TAG}:\n\n" >> $MAKE_LOG_FILENAME
    printf "M - files modified locally\n" >> $MAKE_LOG_FILENAME
    printf "U - files that have changed since ${BUILD_TAG}\n" >> $MAKE_LOG_FILENAME
    printf "Unknown local files are not shown.\n\n" >> $MAKE_LOG_FILENAME

    echo Running: cvs -nq update -d -r ${BUILD_TAG} 
    RepeatUntil 0 100 cvs -nq update -d -r ${BUILD_TAG} > ~/tmp/cvs.changed_files.log
    CVS_STATUS=$?
    if [ $CVS_STATUS -ne 0 ]; then
	echo cvs failed with exit status $CVS_STATUS
	exit $CVS_STATUS
    fi
    grep -v ^\? < ~/tmp/cvs.changed_files.log  >> $MAKE_LOG_FILENAME


    printf "\n======================================================================\n\n" >> $MAKE_LOG_FILENAME

    (time make -k everything AAFTARGET=${AAFTARGET}) >> $MAKE_LOG_FILENAME 2>&1

fi

#
# Filter log 
#

# Get the date stamped log file name from the link.  The link is used
# in case the build command was not executed (i.e. The -nobuild option
# This is useful when the FilterLog script must be tweaked and the
# user which to avoid recompiling.

FILTER_COMMAND=FilterLog_`sh build/aafplatform.sh`
MAKE_LOG_FILENAME=`ls -l $MAKE_LOG_LINK | awk '{print $11}'`
echo Filtering make log using: $FILTER_COMMAND
$FILTER_COMMAND  < $MAKE_LOG_FILENAME > ${MAKE_LOG_FILENAME}.filtered
rm -f $MAKE_LOG_LINK.filtered
ln -s $MAKE_LOG_FILENAME.filtered $MAKE_LOG_LINK.filtered

#
# Copy the make logs to aaf.sourceforge.net
#
    
DST_DIR=${SF_LOG_DIR}/${BUILD_TAG}/`sh build/aafplatform.sh`
REGRESSION_LOG_LINK=regression.log.${AAFTARGET}
if [ $RUN_REG_TESTS -eq 1 ]; then

    REGRESSION_LOG_FILENAME=regression.log.${LOG_SUFFIX}

    echo Running regression tests.  Log file is: ${REGRESSION_LOG_FILENAME}

    rm -f ${REGRESSION_LOG_LINK}
    cat /dev/null > ${REGRESSION_LOG_FILENAME}

    ln -s ${REGRESSION_LOG_FILENAME} ${REGRESSION_LOG_LINK}

    (AAFTARGET=$AAFTARGET time RunRegressionTests -basedir ${BASE_DIR}) >> ${REGRESSION_LOG_FILENAME} 2>&1
fi

# Recover the regression log filename from the link in case the
# regression tests were not executed.
REGRESSION_LOG_FILENAME=`ls -l $REGRESSION_LOG_LINK | awk '{print $11}'`

if [ $COPY_LOGS -eq 1 ]; then
    echo Copying the log files.
    echo ssh ${SF_SHELL_HOST} mkdir -p ${DST_DIR}

    RepeatWhile 255 5 ssh ${SF_SHELL_HOST} mkdir -p ${DST_DIR}

    echo scp ${MAKE_LOG_FILENAME} ${SF_SHELL_HOST}:${DST_DIR}/${MAKE_LOG_FILENAME}
    RepeatUntil 0 5 scp -q ${MAKE_LOG_FILENAME} ${SF_SHELL_HOST}:${DST_DIR}/${MAKE_LOG_FILENAME}

    echo scp ${MAKE_LOG_FILENAME}.filtered ${SF_SHELL_HOST}:${DST_DIR}/${MAKE_LOG_FILENAME}.filtered
    RepeatUntil 0 5 scp -q ${MAKE_LOG_FILENAME}.filtered ${SF_SHELL_HOST}:${DST_DIR}/${MAKE_LOG_FILENAME}.filtered

    echo scp -q ${REGRESSION_LOG_FILENAME} ${SF_SHELL_HOST}:${DST_DIR}/${REGRESSION_LOG_FILENAME}
    RepeatUntil 0 5 scp -q ${REGRESSION_LOG_FILENAME} ${SF_SHELL_HOST}:${DST_DIR}/${REGRESSION_LOG_FILENAME}

    # Add user friendly links. The links will always point to most recent log.
    echo Making links on the remote host.
    RepeatWhile 255 5 ssh ${SF_SHELL_HOST} \(rm -f ${DST_DIR}/make.log.${AAFTARGET} \; \
                           ln -s ${DST_DIR}/${MAKE_LOG_FILENAME} ${DST_DIR}/make.log.${AAFTARGET}\)

    RepeatWhile 255 5 ssh ${SF_SHELL_HOST} \(rm -f ${DST_DIR}/make.log.${AAFTARGET}.filtered \; \
                           ln -s ${DST_DIR}/${MAKE_LOG_FILENAME}.filtered ${DST_DIR}/make.log.${AAFTARGET}.filtered \)

    RepeatWhile 255 5 ssh ${SF_SHELL_HOST} \(rm -f ${DST_DIR}/regression.log.${AAFTARGET} \; \
                           ln -s ${DST_DIR}/${REGRESSION_LOG_FILENAME} ${DST_DIR}/regression.log.${AAFTARGET} \)

fi
