#!/bin/sh
#
# Copyright © 2004-2005 The Trustees of Indiana University and Indiana
#                         University Research and Technology
#                         Corporation.  All rights reserved.
# Copyright © 2004-2005 The University of Tennessee and The University
#                         of Tennessee Research Foundation.  All rights
#                         reserved.
# Copyright © 2004-2005 High Performance Computing Center Stuttgart,
#                         University of Stuttgart.  All rights reserved.
# Copyright © 2004-2005 The Regents of the University of California.
#                         All rights reserved.
# Copyright © 2006-2017 Cisco Systems, Inc.  All rights reserved.
# Copyright © 2016 Inria.  All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# This script is used to create a nightly snapshot tarball of hwloc.
#
# $1: scratch root
# $2: e-mail address for destination
# $4: dest dir
# $3: git URL
# $5: git branch
#

scratch_root=$1
email=$2
destdir=$3
giturl=$4
gitbranch=$5

# Set this to any value for additional output; typically only when
# debugging
: ${debug:=}

# do you want a success mail?
want_success_mail=1

# max length of logfile to send in an e-mail
max_log_len=50

# how many snapshots to keep in the destdir?
max_snapshots=5

############################################################################
# Shouldn't need to change below this line
############################################################################

start_time="`date`"

# Sanity checks
if test -z "$scratch_root" -o -z "$email" -o -z "$giturl" -o -z "$gitbranch" \
    -o -z "$destdir"; then
    echo "$0 scratch_root email_addr dest_dir git_url git_branch"
    exit 1
fi

# Use the branch name as the "version" string (for if there is an
# error).  This version string will be replaced upon successful "make
# distcheck" with the real version.
version=$gitbranch

# send a mail
# should only be called after logdir is set
send_error_mail() {
    outfile="$scratch_root/output.txt"
    rm -f "$outfile"
    touch "$outfile"
    for file in `/bin/ls $logdir/* | sort`; do
        len="`wc -l $file | awk '{ print $1}'`"
        if test "`expr $len \> $max_log_len`" = "1"; then
            echo "[... previous lines snipped ...]" >> "$outfile"
            tail -n $max_log_len "$file" >> "$outfile"
        else
            cat "$file" >> "$outfile"
        fi
    done
    Mail -s "=== CREATE FAILURE ($version) ===" "$email" < "$outfile"
    rm -f "$outfile"
}

# send output error message
die() {
    msg="$*"
    cat > "$logdir/00_announce.txt" <<EOF
Creating the nightly hwloc tarball ended in error:

$msg
EOF
    send_error_mail
    exit 1
}

# do the work
# should only be called after logdir is set
do_command() {
    cmd="$*"
    logfile="$logdir/20-command.txt"
    rm -f "$logfile"
    if test -n "$debug"; then
        echo "*** Running command: $cmd"
        eval $cmd 2>&1 | tee "$logfile"
        st=$?
        echo "*** Command complete: exit status: $st"
    else
        eval $cmd > "$logfile" 2>&1
        st=$?
    fi
    if test "$st" != "0"; then
        cat > "$logdir/15-error.txt" <<EOF

ERROR: Command returned a non-zero exist status ($version):
       $cmd

Start time: $start_time
End time:   `date`

=======================================================================
EOF
        cat > "$logdir/25-error.txt" <<EOF
=======================================================================

Your friendly daemon,
Cyrador
EOF
        send_error_mail
        exit 1
    fi
    rm -f "$logfile"
}

# see if the destination directory exists
if test ! -d "$destdir"; then
    mkdir -p "$destdir"
fi
if test ! -d "$destdir"; then
    die "Could not cd to dest dir: $destdir"
fi

# move into the scratch directory and ensure we have an absolute
# pathname for it
if test ! -d "$scratch_root"; then
    mkdir -p "$scratch_root"
fi
if test ! -d "$scratch_root"; then
    die "Could not cd to scratch root: $scratch_root"
fi
cd "$scratch_root"
scratch_root="`pwd`"

# setup target directory where clone+logs will go
clone_root="$scratch_root/hwloc-`date +%Y-%m-%d-%H%M%S`"
rm -rf $clone_root
mkdir -p $clone_root

# startup the logfile (must be before do_command)
logdir="$clone_root/logs"
mkdir "$logdir"

# Get a fresh git clone
cd $clone_root
do_command "git clone $giturl hwloc"
cd hwloc
do_command "git checkout $gitbranch"

# Nightly tarballs are named in this format:
# hwloc-${BRANCHNAME}-${YYYYMMDDHHMM}-${SHORTHASH}.tar.${COMPRESSION}
timestamp=`date '+%Y%m%d%H%M'`
githash=`git log -n 1 '--pretty=format:%h'`
version="$gitbranch-$timestamp-$githash"
if test -n "$debug"; then
    echo "*** This snapshot version: $version"
fi

# if there's a $destdir/latest_snapshot.txt, see if anything has
# happened since the version listed in that file
if test -f "$destdir/latest_snapshot.txt"; then
    snapshot_version=`cat $destdir/latest_snapshot.txt`
    if test -n "$debug"; then
        echo "*** Last snapshot version: $snapshot_version"
    fi

    # Do we need a new snapshot?
    # Snip the timestamp out of the versions and compare just
    # ${BRANCHNAME}-${SHORTHASH}.
    compare_version="$gitbranch-$githash"
    compare_snapshot_version=`echo $snapshot_version | perl -p -e 's/^(.+?)-(\d+)-(.*+)$/$1-$3/'`
    if test "$compare_version" = "$compare_snapshot_version"; then
        if test -n "$debug"; then
            echo "*** Our branch/git hash is the same as the last snapshot -- not doing anything"
        fi
        # Since we didn't do anything, there's no point in leaving the clone we
        # just created
        cd ..
        rm -rf $clone_root

        # All done... nothing to see here...
        exit 0
    fi
fi

if test -n "$debug"; then
    echo "*** Houston: we're a go to make snapshot $version"
fi

# Ensure that VERSION is set to indicate that it wants a snapshot, and
# insert the actual value that we want (so that hwloc_get_version.sh
# will report exactly that version).
sed -e 's/^snapshot=.*/snapshot=1/' \
    -e 's/^snapshot_version=.*/snapshot_version='$version/ \
    VERSION > VERSION.new
cp -f VERSION.new VERSION
rm -f VERSION.new

# autogen is our friend
do_command "./autogen.sh"

# do config
do_command "./configure"

# because of the doxygen setup, we now much run "make doc" before we
# run "make dist".
do_command "make doc"

# Do make distcheck (which will invoke config/distscript.csh to set
# the right values in VERSION).  distcheck does many things; we need
# to ensure it doesn't pick up any other installs via LD_LIBRARY_PATH.
# It may be a bit Draconian to totally clean LD_LIBRARY_PATH (i.e., we
# may need something in there), but at least in the current building
# setup, we don't.  But be advised that this may need to change in the
# future...
save=$LD_LIBRARY_PATH
LD_LIBRARY_PATH=
do_command "make distcheck"
LD_LIBRARY_PATH=$save
save=

# chmod the whole directory, so that core files are accessible by others
chmod a+rX -R .

# move the resulting tarballs to the destdir
gz="`/bin/ls hwloc*tar.gz`"
bz2="`/bin/ls hwloc*tar.bz2`"
mv $gz $bz2 $destdir
cd $destdir

# make the latest_snapshot.txt file containing the last version
version="`echo $gz | sed -e 's/hwloc-\(.*\)\.tar\.gz/\1/g'`"
rm -f latest_snapshot.txt
echo $version > latest_snapshot.txt

# trim the destdir to $max_snapshots
for ext in gz bz2; do
    count="`ls hwloc*.tar.$ext | wc -l | awk '{ print $1 }'`"
    if test "`expr $count \> $max_snapshots`" = "1"; then
        num_old="`expr $count - $max_snapshots`"
        old="`ls -rt hwloc*.tar.$ext | head -n $num_old`"
        rm -f $old
    fi
done

# generate md5 and sha1 sums
rm -f md5sums.txt sha1sums.txt
touch md5sums.txt sha1sums.txt
for file in `/bin/ls *gz *bz2 | grep -v latest`; do
    md5sum $file >> md5sums.txt
    sha1sum $file >> sha1sums.txt
done

# remove temp dirs
cd "$scratch_root"
rm -rf "$clone_root"

# send success mail
if test "$want_success_mail" = "1"; then
    Mail -s "Create success (hwloc git $version)" "$email" <<EOF
Creating nightly hwloc snapshot git tarball was a success.

Snapshot:   hwloc $version
Start time: $start_time
End time:   `date`

Your friendly daemon,
Cyrador
EOF
fi
