#!/bin/bash
#
# Creating a new CGAL internal+public release.
#
# Radu Ursu, Sylvain Pion, 2004-2006.

DO_PUBLIC=""             # Also build the public versions
DO_IT=""                 # Real mode (copy to HTTP server), versus local testing
DO_NOT_TAG=""            # If set, do not call tag
DO_TAG=""                # If set, tag is called anyway
NO_TESTUITE=""           # If set, the LATEST file is not updated
NO_SCM=""                # If set, git pull is not called.
SOURCES_DIR="$PWD"       # Directory containing the sources, default is "$PWD"
VERBOSE=""               # Verbose mode (displays log to standard err)
BETA=""                  #If set, will change the release number and version number accordingly.
DESTINATION="$PWD"
INTEGRATION=""

SOURCES_DIR_HAS_BEEN_SET=

printerr() {
    echo "$@" >&2;
}

usage() {
    printerr "Usage : $0 [--help] [--public] [--do-it] [--beta <n>] <packages dir>"
    printerr
    printerr '  --help           : prints this usage help'
    printerr '  --public         : also build the corresponding public versions'
    printerr '  --do-it          : the real thing (NOT for local tests!  Only for the release'
    printerr '                     master! Does write operations (updating the version_number,'
    printerr '                     tag, copying on the web server...)'
    printerr '  --do-not-tag     : when used with --do-it, the tag is not created.'
    printerr '  --tag            : when used without --do-it, the tag is created, but files'
    printerr '                     are not published'
    printerr '  --no-scm-update  : do not "git pull"'
    printerr '  --no-testsuite   : when used with --do-it, the tag is made, files are published,'
    printerr '                     but the LATEST file is not updated.'
    printerr '  --verbose        : print log to standard output, instead of the log file'
    printerr '  --beta <n>       : followed by a number. When used with --public, will modify
    the release number and the release version name to include beta<n>'
    printerr '  --dest           : followed by the path to where the release should be created. Default is /tmp.'
    printerr '  --integration    : replace the I in the name by Ic.'
    printerr '  <packages dir>   : the directory containing the packages [default is trunk]'
}


# Parsing command-line
while [ $1 ]; do
    case "$1" in
        -h|-help|--h|--help)
            usage;
            exit;
        ;;
        --public)
            DO_PUBLIC="ON"
            shift; continue
        ;;
        --do-it)
            DO_IT="y"
            shift; continue
        ;;
        --no-scm-update)
            NO_SCM="y";
            shift; continue
        ;;
        --tag)
            DO_TAG="y"
            shift; continue
        ;;
        --do-not-tag)
            DO_NOT_TAG="y"
            shift; continue
        ;;
        --no-testsuite)
            NO_TESTSUITE="y"
            shift; continue
        ;;
        --verbose)
            VERBOSE="ON"
            shift; continue
        ;;
        --beta)
            shift;
            BETA=$1
            re='^[0-9]+$'
            if ! [[ $BETA =~ $re ]] ; then
               echo "error: --beta must be followed by an integer." >&2; exit 1
            fi
            shift;
            continue
        ;;
        --dest)
            shift
            DESTINATION=$1
            shift;continue
        ;;
        --integration)
            INTEGRATION="y"
            shift;continue
        ;;
        -*)
            printerr "Unrecognized option : $1"
            exit
        ;;
        *)
            if [ -z "$SOURCES_DIR_HAS_BEEN_SET" ]; then
                SOURCES_DIR="$1"
                SOURCES_DIR_HAS_BEEN_SET=y
                shift; continue
            elif [ -z "$INTEGRATION" ]; then
                # Compatibility with the old syntax with candidates
                INTEGRATION="y"
                shift; continue
            else
                printerr "Unrecognized option : $1"
                usage
            fi
        ;;
    esac
done

# The internal release number is extracted/updated from this file :
VERSION_FILE="version_number"

# Where to put the resulting tarball and where to send the announce.
HTML_DIR="/u/agrion/geometrica/CGAL/Members/Releases"
URL="http://cgal.inria.fr/CGAL/Members/Releases"


PATH=$PATH:/usr/local/bin:/usr/sbin

# Working dir
TMPDIR="`pwd`"

if [ -f $HOME/.cgal_create_new_release_rc ]; then
  . $HOME/.cgal_create_new_release_rc
fi

[ -n "$DO_IT" -a -z "$DO_NOT_TAG" ] && DO_TAG="y"
[ -z "$DO_IT" ] && HTML_DIR=$TMPDIR/tmp
[ -d "$HTML_DIR" ] || mkdir "$HTML_DIR"

# ISO format ("date -I" does not work on Darwin).
date_=`date "+%Y-%m-%d"`

LOGFILE="${TMPDIR}/create_release.log.$date_.$$"

if [ -z "$VERBOSE" ]; then
  # Redirect standard out and standard err to $LOGFILE
  exec 3>&1 >> ${LOGFILE}
fi

# Verbose: displays all executed commands
#PS4='[${LINENO}]+ '
#set -x

# Exit once a sub-command exits with an error
set -e

cd ${TMPDIR} || return

# Update the working copy
if [ -e "${SOURCES_DIR}/.git" ]; then
    pushd "${SOURCES_DIR}"
    [ -z "$NO_SCM" ] && git pull
    CGAL_GIT_HASH=`git rev-parse HEAD`
    popd
else
    echo "Not a git repository"
    exit 1
fi
# Set the major/minor/bugfix release numbers
NUMBERS_DIR=${SOURCES_DIR}/Maintenance/release_building
if [ -f ${NUMBERS_DIR}/MAJOR_NUMBER ]; then
    MAJOR_NUMBER=`cat ${NUMBERS_DIR}/MAJOR_NUMBER`     # 2 digits max
    MINOR_NUMBER=`cat ${NUMBERS_DIR}/MINOR_NUMBER`     # 2 digits max
    BUGFIX_NUMBER=`cat ${NUMBERS_DIR}/BUGFIX_NUMBER`   # 1 digit max
else
    eval $(cmake -DCGALCONFIGVERSIONFILE=${SOURCES_DIR}/CGALConfigVersion.cmake -P ${SOURCES_DIR}/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake 2>&1)
fi

# Do not show the bugfix number if it is 0.
if [ x"$BUGFIX_NUMBER" != "x0" ]; then
    BUGFIX_STRING=".$BUGFIX_NUMBER"
else
    BUGFIX_STRING=""
fi

# Compute the internal release number.
if [ -r $VERSION_FILE ]; then
  INTERNAL_NUMBER=$(( `cat $VERSION_FILE` + 1 ))
  [ -n "$DO_TAG" ] && printf "%d\n" "${INTERNAL_NUMBER}" > $VERSION_FILE
else
  echo "Need a \"version_number\" file."
fi
if [ -z "$INTERNAL_NUMBER" ]; then
  INTERNAL_NUMBER=1
fi

if [ -n "${INTEGRATION}" ]; then
    INTERNAL_STRING="-Ic-${INTERNAL_NUMBER}"
else
    INTERNAL_STRING="-I-${INTERNAL_NUMBER}"
fi

internal_nr=`printf "%4s" "${INTERNAL_NUMBER}" | sed "y/ /0/"`

if [ -r "${NUMBERS_DIR}/release_name" ]; then
    release_version=`cat "${NUMBERS_DIR}/release_name"`${INTERNAL_STRING}
else
    release_version="${MAJOR_NUMBER}.${MINOR_NUMBER}${BUGFIX_STRING}${INTERNAL_STRING}"
fi
release_name="CGAL-${release_version}"
echo "${release_name}"
major_nr=`printf "%2s" "${MAJOR_NUMBER}" | sed "y/ /0/"`
minor_nr=`printf "%2s" "${MINOR_NUMBER}" | sed "y/ /0/"`
bugfix_nr=`printf "%1s" "${BUGFIX_NUMBER}" | sed "y/ /0/"`
release_number="1${major_nr}${minor_nr}${bugfix_nr}${internal_nr}"
echo "Release number is ${release_number}"

if [ -n "$DO_IT" -a -e "${HTML_DIR}/${release_name}.tar.gz" ]; then
    printf "%s\n" "\"${HTML_DIR}/${release_name}.tar.gz\" already exists!"
    exit 1
fi

function cleanup() {
    # Remove local directory and tarball
    if [ -d ${release_name} ]; then
      rm -rf ./"${release_name}"
    fi
    if [ -d "${DESTINATION}/${release_name}" ]; then
        rm -rf "${DESTINATION}/${release_name}"
    fi
    if [ -f ${release_name}.tar.gz ]; then
      rm ${release_name}.tar.gz
    fi
    if [ -n "$DO_PUBLIC" ]; then
        [ -d "${public_release_name}" ] && rm -rf  ./"${public_release_name}"
        rm -rf doc
        #  rm -rf doc_tex
        rm -rf doc_html
        rm -f "${public_release_name}.tar.gz" "${public_release_name}.zip"
    fi
}

trap cleanup EXIT

# Create the release
cmake -DGIT_REPO=${SOURCES_DIR} -DPUBLIC=NO -DTESTSUITE=ON -DDESTINATION="${DESTINATION}" -DCGAL_VERSION="${release_version}" -DCGAL_VERSION_NR="${release_number}" -DVERBOSE="${VERBOSE}" -P ${SOURCES_DIR}/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake
pushd "${DESTINATION}/${release_name}"
sed -i -e "s/define CGAL_GIT_HASH .*/define CGAL_GIT_HASH $CGAL_GIT_HASH/" include/CGAL/version.h
cd ..
# Make the release tarball
rm -f "${release_name}".tar*
tar -cf "${release_name}.tar" "${release_name}"
gzip "${release_name}.tar"
cp "${release_name}.tar.gz" "${HTML_DIR}"
rm -f "$HTML_DIR/CGAL-last.tar.gz"
ln -s "${release_name}.tar.gz" "$HTML_DIR/CGAL-last.tar.gz"
if [ -z "${NO_TESTSUITE}" ]; then
  echo "${release_name}.tar.gz" > "${HTML_DIR}/LATEST"
fi
popd

# Tag
if [ -n "$DO_TAG" ]; then
#    mail -s "[automatic] ${release_name} is released" ${MAILTO} <<EOF
#
#You can fetch it at :
#${URL}/${release_name}.tar.gz
#
#EOF

    # Now we tag.
    echo "Tagging ${SOURCES_DIR} with $release_name"
    if [ -n "$NO_TESTSUITE" ]; then
        TAG_MSG_EXTRA=" (no testsuite)"
    fi
fi


# Build public release version
if [ -n "$DO_PUBLIC" ]; then
    echo "Making the public version of the tarball"
    if [ -n "$BETA" ]; then
      public_release_number="1${major_nr}${minor_nr}${bugfix_nr}09${BETA}0"
    else
      public_release_number="1${major_nr}${minor_nr}${bugfix_nr}1000"
    fi
    public_release_version="${MAJOR_NUMBER}.${MINOR_NUMBER}${BUGFIX_STRING}"
    if [ -n "$BETA" ]; then
        public_release_version="${public_release_version}-beta${BETA}"
    fi
    if [ -r "${NUMBERS_DIR}/public_release_name" ]; then
        public_release_name=`cat "${NUMBERS_DIR}/public_release_name"`
        public_release_version=${public_release_name#CGAL-}
    else
        public_release_name="CGAL-${public_release_version}"
    fi
    if ! [ -f ${NUMBERS_DIR}/MAJOR_NUMBER ]; then
        eval $(cmake -DCGALCONFIGVERSIONFILE=${SOURCES_DIR}/CGALConfigVersion.cmake -P ${SOURCES_DIR}/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake 2>&1)
    fi

    cmake -DGIT_REPO=${SOURCES_DIR} -DGENERATE_TARBALLS="ON" -DPUBLIC="ON" -DDESTINATION="${DESTINATION}" -DCGAL_VERSION="${public_release_version}" -DCGAL_VERSION_NR="${public_release_number}" -DVERBOSE="${VERBOSE}" -P ${SOURCES_DIR}/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake
    tar -xf ${public_release_name}.tar.xz
    mkdir "${HTML_DIR}/${release_name}-public"
    # Do a Zip file as well for the public version.
    zip -q -r ${public_release_name}.zip ${public_release_name}
    rm -rf ./${public_release_name}
    tar -xf ${public_release_name}-examples.tar.xz
    zip -q -r ${public_release_name}-examples.zip ${public_release_name}
    rm -rf ./${public_release_name}
    tar xf ${public_release_name}-library.tar.xz
    zip -q -r ${public_release_name}-library.zip ${public_release_name}
    mv ${public_release_name}*.tar.xz "${HTML_DIR}/${release_name}-public/"
    mv ${public_release_name}*.zip "${HTML_DIR}/${release_name}-public/"
    if command -v sestatus >/dev/null 2>&1; then
        sestatus && restorecon -R "${HTML_DIR}/${release_name}-public"
    fi
    rm -f "$HTML_DIR/CGAL-last-public"
    ln -s "${release_name}-public" "$HTML_DIR/CGAL-last-public"
fi
