#!/bin/bash
#
# Variable and function definitions
#
AUTHOR='J. Pety <pety@iram.fr>'
VERSION=`echo '$Revision: 1.47 $' | cut -d' ' -f2`
PROJECT='GILDAS <http://www.iram.fr/IRAMFR/GILDAS>'
PROGNAME=`basename $0`
REPOSITORY="git@git.iram.fr:scsf/gildas.git"
#
usage() {
    cat <<EOF 1>&2

  (Re)build (ie get, compile and install) a GILDAS version using standard
directory name conventions. A log of all command output is automatically
kept. When used with the "source-gag.sh" script, it enable easy coexistence
of many different GILDAS version. However, it may also be used to regularly
rebuild just one version.
  The script returns an error code to the caller if something goes wrong
during the build. It also creates a trace file in the logs directory which
can be sensed to check after on if the build was a success or not.

usage: $PROGNAME [options] [version]

version:     description:                 repository tag:
  dev          Latest repository state      HEAD
  day          Current day (ie today)       day
  last         Last fully compilable        last
  month        Current month                (Not available)
  jan04        jan04 monthly release        jan04

Comment: contrary to the "last" version, the "day" one may not
         be compilable!

options:
  -c compiler Replace default compiler by this one
  -D          Clean current version for current system
  -R          Remove current version (sources but also binaries for all systems)
  -G          Get sources from the GIT repository
  -U          Update sources from the GIT repository (a checked-out version must
              exist already)
  -C          Compile sources
  -I          Install executables
  -P          Make and install PDF doc
  -W          Make and install WWW doc (ie html)
  -e          Equivalent to -GCI
  -a          Equivalent to -GCIPW
  -o config   Add config to the config list
  -t target   Define the system target compiled under current build environment
  -h          Show this help page
  -v          Show version information

EOF
}
#
showversion() {
    echo "$PROGNAME version $VERSION, by $AUTHOR"
    echo "Project: $PROJECT"
}
#
message() {
    echo "$PROGNAME: $1"
}
#
error_exit() {
    ERROR_STATUS=$1
    ERROR_MESSAGE=$2
    ERROR_LOGFILE=$3
    if [ "$ERROR_LOGFILE" != "" ]; then
	echo  1>&2
	echo "Last 20 lines of log file:"  1>&2
	echo $ERROR_LOGFILE 1>&2
	echo  1>&2
	tail -20 $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
}
#
# This function is to go around old "which" implementations who returned
# status is always 0 even though the command has not been found...
#
gag_which() {
    PROG=$1
    FOUND=`which $PROG 2> /dev/null`
    if [ $? -ne 0 ]; then
	exit 1
    else
	if [ `echo $FOUND | grep -c -i "no $PROG"` -ne 0 ]; then
	    exit 1
	elif [ `echo $FOUND | grep -c -i "not found"` -ne 0 ]; then
	    exit 1
	else
	    echo $FOUND
	    exit 0
	fi
    fi
}
#
is_git_repo() {
    # Return 0 (success) if the input directory name is a git-versioned
    # directory. Return 1 (error) if not.
    if [ ! -d $1 ]; then
      return 1;
    fi
    \cd $1 || return 1;
    if git rev-parse --git-dir > /dev/null 2>&1; then
      returnval=0;
    else
      returnval=1;
    fi;
    \cd $OLDPWD;
    \return $returnval;
}
#
###########################################################################
#
# Option parsing
#
IN_COMPILER="default" # Default compiler will be setup by gagdefsys
temp=`getopt "c:DRGUCIPWaeo:t:hv" "$@"`
if [ $? -ne 0 ]; then usage; exit 1; fi
eval set -- "$temp"
unset temp
while [ $1 != -- ]; do
    case $1 in
    -c) IN_COMPILER=$2; shift ;;
    -D) clean=1 ;;
    -R) remove=1 ;;
    -G) checkout=1 ;;
    -U) update=1 ;;
    -C) compile=1 ;;
    -I) install=1 ;;
    -P) pdf=1 ;;
    -W) html=1 ;;
    -t) TARGET=$2; ENVOPT="-t $2" ;;
    -e) checkout=1; compile=1; install=1 ;;
    -a) checkout=1; compile=1; install=1 ; pdf=1 ; html=1 ;;
    -o) CONFIG=$2; ENVOPT="-o $2" ;;
    -v) showversion; exit 0 ;;
    -h) usage; exit 0 ;;
    esac
    shift # Next flag
done
shift # Skip double dash
case $# in
    0) IN_VERSION="default" ;; # Default version will be setup by gagdefver
    1) IN_VERSION=$1 ;;
    *) usage; exit 1 ;;
esac
set abc; shift # This line to avoid remanence effect in a portable way
#
###########################################################################
#
# Test for GNU make
#
GMAKE=`gag_which gmake`
if [ -z "$GMAKE" ]; then
    GMAKE=`gag_which make`
    if [ -z "$GMAKE" ]; then
        error_exit 6 "No make in your \$PATH"
    else
        if [ `$GMAKE -v 2>&1 | grep -c "GNU"` -eq 0 ]; then
            error_exit 6 "Your make is not the GNU one"
        fi
    fi
fi
#
###########################################################################
#
# Define admin directory (gagadmdir)
#
if [ -z "$gaghome" ]; then
    gaghome=$HOME/gildas
    export gaghome
fi
if [ -d "$gaghome/gildas-admin" ]; then
    gagadmdir=$gaghome/gildas-admin
elif [ -d "$gagsrcdir/admin" ]; then
    gagadmdir=$gagsrcdir/admin
else
    echo "$PROGNAME error: Failed to define \$gagadmdir." 1>&2
    exit 2
fi
export gagadmdir
#
# Define system (GAG_EXEC_SYSTEM) and version (GAG_VERS/GAG_TAG)
#
. $gagadmdir/define-system.sh       # Load gagdefsys function
. $gagadmdir/define-version.sh      # Load gagdefver function
gagdefsys $ENVOPT -c $IN_COMPILER > /dev/null || exit 2  # Use them
gagdefver -d $IN_VERSION || exit 2  # Default is to refine date as much as possible in GAG_VERS
unset gagdefsys gagdefver           # Remove them
#
# Initial message
#
message "Try to (re)build GILDAS version: $GAG_VERS on $GAG_EXEC_SYSTEM"
#
# Create needed directories and go to the source directory
#
if [ ! -d $LOGDIR ]; then
    mkdir -p $LOGDIR || error_exit 3 "creating \$LOGDIR directory"
fi
LOGFILE=$LOGDIR/$GAG_EXEC_SYSTEM
#
# Delete the file traces from any previous build
SUCCESS=$LOGFILE.success
if [ -e "$SUCCESS" ]; then
    rm -f $SUCCESS || error_exit 3 "cleaning success file ($SUCCESS)"
fi
FAILURE=$LOGFILE.failure
if [ -e "$FAILURE" ]; then
    rm -f $FAILURE || error_exit 3 "cleaning failure file ($FAILURE)"
fi
#
# Remove current version source tree before building new one when asked.
# This removes sources AND integration branch, i.e. all binaries of ALL
# systems for this version.
#
if [ "$remove" ]; then
    message "Remove"
    rm -rf $SRCDIR > $LOGFILE.rm 2>&1 || \
	error_exit 4 "removing old version" $LOGFILE.rm
fi
#
# Clean current version in integration branch, i.e. all binaries for
# current system and for this version.
#
if [ "$clean" ]; then
    message "Clean"
    if [ -d "$SRCDIR" ]; then
	cd $SRCDIR || error_exit 4 "going to \$SRCDIR=$SRCDIR directory"
	nice $GMAKE distclean GAG_EXEC_SYSTEM=$GAG_EXEC_SYSTEM > $LOGFILE.clean 2>&1 ||\
	    error_exit 4 "cleaning current version" $LOGFILE.clean
    else
	error_exit 4 "\$SRCDIR=$SRCDIR does not exist."
    fi
fi
#
# Check-out/update GILDAS from repository
if [ "$checkout" -a "$update" ]; then
    error_exit 5 "incompatible options -G and -U" $LOGFILE.git
fi
#
if [ "$checkout" ]; then
    if is_git_repo "$SRCDIR"; then
	message "Get sources (pulling)"
	cd $SRCDIR || error_exit 5 "going to \$SRCDIR directory" $LOGFILE.git
	git checkout $GAG_TAG > $LOGFILE.git 2>&1 || \
            error_exit 5 "checking out branch $GAG_TAG" $LOGFILE.git
	git pull > $LOGFILE.git 2>&1 || \
	    error_exit 5 "pulling branch $GAG_TAG" $LOGFILE.git
    else
	message "Get sources (cloning from scratch)"
	cd `dirname $SRCDIR`
	git clone --branch $GAG_TAG --single-branch \
	    $REPOSITORY `basename $SRCDIR` > $LOGFILE.git 2>&1 || \
	    error_exit 5 "cloning sources from GIT." $LOGFILE.git
	cd $SRCDIR
    fi
    rm -f $SRCDIR/VERSION
    echo $GAG_VERS > $SRCDIR/VERSION
    chmod a-w $SRCDIR/VERSION
fi
#
if [ "$update" ]; then
    if ! is_git_repo "$SRCDIR"; then
	error_exit 5 "no previous version found to be pulled from GIT." $LOGFILE.git
    fi
    message "Pulling sources"
    cd $SRCDIR || error_exit 5 "going to \$SRCDIR directory" $LOGFILE.git
    git checkout $GAG_TAG > $LOGFILE.git 2>&1 || \
        error_exit 5 "checking out branch $GAG_TAG" $LOGFILE.git
    git pull > $LOGFILE.git 2>&1 || \
	error_exit 5 "pulling branch $GAG_TAG" $LOGFILE.git
fi
#
# Check if $SRCDIR has been created ($checkout = 1), or already exists.
#
if [ ! -d "$SRCDIR" ]; then
    error_exit 3 "\$SRCDIR=$SRCDIR does not exist"
fi
#
# Set up GILDAS compilation environment
#
if [ "$compile" -o "$install" -o "$pdf" -o "$html" ]; then
    message "Setup env"
    ogagsrcdir=$gagsrcdir
     gagsrcdir=$SRCDIR
    export ogagsrcdir gagsrcdir
    . $gagadmdir/gildas-env.sh -c "$IN_COMPILER" "$ENVOPT" > $LOGFILE.env 2>&1 || \
	error_exit 6 "setting up GILDAS environment." $LOGFILE.env
    . $gagadmdir/go.sh >> $LOGFILE.env 2>&1 || \
	error_exit 6 "going to $gagsrcdir" $LOGFILE.env
    . $gagadmdir/show-path > $LOGFILE.path 2>&1 || \
	error_exit 6 "showing paths" $LOGFILE.path
fi
#
# Compile
#
if [ "$compile" ]; then
    message "Compile"
    nice $GMAKE SYSTEM=$GAG_COMP_SYSTEM > $LOGFILE.compile 2>&1 || \
	error_exit 7 "compiling GILDAS environment." $LOGFILE.compile
fi
#
# Remove current version executable tree before installing new one
#
if [ "$remove" ]; then
    message "Remove"
    rm -rf $EXEDIR/$GAG_EXEC_SYSTEM >> $LOGFILE.rm 2>&1 || \
	error_exit 4 "removing old version" $LOGFILE.rm
fi
#
# Install
#
if [ "$install" ]; then
    message "Install"
    nice $GMAKE install GAG_EXEC_SYSTEM=$GAG_EXEC_SYSTEM > $LOGFILE.install 2>&1 ||\
	error_exit 8 "installing GILDAS." $LOGFILE.install
fi
#
# Make and install pdf doc
#
if [ "$pdf" ]; then
    message "pdf doc"
    nice $GMAKE install-doc GAG_EXEC_SYSTEM=$GAG_EXEC_SYSTEM > $LOGFILE.pdf 2>&1 ||\
	error_exit 9 "Making or installing GILDAS PDF doc." $LOGFILE.pdf
fi
#
# Make and install html doc
#
if [ "$html" ]; then
    message "html doc"
    nice $GMAKE install-html GAG_EXEC_SYSTEM=$GAG_EXEC_SYSTEM > $LOGFILE.html 2>&1 ||\
	error_exit 10 "Making or installing GILDAS HTML doc." $LOGFILE.html
fi
#
# Final trace for successfull build
#
touch $SUCCESS || error_exit 99 "Touching success trace file ($SUCCESS)"
#
# Final message
#
message "It worked! Bye."
#
###########################################################################
