#!/bin/bash
#
########################################################################
# GLOBAL VARIABLES
#
# General
AUTHOR='S. Bardeau <gildas@iram.fr>'
VERSION=`echo '$Revision: 1.13 $' | cut -d' ' -f2`
PROJECT='MOPSIC (R.W.Zylka) / GILDAS <http://www.iram.fr/IRAMFR/GILDAS>'
PROGNAME=`basename $0`
#
GILDASDIR=$HOME/gildas                 # Gildas
MOPSICDIR=$HOME/mopsic                 # Mopsic
RELEASEDIR=$HOME/www/dist              # www/ public directory
ARCHIVEDIR=$RELEASEDIR/archive/mopsic  # www/ public directory for archives
#
###########################################################################
#
# Define local functions
#
function usage() {
    cat <<EOF 1>&2
This script as of its current status can be used to compile mopsic and
release the binaries in a .tar.gz archive. Mopsic will be built in
\$HOME/mopsic. Gildas is assumed to be found in \$HOME/gildas, else it
will be checked-out from the CVS repository in \$HOME/mopsic.

If binaries are to be built, dynamic linking is used unless "-o staticlink"
option is provided.

More features may come later such as releasing the sources or building
mopsic automatically on all available machines at IRAM.

usage:
  $PROGNAME [-s] [-e] [-c <compiler>] [-g <ref>] [-D <date>] [-o <config>]
            [-h] [-v]

version:
  month        Alias for current month e.g. apr09
  apr09,may09,...
  <other versions not yet supported>

options:
  -s           Release the mopsic sources (not yet implemented)
  -e           Release the mopsic executable. Implies the build of mopsic, i.e.
               requires -g and optionally a version.
  -c <compiler>  Use the input compiler (default ifort)
  -g <ref>     Get Gildas version from input branch or tag. Mandatory argument
               when binaries are to be built or released.
  -D <date>    Get mopsic sources from input date-time instead of current
               status. Allowed syntax must be accepted by 'date', e.g.
               "2009-01-08 15:00". If no version or -D option are given,
               current date-time is used.
  -o <config>  Use the input config (e.g. staticlink)
  -h           Show this help page
  -v           Show version information

examples:
  $PROGNAME -e -g mar08 -D "2009-01-01 12:00"
  $PROGNAME -e -g mar08 -o staticlink month
EOF
}
#
function showversion() {
    echo "$PROGNAME version $VERSION, by $AUTHOR"
    echo "Project: $PROJECT"
}
#
function message() {
    echo "$PROGNAME "`date '+%Y-%m-%d %k:%M:%S'`": $@"
}
#
function error_exit() {
    # $1: Status to be returned
    # $2: Message to be echoed
    # $3: Logfile to be echoed (last lines)
    #
    # Error status numbers:
    #  1  Problem in calling sequence / options
    #  2  Could not define system
    #  3  Tree problem, e.g. file or directory not found
    #  4  CVS failure
    #  5  Compilation failure (make)
    #  6  Installation failure (make install)
    #  7  Problem when releasing binaries
    #
    ERROR_STATUS=$1
    ERROR_MESSAGE=$2
    ERROR_LOGFILE=$3
    if [ -n "$ERROR_LOGFILE" ]; then
	echo                               1>&2
	echo "Last 10 lines of log file:"  1>&2
	echo $ERROR_LOGFILE                1>&2
	echo                               1>&2
	tail -10 $ERROR_LOGFILE            1>&2
    fi
    echo                                   1>&2
    echo "$PROGNAME error: $ERROR_MESSAGE" 1>&2
    echo                                   1>&2
    #
    if [ -n "$FAILURE" ]; then
	echo $ERROR_STATUS > $FAILURE || \
	    echo "$PROGNAME error: Creating failure trace file ($FAILURE)"
    fi
    #
    exit $ERROR_STATUS
}
#
function remove_version() {
    # Removes src, exe, and logs directories of input version. Must be
    # called from appropriate directory. Does not complain if $1 is empty,
    # or if directories do not exist (thanks to the -f flag). These are
    # desired behaviours.
    if [ -z "$1" ]; then
	return 0
    fi
    #
    message "Clean '$1' version"
    # Order matters here:
    rm -rf ./mopsic-src-$1       2>&1  # Sources
    if [ $? -ne 0 ]; then
	message "Unable to remove mopsic-src-$1"
	return 1
    fi
    rm -rf ./mopsic-exe-$1       2>&1  # Executables
    if [ $? -ne 0 ]; then
	message "Unable to remove mopsic-exe-$1"
	return 1
    fi
#     rm -rf ./logs/$1             2>&1  # Logs
#     if [ $? -ne 0 ]; then
# 	message "Unable to remove logs/$1"
# 	return 1
#     fi
}
#
function make_install() {
    # Go to $1 directory and execute 'make install' into $MOPSICEXEDIR
    # from there. $LOGFILE must be correctly defined before calling.
    #
    SUBDIR=$1
    message "Install $SUBDIR in '$MOPSICEXEDIR'"
    #
    cd $SUBDIR   >> $LOGFILE 2>&1 || \
	error_exit 3 "cd'ing to $SUBDIR"                    $LOGFILE
    #
    make install >> $LOGFILE 2>&1 || \
	error_exit 6 "install'ing $SUBDIR in $MOPSICEXEDIR" $LOGFILE

}
#
########################################################################
# OPTION PARSING
#
message "Building mopsic on $HOSTNAME: $PROGNAME $@"
#
temp=`getopt "ec:g:D:o:hv" "$@"`
if [ $? -ne 0 ]; then usage; exit 1; fi
eval set -- "$temp"
unset temp
while [ $1 != -- ]; do
    case "$1" in
    -e) release_exe=1 ;;
    -c) COMPILER=$2;   shift ;; # Compiler to be used
    -g) GILDASREF=$2;  shift ;; # Gildas reference name
    -D) MOPSICDATE=$2; shift ;; # Mopsic reference version
    -o) CONFIG=$2;     shift ;; # Additional config to use
    -v) showversion; exit 0 ;;
    -h) usage; exit 0 ;;
    *)  usage; exit 1 ;;
    esac
    shift # Next flag
done
shift # Skip double dash
#
if [ -n "$1" ]; then
    MOPSICREF=$1  # A reference version is given in the command line
    if [ "$MOPSICREF" = "dev" ]; then
        MOPSICTAG="HEAD"  # Tag recognized by CVS
    else
        MOPSICTAG=$MOPSICREF
    fi
fi
set abc; shift # This line to avoid remanence effect in a portable way
#
if [ -z "$COMPILER" ]; then
    COMPILER=ifort   # Default ifort
fi
#
if [ -z "$GILDASREF" ]; then
    message "Missing option '-g <ref>' is required"
    usage
    exit 1
fi
if [ "$GILDASREF" = "mar08" ]; then
    GILDASREPO="gildas-2008"
else
    GILDASREPO="gildas"  # Name of the module on the repository
fi
#
if [ -n "$MOPSICDATE" ] && [ -n "$MOPSICREF" ]; then
    message "Incompatible option -D and input version"
    usage
    exit 1
fi
if [ -z "$MOPSICDATE" ] && [ -z "$MOPSICREF" ]; then
    # Use current date
    MOPSICDATE=`date '+%Y-%m-%d %k:%M'`
fi
# Check if input date is valid
date -d "$MOPSICDATE" > /dev/null || error_exit 1 "invalid date '$MOPSICDATE'"
#
if [ -n "$CONFIG" ]; then
    BUILDOPT="-o $CONFIG"
fi
#
########################################################################
# SYSTEM
#
# Ensure a stable $gagadmdir to start the process
export gagadmdir=$GILDASDIR/gildas-admin
if [ ! -d "$gagadmdir" ]; then
    error_exit 2 "\$gagadmdir=$gagadmdir does not exist"
fi
#
# Define system (GAG_EXEC_SYSTEM)
. $gagadmdir/define-system.sh                 # Load gagdefsys function
gagdefsys -c $COMPILER > /dev/null || exit 2  # Use them
unset gagdefsys                               # Remove them
#
########################################################################
# ENVIRONMENT
#
if [ -z "$MOPSICREF" ]; then
    MOPSICREF=`date -d "$MOPSICDATE" '+%d%b%y' | tr '[:upper:]' '[:lower:]'`  # Date of Mopsic version
elif [ "$MOPSICREF" = "month" ]; then
    MOPSICREF=`date '+%b%y' | tr '[:upper:]' '[:lower:]'`
fi
MOPSICSRCDIR=$MOPSICDIR/mopsic-src-$MOPSICREF  # Where Mopsic sources are found
MOPSICEXEDIR=$MOPSICDIR/mopsic-exe-$MOPSICREF  # Where Mopsic builds are found
#
# Logs
LOGDIR=$MOPSICDIR/logs/$MOPSICREF
if [ ! -d $LOGDIR ]; then
    mkdir -p $LOGDIR || error_exit 3 "creating \$LOGDIR=$LOGDIR directory"
fi
#
LOGGILDAS=$LOGDIR/gildas-$GAG_EXEC_SYSTEM
LOGMOPSIC=$LOGDIR/mopsic-$GAG_EXEC_SYSTEM
if [ -n "$CONFIG" ]; then
    LOGGILDAS=$LOGGILDAS-$CONFIG
    LOGMOPSIC=$LOGMOPSIC-$CONFIG
fi
#
# Delete the file traces from any previous build
SUCCESS=$LOGMOPSIC.success
if [ -e "$SUCCESS" ]; then
    rm -f $SUCCESS || error_exit 3 "cleaning success file ($SUCCESS)"
fi
FAILURE=$LOGMOPSIC.failure
if [ -e "$FAILURE" ]; then
    rm -f $FAILURE || error_exit 3 "cleaning failure file ($FAILURE)"
fi
#
# Restart from scratch if binaries have to be released
if (($release_exe)); then
    message "Binary release: remove old mopsic directories"
    cd $MOPSICDIR || error_exit 3 "cd to mopsic directory '$MOPSICDIR' (1)"
    remove_version $MOPSICREF || error_exit 3 "removing old mopsic directories"
fi
#
########################################################################
# GILDAS
#
# Where Gildas sources are found ?
if [ -d "$GILDASDIR/gildas-src-$GILDASREF" ]; then
    GILDASSRCDIR=$GILDASDIR/gildas-src-$GILDASREF
    message "Using pre-existing Gildas src dir '$GILDASSRCDIR'"
    cd $GILDASSRCDIR
    #
    # If a CVS version, update
    if [ -d "CVS" ]; then
	message "Update gildas ref: cvs up -r $GILDASREF -A"
	cvs up -r $GILDASREF -A > $LOGGILDAS.cvs 2>&1 ||  \
	    error_exit 4 "updating gildas ref: cvs up -r $GILDASREF -A" $LOGGILDAS.cvs
    fi
else
    # Else, check it out in $MOPSICDIR
    GILDASSRCDIR=$MOPSICDIR/gildas-src-$GILDASREF
    message "No pre-existing Gildas src dir. Check out my own in '$GILDASSRCDIR'"
    cd $MOPSICDIR
    cvs co -d gildas-src-$GILDASREF -r $GILDASREF $GILDASREPO  \
	> $LOGGILDAS.cvs 2>&1 ||  \
	error_exit 4 "checking out gildas ref: cvs co -d gildas-src-$GILDASREF -r $GILDASREF $GILDASREPO" $LOGGILDAS.cvs
    cd $GILDASSRCDIR
fi
#
# Set environment
message "Set compilation environment for gildas $GILDASREF"
unset gaghome gagadmdir gagsrcdir gagusedir gagintdir gagexedir
source admin/gildas-env.sh -c $COMPILER $BUILDOPT > $LOGGILDAS.env 2>&1
export gagexedir=$MOPSICEXEDIR
source $gagadmdir/show-path > $LOGGILDAS.path 2>&1 || \
    error_exit 3 "Showing paths" $LOGGILDAS.path
#
# Compile
message "Make gildas $GILDASREF"
make > $LOGGILDAS.compile 2>&1 || error_exit 5 "make'ing gildas" $LOGGILDAS.compile
#
# Install
LOGFILE=$LOGGILDAS.install
make_install $GILDASSRCDIR/kernel/etc          # gag.dico.gbl is required
make_install $GILDASSRCDIR/kernel/doc          # Kernel docs might be useful
make_install $GILDASSRCDIR/packages/astro/etc  # ephini requires gag_ephemeris=vsop87.bin
#
# Install nothing more. Binaries not required (and not desired) because
# of the staticlink (not true anymore)
#
########################################################################
# MOPSIC
#
cd $MOPSICDIR || error_exit 3 "cd to mopsic directory '$MOPSICDIR' (2)"
#
if [ -d "mopsic-src-$MOPSICREF/CVS" ]; then
    CVSOPT="up -A"
    CVSDIR="mopsic-src-$MOPSICREF"
else
    CVSOPT="co -A -d mopsic-src-$MOPSICREF"
    CVSDIR="mopsic"
fi
#
# Check-out or update mopsic
if [ -n "$MOPSICDATE" ]; then
    message "cvs mopsic: cvs $CVSOPT -D \"$MOPSICDATE\" $CVSDIR"
    cvs $CVSOPT -D "$MOPSICDATE" $CVSDIR > $LOGMOPSIC.cvs 2>&1 ||  \
        error_exit 4 "cvs'ing mopsic: cvs $CVSOPT -D \"$MOPSICDATE\" $CVSDIR" $LOGMOPSIC.cvs
else
    message "cvs mopsic: cvs $CVSOPT -r $MOPSICTAG $CVSDIR"
    cvs $CVSOPT -r $MOPSICTAG $CVSDIR > $LOGMOPSIC.cvs 2>&1 ||  \
        error_exit 4 "cvs'ing mopsic: cvs $CVSOPT -r $MOPSICTAG $CVSDIR" $LOGMOPSIC.cvs
fi
cd mopsic-src-$MOPSICREF
#
# Check out or update the administrative directory. Get it from Gildas ref.
if [ -d "admin/CVS" ]; then
    CVSOPT="up -A"
    CVSDIR="admin"
else
    CVSOPT="co -A -d admin"
    CVSDIR="$GILDASREPO/admin"
fi
message "cvs admin: cvs $CVSOPT -r $GILDASREF $CVSDIR"
cvs $CVSOPT -r $GILDASREF $CVSDIR >> $LOGMOPSIC.cvs 2>&1 ||  \
    error_exit 4 "cvs'ing admin: cvs $CVSOPT -r $GILDASREF $CVSDIR" $LOGMOPSIC.cvs
#
# Set the environment
message "Set compilation environment for mopsic $MOPSICREF"
unset gaghome gagadmdir gagsrcdir gagusedir gagintdir gagexedir
source admin/gildas-env.sh -c $COMPILER $BUILDOPT -u $GILDASSRCDIR/integ  \
    > $LOGMOPSIC.env 2>&1
export gagexedir=$MOPSICEXEDIR
if [ "$CONFIG" = "staticlink" ] && [ "$COMPILER" = "ifort" ]; then
    export GAG_FLDFLAGS="-i-static"  # Links statically with ifort libraries (9.0)
    # export GAG_FLDFLAGS="-static-intel"  # Links statically with ifort libraries (> 10.0)
fi
source $gagadmdir/show-path > $LOGMOPSIC.path 2>&1 || \
    error_exit 3 "Showing paths" $LOGMOPSIC.path
#
# Compile
message "Make mopsic $MOPSICREF"
make > $LOGMOPSIC.compile 2>&1 || error_exit 5 "make'ing mopsic" $LOGMOPSIC.compile
#
# Install
LOGFILE=$LOGMOPSIC.install
make_install $MOPSICSRCDIR        # Whole mopsic
make_install $GILDASSRCDIR/admin  # Install the etc/bash_profile
#
########################################################################
# TAR + RELEASE
#
if (($release_exe)); then
    #
    HARDWARE=`uname -m`  # ix86 or x86_64 ?
    #
    # Add the README file to the release
    message "Generate README"
    cat <<EOF > $MOPSICEXEDIR/README
This archive contains mopsic binaries for Linux $HARDWARE machines
as of $MOPSICDATE and a minimum number of files necessary to launch
it.
It does not contain the Data Associated Files (calibration files
and links needed by MOPSIC to calibrate your data). Please ask for
them to R.Zylka or Pico Veleta. More informations available here:
http://www.iram.es/IRAMES/mainWiki/CookbookMopsic

INSTALL:

  I) Permament availability:
    The lines below show how to make mopsic available at any time.
    WARNING, this may introduce conflict with your gildas
    installation, if any!

    bash users: add in your ~/.bash_profile the following lines
        export GAG_ROOT_DIR=<install-dir>/mopsic-exe-$MOPSICREF
        export GAG_EXEC_SYSTEM=$GAG_EXEC_SYSTEM
        source \$GAG_ROOT_DIR/etc/bash_profile

    csh users:  add in your ~/.login the following lines
        setenv GAG_ROOT_DIR <install-dir>/mopsic-exe-$MOPSICREF
        setenv GAG_EXEC_SYSTEM $GAG_EXEC_SYSTEM
        source \$GAG_ROOT_DIR/etc/login

    You should then exit this xterm and open a new one to reset your
    path.

  II) On-demand availability:
    The lines below show how to make mopsic available only when
    desired. This is more flexible but requires to load a function
    each time you open a new terminal.

    bash users: add in your ~/.bash_profile the following lines
        function gagmopsic() {
            export GAG_ROOT_DIR=<install-dir>/mopsic-exe-$MOPSICREF
            export GAG_EXEC_SYSTEM=$GAG_EXEC_SYSTEM
            source \$GAG_ROOT_DIR/etc/bash_profile
        }

    csh users:  add in your ~/.login the following lines
        <not available>

    You should then exit this xterm, call 'gagmopsic' at the shell
    prompt when desired, and then call 'mopsic'.
EOF
    #
    # Tar
    TARNAME=mopsic-exe-$MOPSICREF-$HARDWARE.tar.gz
    message "Tar'ing in $TARNAME"
    cd $MOPSICDIR
    if [ -e "$TARNAME" ]; then
	rm -v $TARNAME > $LOGMOPSIC.release 2>&1 || \
	    error_exit 3 "could not remove $TARNAME" $LOGMOPSIC.release
    fi
    tar -cvzf $TARNAME mopsic-exe-$MOPSICREF >> $LOGMOPSIC.release 2>&1 || \
	error_exit 7 "tar'ing mopsic-exe-$MOPSICREF/* in $TARNAME" $LOGMOPSIC.release
    #
    # Release
    if [ -d "$RELEASEDIR" ]; then
	message "Releasing in $RELEASEDIR"
	#
	# Cleaning/archiving
	if [ -e "$RELEASEDIR/$TARNAME" ]; then
	    rm -v $RELEASEDIR/$TARNAME >> $LOGMOPSIC.release 2>&1 || \
		error_exit 3 "could not remove $RELEASEDIR/$TARNAME" $LOGMOPSIC.release
	fi
	mv -v $RELEASEDIR/mopsic-exe-*-$HARDWARE.tar.gz $ARCHIVEDIR \
	    >> $LOGMOPSIC.release 2>&1
	#
	# Move
	mv -v $TARNAME                                  $RELEASEDIR \
	    >> $LOGMOPSIC.release 2>&1 || \
	    error_exit 3 "moving $TARNAME in $RELEASEDIR" $LOGMOPSIC.release
	#
	# Reprocess the index.html files
	cd $RELEASEDIR
	ls2html -t "GILDAS download area"    -x index.html > index.html || \
	    error_exit 7 "making index.html for distrib dir $RELEASEDIR"
	cd $ARCHIVEDIR
	ls2html -t "MOPSIC download archive" -x index.html > index.html || \
	    error_exit 7 "making index.html for archive dir $ARCHIVEDIR"
	#
    else
	message "Release directory '$RELEASEDIR' does not exist. Skipping."
    fi
    #
fi
#
########################################################################
# Final trace for successfull build
#
touch $SUCCESS || error_exit 99 "Touching success trace file ($SUCCESS)"
#
message "Built successfull on $HOSTNAME"
#
########################################################################
