#!/bin/sh

########################################################################
# Regenerate auto-generated files (e.g. configure)
#
# If the -s option is given, save the autogenerated scripts in
# $SAGE_ROOT/upstream/configure-$CONFVERSION.tar.gz where CONFVERSION
# is the sha1 of HEAD `git rev-parse HEAD`
#
# If optional argument -d is given and bootstrapping failed, instead
# extract the files from a local configure tarball, downloading it if
# needed. If -D is given, don't try to bootstrap and always extract or
# download.
#
# If optional argument -u <URL> is given download the configure
# tarball from that base url. That is, "bootstrap -u http://host/path"
# will download http://host/path/configure-$CONFVERSION.tar.gz to
# upstream/configure-$CONFVERSION.tar.gz. This is used by the buildbot
# to download tarballs that are not published.
#
# The -q (quiet) flag hides all "informational" output.
#
########################################################################

# Set SAGE_ROOT to the path to this file and then cd into it
SAGE_ROOT="$(cd "$(dirname "$0")" && pwd -P)"
export SAGE_ROOT
cd "$SAGE_ROOT"

export PATH="$SAGE_ROOT/build/bin:$PATH"

PKG=build/pkgs/configure
MAKE="${MAKE:-make}"
CONFVERSION=$(cat $PKG/package-version.txt)

install_config_rpath() {
    # The file config.rpath which comes from gettext is supposed to be
    # installed by automake, but due to a bug in most distros it is not;
    # see https://trac.sagemath.org/ticket/27823#comment:17
    #
    # Here we need to determine where gettext stores its data files and
    # copy config.rpath from there to config/
    gettextize="$(command -v gettextize)"
    if [ -z "$gettextize" ]; then
        echo >&2 "gettext and the gettextize program must be installed and be in"
        echo >&2 "your PATH. E.g. Homebrew installs them in /usr/local/opt/gettext/bin."
        return 179
    fi
    eval `sed -n '/^prefix=.*$/p' "$gettextize"`
    eval `sed -n '/^datarootdir=.*$/p' "$gettextize"`
    eval `sed -n '/^: \${gettext_datadir=.*$/p' "$gettextize"`

    if [ -z "$gettext_datadir" ]; then
        eval `sed -n '/^gettext_dir=.*$/p' "$gettextize"`
        # In older versions (before 2014) this is spelled gettext_dir
        # See https://github.com/autotools-mirror/gettext/commit/ff18897068486560e2bb421004cfbd42b7cdd0f8
        gettext_datadir="$gettext_dir"
    fi

    if [ -z "$gettext_datadir" ]; then
        echo >&2 "Failed to read the gettext_datadir directory from $gettextize"
        echo >&2 "The config.rpath file must manually be copied into config/"
        echo >&2 "This file is installed with gettext typically in /usr/share/gettext"
        return 179
    fi

    config_rpath="$gettext_datadir/config.rpath"
    if [ ! -f "$config_rpath" ]; then
        echo >&2 "Missing $config_rpath file; this indicates a broken gettext install."
        return 179
    fi

    if [ "${BOOTSTRAP_QUIET}" = "no" ]; then
	echo "bootstrap:$LINENO: installing 'config/config.rpath'"
    fi
    cp "$config_rpath" config/
}



bootstrap () {
    rm -f m4/sage_spkg_configures.m4
    spkg_configures=""

    # initialize SAGE_ENABLE... options for standard packages
    for pkgname in $(./sage --package list :standard: | sort); do
        spkg_configures="$spkg_configures
AS_VAR_SET_IF([SAGE_ENABLE_$pkgname], [], [AS_VAR_SET([SAGE_ENABLE_$pkgname], [yes])])"
    done
    # --enable-SPKG options
    for pkgname in $(./sage --package list :optional: :experimental: | sort); do
                # Trac #29629: Temporary solution for Sage 9.1: Do not provide
                # --enable-SPKG options for installing pip packages
                if [ ! -f build/pkgs/$pkgname/requirements.txt ]; then
                    pkgtype="$(cat build/pkgs/$pkgname/type)"
                    # Trac #29124: Do not provide --enable-_recommended and similar
                    case "$pkgname" in
                        _*) ;;
                        *)  spkg_configures="$spkg_configures
AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed])"
                            if [ -f build/pkgs/$pkgname/spkg-install -o -f build/pkgs/$pkgname/spkg-install.in ]; then
                                # Trac #31163: Not just an optional dummy package
                                spkg_configures="$spkg_configures
SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(head -n1 build/pkgs/$pkgname/SPKG.rst 2>/dev/null || echo $pkgname)])"
                            fi
                            ;;
                    esac
                fi
    done
    for pkgname in $(./sage --package list --has-file spkg-configure.m4 | sort); do
        echo "m4_sinclude([build/pkgs/$pkgname/spkg-configure.m4])" >> m4/sage_spkg_configures.m4
        spkg_configures="$spkg_configures
SAGE_SPKG_CONFIGURE_$(echo ${pkgname} | tr '[a-z]' '[A-Z]')"
    done
    echo "$spkg_configures" >> m4/sage_spkg_configures.m4

    for pkgname in $(./sage --package list --has-file bootstrap); do
        (cd build/pkgs/$pkgname && ./bootstrap) || exit 1
    done

    # Default to no filter if "-q" was not passed.
    QUIET_SED_FILTER=""
    if [ "${BOOTSTRAP_QUIET}" = "yes" ]; then
	# Otherwise, this filters the expected output from automake.
	QUIET_SED_FILTER='/configure\.ac:[0-9][0-9]*: installing /d'
    fi

    # The insanity with automake's descriptors is intended to filter
    # ONLY stderr, and to re-output the results back to stderr leaving
    # stdout alone. Basically we swap the two descriptors using a
    # third, filter, and then swap them back.
    src/doc/bootstrap && \
    install_config_rpath && \
    aclocal -I m4 && \
    automake --add-missing --copy build/make/Makefile-auto 3>&1 1>&2 2>&3 \
        | sed "${QUIET_SED_FILTER}" 3>&1 1>&2 2>&3 && \
    autoconf

    st=$?
    case $st in
        0) true;; # Success

        179|16|63|127)  # install_config_rpath failed|no m4 for pkg-config|autotools not installed|or version too old
            if [ $DOWNLOAD = yes ]; then
                echo >&2 "Bootstrap failed, downloading required files instead."
                bootstrap_download || exit $?
            else
                if [ $st -eq 127 ]; then
                    verb="install"
                elif [ $st -eq 16 ]; then
                    verb="install pkg-config m4 macros for"
                else
                    verb="upgrade"
                fi
                echo >&2 "Bootstrap failed. Either $verb autotools and gettext; or run bootstrap with"
                echo >&2 "the -d option to download the auto-generated files instead."

                SYSTEM=$(build/bin/sage-guess-package-system)
                if test $SYSTEM != unknown; then
                    SYSTEM_PACKAGES=$(build/bin/sage-get-system-packages $SYSTEM _bootstrap)
                    if test -n "$SYSTEM_PACKAGES"; then
                        PRINT_SYS="build/bin/sage-print-system-package-command $SYSTEM --verbose=\"    \" --prompt=\"      \$ \" --sudo"
                        COMMAND=$(eval "$PRINT_SYS" update && eval "$PRINT_SYS" install $SYSTEM_PACKAGES && SAGE_ROOT="$SAGE_ROOT" eval "$PRINT_SYS" setup-build-env )
                        echo >&2
                        echo >&2 "hint: On your system ($SYSTEM), you can install the required system packages as follows:"
                        echo >&2 "$COMMAND"
                        echo >&2
                    fi
                fi
                exit $st
            fi;;

        *) exit $st;; # Failure
    esac
}

# Bootstrap by downloading the auto-generated files
bootstrap_download () {
    SAGE_DL_LOGLEVEL=""
    [ "${BOOTSTRAP_QUIET}" = "yes" ] && SAGE_DL_LOGLEVEL="--log=WARNING"
    sage-download-file ${SAGE_DL_LOGLEVEL} configure-$CONFVERSION.tar.gz

    if [ $? -ne 0 ]; then
        echo >&2 "Error: downloading configure-$CONFVERSION.tar.gz failed"
        exit 1
    fi

    # The "m" option to tar ensures that timestamps are set to the
    # current time, not taken from the tarball.
    # We need these files to be more recent than the input files
    # like configure.ac, otherwise "make" gets confused.
    tar xzmf $CONFBALL || exit $?
}

save () {
    set -e

    # Check that config.guess is sufficiently recent
    if ! grep '^timestamp=.*20\(1[5-9]\|2[0-9]\)' config/config.guess >/dev/null; then
        echo >&2 "Error: config.guess is outdated:"
        grep >&2 '^timestamp=' config/config.guess
        echo >&2 "You should update the 'gnuconfig' or 'automake' package and try again"
        exit 63
    fi

    NEWCONFVERSION=`git rev-parse HEAD`
    NEWCONFBALL="upstream/configure-$NEWCONFVERSION.tar.gz"

    # Create configure tarball
    if [ "${BOOTSTRAP_QUIET}" = "no" ]; then
	echo "Creating $NEWCONFBALL..."
    fi
    mkdir -p upstream
    tar zcf "$NEWCONFBALL" \
	configure \
	config/* \
	build/make/Makefile-auto.in \
	src/doc/en/installation/*.txt \
	src/doc/en/reference/spkg/*.rst \
	src/doc/en/reference/repl/*.txt \
	environment.yml \
	src/environment.yml \
	environment-optional.yml \
	src/environment-optional.yml \
	src/Pipfile \
	src/pyproject.toml \
	src/requirements.txt \
	src/setup.cfg

    # Update version
    echo "$NEWCONFVERSION" >$PKG/package-version.txt

    # Compute checksum
    if [ "${BOOTSTRAP_QUIET}" = "no" ]; then
	./sage --package fix-checksum configure
    else
	# Hide the "Updating checksum..." message
	./sage --package fix-checksum configure > /dev/null
    fi
}


usage () {
    echo >&2 "Usage: $0 [-d|-D|-s] [-u <URL>] [-h] [-q]"
    echo >&2 ""
    echo >&2 "Options:"
    echo >&2 "  -d         fall back to downloading (released versions only)"
    echo >&2 "             or using a pre-generated configure script"
    echo >&2 "  -D         download and use a pre-generated configure script"
    echo >&2 "             (released versions only); overrides -d"
    echo >&2 "  -s         save the generated configure script under upstream/"
    echo >&2 "             for later use with -d or -D"
    echo >&2 "  -u <URL>   like -D, but downloads from the specified base URL"
    echo >&2 "  -h         display this help and exit"
    echo >&2 "  -q         hide informational output (be quiet)"
}


# Parse options
SAVE=no
DOWNLOAD=no
ALWAYSDOWNLOAD=no
CONFTARBALL_URL=""
BOOTSTRAP_QUIET=no
while getopts "Ddsu:hq" OPTION
do
     case "$OPTION" in
         D) ALWAYSDOWNLOAD=yes; DOWNLOAD=yes;;
         d) DOWNLOAD=yes;;
         s) SAVE=yes;;
         u) CONFTARBALL_URL="$OPTARG"; ALWAYSDOWNLOAD=yes; DOWNLOAD=yes;;
         h) usage; exit 0;;
         q) BOOTSTRAP_QUIET=yes;;
         ?) usage; exit 2;;
     esac
done
export BOOTSTRAP_QUIET
CONFBALL="upstream/configure-$CONFVERSION.tar.gz"

if [ $DOWNLOAD$SAVE = yesyes ]; then
    echo >&2 "$0: refusing to download and save."
    usage
    exit 2
fi

# Start cleanly (it's not a problem if this fails)
# POSIX supports two separate incompatible formats for the MAKEFLAGS
# variable, so instead of guessing, we simply define our own variable
# to optionally pass an "-s" (silent) flag to Make.
MAKE_SILENT=""
[ "${BOOTSTRAP_QUIET}" = "yes" ] && MAKE_SILENT="-s"
$MAKE ${MAKE_SILENT} bootstrap-clean 2>/dev/null
mkdir config 2>/dev/null

if [ $ALWAYSDOWNLOAD = yes ]; then
    if [ -n "$CONFTARBALL_URL" ]; then
        URL="$CONFTARBALL_URL"/configure-$CONFVERSION.tar.gz
        SAGE_DL_LOGLEVEL=""
        [ "${BOOTSTRAP_QUIET}" = "yes" ] && SAGE_DL_LOGLEVEL="--log=WARNING"
        sage-download-file ${SAGE_DL_LOGLEVEL} "$URL" upstream/configure-$CONFVERSION.tar.gz
        if [ $? -ne 0 ]; then
            echo >&2 "Error: downloading configure-$CONFVERSION.tar.gz from $CONFTARBALL_URL failed"
            exit 1
        fi
        echo >&2 "Downloaded configure-$CONFVERSION.tar.gz from $CONFTARBALL_URL "
    else
        bootstrap_download || exit $?
    fi
else
    bootstrap
fi

if [ $SAVE = yes ]; then
    save
fi
