#!/bin/bash

#---------------------------------------------------------------------------
#
# Project: OpenWalnut ( http://www.openwalnut.org )
#
# Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
# For more information see http://www.openwalnut.org/copying
#
# This file is part of OpenWalnut.
#
# OpenWalnut is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenWalnut is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
#
#---------------------------------------------------------------------------

#############################################################################################################
# Release Configuration Variables
#############################################################################################################

# Which version?
VERSION_BASE=1.3.1

# Any additonal tags?
VERSION_TAGS=""

# Should the package number contain the HG revision?
VERSION_INCLUDE_HG=1

# Where to grab the sources?
REPO="ssh://openwalnut.com//srv/hg/ow"
REPO_BRANCH="OpenWalnut_1.3"
# build from a release branch?
#REPO_BRANCH="OpenWalnut_$VESION"

# Which packages to build
PACKAGES="deb src"

# Define which chroot/distribution to use for build the packages
# NOTE: supported are "sid wheezy squeeze lucid maverick natty"

# As we only need a source DEB, we do not build the deb for all supported distributions. The NeuroDebian project is doing this.
# DISTRIBUTIONS_DEB="sid wheezy squeeze lucid maverick natty"
DISTRIBUTIONS_DEB="sid wheezy quantal precise oneiric"

# use these distributions to build binary tgz
#DISTRIBUTIONS_TGZ="sid wheezy squeeze lucid maverick natty"
# I am not sure whether this is useful? The binary would depend on a very specific boost version ... maybe we fix this by providing the boost libs too?
DISTRIBUTIONS_TGZ=""

# Architectures to build for
# NOTE: we need the debsrc package.
ARCHITECTURES_DEB="i386 amd64"
# Build binary tgz for 386 and amd64
ARCHITECTURES_TGZ="amd64"

# where to put the created stuff?
RELEASE_DIR="OpenWalnut-Release"

#############################################################################################################
# Internal Variables
#############################################################################################################

# Ensure english warning/error text (easier googling)
export LC_ALL=C

# Where to put the files
CHECKOUT_DIR="OpenWalnut-hg"

# the source config file
CONFIG_FILE=owrelease.config

# Where to put logs from this script not distri/arch or pack specific.
MAINLOGFILE="$0.log"

#############################################################################################################
# Functions
#############################################################################################################

#########################################################################################################
# Checkout a fresh OW copy and create config file. Copy newest script versions.
Bootstrap()
{
    echo "* Removing old checkout."
    rm -rf "$CHECKOUT_DIR"
    if [ $? -ne 0 ]; then
        echo " * Remove failed."
        exit 1
    fi

    # get code
    echo "* Cloning OpenWalnut repository \"$REPO\"."
    hg clone --branch $REPO_BRANCH "$REPO" "$CHECKOUT_DIR"
    if [ $? -ne 0 ]; then
        echo " * Cloning failed. Wrong repository?"
        exit 1
    fi

    echo "* Creating release directory \"$RELEASE_DIR\"."
    mkdir -p $RELEASE_DIR
    if [ $? -ne 0 ]; then
        echo " * Creating release directory failed."
        exit 1
    fi

    # write config file
    echo "SRC_DIR=$CHECKOUT_DIR" > $CONFIG_FILE
    echo "RELEASE_DIR=$RELEASE_DIR" >> $CONFIG_FILE
    # The version. You can use shell commands to evaluate this. The command is
    # called inside the working dir of owpack script.
    echo "VERSION_BASE=$VERSION_BASE" >> $CONFIG_FILE
    if [ $VERSION_INCLUDE_HG -ne 0 ]; then
        echo "VERSION=$VERSION_BASE$VERSION_TAGS+hg`cd $CHECKOUT_DIR;hg parents --template "{rev}"`" >> $CONFIG_FILE
    else
        echo "VERSION=$VERSION_BASE$VERSION_TAGS" >> $CONFIG_FILE
    fi

    # get the latest scripts
    cp $CHECKOUT_DIR/tools/release/owpack .
    cp $CHECKOUT_DIR/tools/release/owbuildchroot .
    cp $CHECKOUT_DIR/tools/release/owrelease .
}

#########################################################################################################
# Cleanup any mess. Remove build stuff but keeps config and checkout (and scripts), like after bootstrap.
CleanUp()
{
    echo "* Removing logs."
    # we need root since the build-user in the chroot is root and created some
    # files
    rm -f $0-*.log
    rm -f $MAINLOGFILE

    echo "* Removing buildfiles."
    sudo ./owpack clean || exit $?

    echo "* Removing packages."
    rm -rf $RELEASE_DIR/*
}

#########################################################################################################
# Complete cleanup. Removes everything created.
Purge()
{
    CleanUp

    echo "* Removing checkout."
    rm -rf $CHECKOUT_DIR

    echo "* Removing scripts."
    rm -f owpack
    rm -f owbuildchroot
    rm -f owrelease

    echo "* Removing config."
    rm -f $CONFIG_FILE

    echo "* Removing releases."
    rm -rf $RELEASE_DIR
}

#########################################################################################################
# Build for different target systems
BuildAll()
{
    echo "LOG created by $0 on `date`" > $MAINLOGFILE

    # does config exist? Needed. If not found, abort
    if [ ! -f $CONFIG_FILE ]; then
        echo " * File \"$CONFIG_FILE\" not found! Forgot to bootstrap?"
        exit 1
    fi

    for pack in $PACKAGES
    do
        # gather information on the needed distributions and architectures for this type of package
        PkgDistributions="sid" # default
        PkgArchitectures="i386 amd64"
        case "$pack" in
            src)
                PkgDistributions="sid"
                PkgArchitectures="amd64"
                ;;
            deb)
                PkgDistributions=$DISTRIBUTIONS_DEB
                PkgArchitectures=$ARCHITECTURES_DEB
                ;;
            tgz)
                PkgDistributions=$DISTRIBUTIONS_TGZ
                PkgArchitectures=$ARCHITECTURES_TGZ
                ;;
            *)
                echo "* Unknown package \"$pack\"" | tee -a $MAINLOGFILE
                exit 1
                ;;
        esac

        # build package for each of its distributions and architectures
        for distri in $PkgDistributions
        do
            for arch in $PkgArchitectures
            do
                LOGFILE=$0-$pack-$distri-$arch.log
                echo "LOG created by $0 on `date`" > $LOGFILE

                # check for chroot existence
                echo "* Check build chroot for $pack-$distri-$arch." | tee -a $MAINLOGFILE
                sudo ./owbuildchroot $arch $distri check &>> $MAINLOGFILE
                if [ $? -ne 0 ]; then
                    echo " * Build chroot not found. Creating." | tee -a $MAINLOGFILE
                    sudo ./owbuildchroot $arch $distri create &>> $MAINLOGFILE
                    if [ $? -ne 0 ]; then
                        echo " * Error. Build chroot not found." | tee -a $MAINLOGFILE
                        # do not be very tolerant. A missing chroot is a fatal error
                        exit 1
                    fi
                fi

                # do
                echo "* Building $pack for \"$distri-$arch\". Log: $LOGFILE" | tee -a $MAINLOGFILE
                sudo ./owbuildchroot $arch $distri run /build/owpack $pack $distri-$arch /build &>> $LOGFILE

                # for later error reporting
                if [ $? -ne 0 ]; then
                    echo " * Error while building for \"$distri\", $arch. Check \"$LOGFILE\" for details" | tee -a $MAINLOGFILE
                    continue
                fi
            done
        done
    done
}

#########################################################################################################
# Something went wrong. Quit.
#
# Param 1 the error code to return.
Exit()
{
    echo "*** Failed. Exiting."
    exit $1
}

#########################################################################################################
# Quit and print usage info.
UsageExit()
{
        echo "Central script for release management. Bootstraps the OpenWalnut Release code and starts the building."
        echo ""
        echo "Usage: $0 {clean|purge|bootstrap|do}"
        echo "  COMMANDS:"
        echo "    clean: removes created build sub-directories and logs but keeps bootstrap status."
        echo "    purge: like clean but also removes checkouts and scripts."
        echo "    bootstrap: gets a fresh copy of OpenWalnut."
        echo "    do: does the actual building."
        echo ""
        Exit 2
}

#########################################################################################################
# Main

# Handle user command
case "$1" in
    clean)
        CleanUp
        ;;
    purge)
        Purge
        ;;
    bootstrap)
        Bootstrap || Exit $?
        ;;
    do)
        BuildAll || Exit $?
        ;;
    *)
        UsageExit
        ;;
esac
