#!/usr/bin/env bash
#
#  sage-spkg: install a Sage package
#
#  This script is typically invoked by giving the command
#      sage {-i|-p} <options> <package name>...
#
#  sage-spkg itself only accepts one <package name>.
#
#      sage-spkg <options> <package name> [<installation tree>]
#
#  Options can be:
#   -s: do not delete temporary build directory
#   -k: do not uninstall existing installation of this package before
#       installing; instead simply overwrite existing files.
#   -c: after installing, run the test suite for the spkg. This should
#       override the settings of SAGE_CHECK.
#       Exit with an error if the test suite fails.
#   -w: after installing, run the test suite for the spkg. This should
#       override the settings of SAGE_CHECK.
#       Print a warning if the test suite fails.
#   -d: only download the package
#   -y: automatically reply "y" for all prompts regarding
#       experimental and old-style packages
#   -n: automatically reply "n" for all prompts regarding
#       experimental and old-style packages
#
#  A package may assume that the following environment
#  variables are defined:
#
#      SAGE_ROOT      -- root directory of sage distribution
#      SAGE_LOCAL     -- prefix where packages are installed (usually $SAGE_ROOT/local)
#      SAGE_INST_LOCAL-- prefix where to install this package;
#                        this is set by the optional argument <installation tree>
#                        and defaults to $SAGE_LOCAL.
#      SAGE_DISTFILES -- directory that stores upstream tarballs
#      SAGE_DESTDIR   -- temporary root the package will be installed to
#      PKG_BASE       -- the base name of the package itself (e.g. 'patch')
#      PKG_VER        -- the version number of the package
#      PKG_NAME       -- $PKG_BASE-$PKG_VER
#      LIBRARY_PATH, PYTHONPATH, LD_LIBRARY_PATH, DYLD_LIBRARY_PATH
#      CC, CXX, CFLAGS, CXXFLAGS, LDFLAGS, MAKE
#
#  Your package script should try to build using the giving CC, CXX,
#  CFLAGS, MAKE, etc, via a file spkg-install in your script.
#
#  This script does the following:
#
#      1. Set environment variables (by calling sage-env)
#      2. Extract the metadata and upstream sources into a build directory
#      3. Run the script in the package called spkg-install
#      4. Return error 1 if anything goes wrong.
#
# AUTHORS:
#
# - Robert Bradshaw, R. Andrew Ohana (2013): #14480: extend functionality to
#   support the unified git repository.
#
# - Jeroen Demeyer (2012-02-27): #12602: refactor code to find packages,
#   download them and extract them.
#
# - Jeroen Demeyer (2012-02-27): #12479: big reorganization.
#
# - Volker Braun, Jeroen Demeyer (2012-01-18): #11073: remove the
#   spkg/base repository, move this file from local/bin/sage-spkg to
#   spkg/bin/sage-spkg.
#
# - William Stein, John Palmieri and others (Sage 4.8 and earlier).
#
#*****************************************************************************
#  Distributed under the terms of the GNU General Public License (GPL)
#  as published by the Free Software Foundation; either version 2 of
#  the License, or (at your option) any later version.
#                  http://www.gnu.org/licenses/
#*****************************************************************************

# Avoid surprises with character ranges [a-z] in regular expressions
# See Trac #15791; some locales can produce different results for
# character ranges; using C.UTF-8 to ensure UTF-8 default encoding in Python
# introduces extra complications, see #30053, so we don't do it, but
# assume we are on Python3.x,  for x at least 7.
export LC_ALL=C

usage()
{
cat <<EOF
Usage: sage {-i|-p} <options> <package name>

Search Sage's list of packages (see 'sage --package list') for a
matching package, and if a match is found, install it.

Options:
   -s: do not delete the temporary build directory
   -c: after installing, run the test suite for the package;
       exit with an error on test suite failures
   -w: after installing, run the test suite for the package;
       print a warning on test suite failures
   -d: only download the package
   -y: automatically reply "y" for all prompts regarding
       experimental and old-style packages; warning: there
       is no guarantee that these packages will build correctly;
       use at your own risk"
   -n: automatically reply "n" for all prompts regarding
       experimental and old-style packages
   -o: allow fetching the package from its upstream URL
       when it is not available from the Sage mirrors (yet)
EOF
}

# error_msg(header, command)
# This is for printing an error message if something went wrong.
# The first argument is the header to print. If given, the second
# argument should be some proposed command to run in the subshell
# such as "make".
error_msg()
{
cat >&2 <<MESSAGE
************************************************************************
$1
************************************************************************
Please email sage-devel (http://groups.google.com/group/sage-devel)
explaining the problem and including the log files
  $SAGE_LOGS/$PKG_NAME.log
and
  $SAGE_ROOT/config.log
Describe your computer, operating system, etc.
MESSAGE

if [ -n "$2" ]; then
cat >&2 <<MESSAGE
If you want to try to fix the problem yourself, *don't* just cd to
`pwd` and type '$2' or whatever is appropriate.
Instead, the following commands setup all environment variables
correctly and load a subshell for you to debug the error:
  (cd '`pwd`' && '$SAGE_ROOT/sage' --buildsh)
When you are done debugging, you can type "exit" to leave the subshell.
MESSAGE
fi

cat >&2 <<MESSAGE
************************************************************************
MESSAGE
}

lookup_param()
{
    local param=$1
    local file=$2
    # Ignore errors if the file does not exist
    sed -n "s/^${param} *= *//p" $file 2>/dev/null
}

write_to_tty()
{
    # Try writing to terminal.  Suppress the possible error message
    if ! ( cat > /dev/tty ) 2> /dev/null ; then
        # Fall back to writing to stdout
        cat
        return 1
    fi
}

# Handle -n, -t, -q options for recursive make
# See Trac #12016.
if echo "$MAKE $MAKEFLAGS -$MAKEFLAGS" |grep '[ ]-[A-Za-z]*[qnt]' >/dev/null; then
    if echo "$MAKE $MAKEFLAGS -$MAKEFLAGS" |grep '[ ]-[A-Za-z]*q' >/dev/null; then
        # Pretend the target is *not* up-to-date
        exit 1
    else
        exit 0
    fi
fi

##################################################################
# Set environment variables
##################################################################

# The following sets environment variables for building packages.
# Since this is sourced, it returns a non-zero value on errors rather
# than exiting.  Using dot suggested by W. Cheung.
. sage-env-config
. sage-env

if [ $? -ne 0 ]; then
    error_msg "Error setting environment variables by sourcing sage-env"
    exit 1
fi

. sage-build-env-config
. sage-build-env

if [ $? -ne 0 ]; then
    error_msg "Error setting environment variables by sourcing sage-build-env"
    exit 1
fi

# Remove '.' from PYTHONPATH, to avoid trouble with setuptools / easy_install
# (cf. #10192, #10176):
if [ -n "$PYTHONPATH" ]; then
    # We also collapse multiple slashs into a single one (first substitution),
    # remove leading './'s and trailing '/.'s (second and third), and
    # remove leading, trailing and redundant ':'s (last three substitutions):
    new_pp=`echo ":$PYTHONPATH:" \
        | sed \
        -e 's|//*|/|g' \
        -e 's|:\(\./\)\{1,\}|:|g' \
        -e 's|\(/\.\)\{1,\}:|:|g' \
        -e 's|\(:\.\)\{1,\}:|:|g' \
        -e 's|::*|:|g' -e 's|^::*||' -e 's|::*$||'`

    if [ "$PYTHONPATH" != "$new_pp" ]; then
        echo "Cleaning up PYTHONPATH:"
        echo "  Old: \"$PYTHONPATH\""
        echo "  New: \"$new_pp\""
        PYTHONPATH=$new_pp
        export PYTHONPATH # maybe redundant, but in any case safe
    fi
fi

##################################################################
# Handle special command-line options
##################################################################
if [ $# -eq 0 ]; then
   usage
   exit 0
fi

# Parse options
INFO=0
YES=0
KEEP_EXISTING=0
while true; do
    case "$1" in
        --info)
            INFO=1;;
        -y)
            YES=1;;
        -n)
            YES=-1;;
        -d)
            SAGE_INSTALL_FETCH_ONLY=1;;
        -s)
            export SAGE_KEEP_BUILT_SPKGS=yes;;
        -c|--check)
            export SAGE_CHECK=yes;;
        -w|--check-warning-only)
            export SAGE_CHECK=warn;;
        -k|--keep-existing)
            KEEP_EXISTING=yes;;
        -o|--allow-upstream)
            SAGE_DOWNLOAD_FILE_OPTIONS+=" --allow-upstream";;
        -*)
            echo >&2 "Error: unknown option '$1'"
            exit 2;;
        *) break;;
    esac
    shift
done


##################################################################
# Figure out the package filename, download it if needed.
##################################################################
# One should be able to install a package using
# sage -i <package-name>

PKG_SRC="$1"
# Does PKG_SRC contain a slash?
if echo "$PKG_SRC" | grep / >/dev/null; then
    echo >&2 "Error: Installing old-style SPKGs is no longer supported"
    exit 1
fi
PKG_NAME="$PKG_SRC"
PKG_BASE=`echo "$PKG_NAME" | sed 's/-.*//'` # strip version number

case $# in
    1)
        SAGE_INST_LOCAL="$SAGE_LOCAL"
        ;;
    2)
        SAGE_INST_LOCAL="$2"
        ;;
    *)
        usage
        exit 1
        ;;
esac
export SAGE_INST_LOCAL

if [ -z "$SAGE_BUILD_DIR" ]; then
    export SAGE_BUILD_DIR="$SAGE_INST_LOCAL/var/tmp/sage/build"
fi

export SAGE_SPKG_INST="$SAGE_INST_LOCAL/var/lib/sage/installed"
export SAGE_SPKG_SCRIPTS="$SAGE_INST_LOCAL/var/lib/sage/scripts"
export SAGE_SPKG_WHEELS="$SAGE_INST_LOCAL/var/lib/sage/wheels"

# PKG_SRC should look like "package-VERSION" or just "package".
# If VERSION matches the version in build/pkgs or there is no version
# specified, use the local scripts; otherwise we try to find a package
# in upstream.
PKG_VER="${PKG_NAME#${PKG_BASE}}"
PKG_VER="${PKG_VER#-}"
PKG_SCRIPTS="$SAGE_ROOT/build/pkgs/$PKG_BASE"
LOCAL_PKG_VER=`cat $PKG_SCRIPTS/package-version.txt 2>/dev/null`
PKG_VER="$LOCAL_PKG_VER"
if [ -z "$PKG_VER" ]; then
    PKG_NAME="${PKG_BASE}"
else
    PKG_NAME="${PKG_BASE}-${PKG_VER}"
fi
PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'`
PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini" | sed "s/VERSION/$PKG_BASE_VER/"`

# Warning for experimental packages
if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" -a $INFO = 0 ]; then
    if [ $YES != 1 ]; then
        # We use /dev/tty here because our output may be redirected
        # to a logfile, or line-buffered.
        write_to_tty <<EOF
=========================== WARNING ===========================
You are about to download and install the experimental package
$PKG_NAME.  This probably won't work at all for you! There
is no guarantee that it will build correctly, or behave as
expected. Use at your own risk!
===============================================================
EOF
        if [ $? -ne 0 ]; then
            echo "Terminal not available for prompting.  Use 'sage -i -y $PKG_BASE'"
            echo "to install experimental packages in non-interactive mode."
            YES=-1
        fi
        if [ $YES != -1 ]; then
            read -p "Are you sure you want to continue [Y/n]? " answer < /dev/tty > /dev/tty 2>&1
        else
            answer=n
        fi
        case "$answer" in
            n*|N*) exit 1;;
        esac
        # Confirm the user's input.  (This gives important
        # feedback to the user when output is redirected to a logfile.)
        echo > /dev/tty "OK, installing $PKG_NAME now..."
    fi
fi

if [ $INFO -ne 0 ]; then
    exec sage-spkg-info $PKG_BASE
fi

# If we haven't found the package yet, we must download it
if [ ! -f "$PKG_SRC" ]; then
    if [ -n "$PKG_NAME_UPSTREAM" ]; then
        # This is the new-style package way of downloading the tarball
        if ! sage-download-file $SAGE_DOWNLOAD_FILE_OPTIONS "$PKG_NAME_UPSTREAM"; then
            error_msg "Error downloading $PKG_NAME_UPSTREAM"
            exit 1
        fi
        PKG_SRC="$SAGE_DISTFILES/$PKG_NAME_UPSTREAM"
    else
        echo >&2 "Error: Installing old-style SPKGs is no longer supported"
        exit 1
    fi
fi

# Do a final check that PKG_SRC is a file with an absolute path
cd /
if [ ! -f "$PKG_SRC" ]; then
    echo >&2 "Error: spkg file '$PKG_SRC' not found."
    echo >&2 "This shouldn't happen, it is a bug in the sage-spkg script."
    exit 1
fi

# Go back to SAGE_ROOT where we have less chance of completely messing
# up the system if we do something wrong.
cd "$SAGE_ROOT" || exit $?

# If SAGE_SPKG_COPY_UPSTREAM is set, it should be the name of a directory
# to which all upstream files are copied. This is used in sage-sdist.
if [ -n "$SAGE_SPKG_COPY_UPSTREAM" ]; then
    mkdir -p "$SAGE_SPKG_COPY_UPSTREAM" && cp -p "$PKG_SRC" "$SAGE_SPKG_COPY_UPSTREAM"
    if [ $? -ne 0 ]; then
        error_msg "Error copying upstream tarball to directory '$SAGE_SPKG_COPY_UPSTREAM'"
        exit 1
    fi
fi
if [ -n "$SAGE_INSTALL_FETCH_ONLY" ]; then
    exit 0
fi

##################################################################
# Setup directories
##################################################################

for dir in "$SAGE_SPKG_INST" "$SAGE_SPKG_SCRIPTS" "$SAGE_BUILD_DIR"; do
    mkdir -p "$dir"
    if [ $? -ne 0 ]; then
        error_msg "Error creating directory $dir"
        exit 1
    fi
done

# Trac #5852: check write permissions
if [ ! -w "$SAGE_BUILD_DIR" ]; then
    error_msg "Error: no write access to build directory $SAGE_BUILD_DIR"
    exit 1
fi
if [ ! -d "$SAGE_INST_LOCAL" ]; then
    # If you just unpack Sage and run "sage -p <pkg>" then local does not yet exist
    mkdir "$SAGE_INST_LOCAL"
fi
if [ ! -w "$SAGE_INST_LOCAL" ]; then
    error_msg "Error: no write access to installation directory $SAGE_INST_LOCAL"
    exit 1
fi

echo "$PKG_NAME"
echo "===================================================="

# Make absolutely sure that we are in the build directory before doing
# a scary "rm -rf" below.
cd "$SAGE_BUILD_DIR" || exit $?


if [ "x$SAGE_KEEP_BUILT_SPKGS" != "xyes" ]; then
    rm -rf "$PKG_NAME"
else
    if [ -e "$PKG_NAME" ]; then
        echo "Moving old directory $PKG_NAME to $SAGE_BUILD_DIR/old..."
        mkdir -p old
        if [ $? -ne 0 ]; then
            error_msg "Error creating directory $SAGE_BUILD_DIR/old"
            exit 1
        fi
        rm -rf old/"$PKG_NAME"
        mv "$PKG_NAME" old/
    fi
fi

if [ -e "$PKG_NAME" ]; then
    error_msg "Error (re)moving $PKG_NAME"
    exit 1
fi

##################################################################
# Extract the package
##################################################################

echo "Setting up build directory for $PKG_NAME"
cp -RLp "$PKG_SCRIPTS" "$PKG_NAME"
cd "$PKG_NAME" || exit $?

sage-uncompress-spkg -d src "$PKG_SRC"
if [ $? -ne 0 ]; then
    error_msg "Error: failed to extract $PKG_SRC"
    exit 1
fi

echo "Finished extraction"

cd src
if ! sage-apply-patches; then
    error_msg "Error applying patches"
    exit 1
fi
cd ..

##################################################################
# The package has been extracted, prepare for installation
##################################################################

# Rewrites the given bash pseudo-script with a boilerplate header that includes
# the shebang line and sourcing sage-env.  Make sure the name of the script is
# passed in as an absolute path.
write_script_wrapper() {
    local script="$1"
    local script_dir="$2"

    trap "echo >&2 Error: Unexpected error writing wrapper script for $script; exit \$_" ERR

    if head -1 "$script.in" | grep '^#!.*$' >/dev/null; then
        echo >&2 "Error: ${script##*/} should not contain a shebang line; it will be prepended automatically."
        exit 1
    fi

    local tmpscript="$(dirname "$script")/.tmp-${script##*/}"

    cat > "$tmpscript" <<__EOF__
#!/usr/bin/env bash

export SAGE_ROOT="$SAGE_ROOT"
export SAGE_SRC="$SAGE_SRC"
export SAGE_PKG_DIR="$script_dir"
export SAGE_SPKG_SCRIPTS="$SAGE_SPKG_SCRIPTS"
export SAGE_SPKG_WHEELS="$SAGE_SPKG_WHEELS"

export PKG_NAME="$PKG_NAME"
export PKG_BASE="$PKG_BASE"
export PKG_VER="$PKG_VER"

for lib in "\$SAGE_ROOT/build/bin/sage-dist-helpers" "\$SAGE_SRC/bin/sage-src-env-config" "\$SAGE_SRC/bin/sage-env-config" "\$SAGE_SRC/bin/sage-env" "\$SAGE_ROOT/build/bin/sage-build-env-config" "\$SAGE_ROOT/build/bin/sage-build-env"; do
    source "\$lib"
    if [ \$? -ne 0 ]; then
        echo >&2 "Error: failed to source \$lib"
        echo >&2 "Is \$SAGE_ROOT the correct SAGE_ROOT?"
        exit 1
    fi
done

export SAGE_INST_LOCAL="$SAGE_INST_LOCAL"

sdh_guard
if [ \$? -ne 0 ]; then
    echo >&2 "Error: sdh_guard not found; Sage environment was not set up properly"
    exit 1
fi

cd "\$SAGE_PKG_DIR"
if [ \$? -ne 0 ]; then
    echo >&2 "Error: could not cd to the package build directory \$SAGE_PKG_DIR"
    exit 1
fi

__EOF__

    cat "$script.in" >> "$tmpscript"
    mv "$tmpscript" "$script"
    chmod +x "$script"

    trap - ERR
}


INSTALLED_SCRIPTS="prerm piprm postrm"
WRAPPED_SCRIPTS="build install check preinst postinst $INSTALLED_SCRIPTS"

# Prepare script for uninstallation of packages that use sdh_pip_install
# or sdh_store_and_pip_install_wheel.
echo 'sdh_pip_uninstall -r $SAGE_SPKG_SCRIPTS/$PKG_BASE/spkg-piprm-requirements.txt' > spkg-piprm.in

for script in $WRAPPED_SCRIPTS; do
    # 'Installed' scripts are not run immediately out of the package build
    # directory, and may be run later, so set their root directory to
    # $SAGE_ROOT
    if echo "$INSTALLED_SCRIPTS" | grep -w "$script" > /dev/null; then
        script_dir="$SAGE_ROOT"
    else
        script_dir="$(pwd)"
    fi

    script="spkg-$script"

    if [ -f "$script.in" ]; then
            write_script_wrapper "$(pwd)/$script" "$script_dir"
    fi
done


# When there is no spkg-install, assume the "spkg" is a tarball not
# specifically made for Sage.  Since we want it to be as easy as
# possible to install such a package, we "guess" spkg-install.
if [ ! -f spkg-install ]; then
    echo '#!/usr/bin/env bash' > spkg-install
    if [ -x configure ]; then
        echo './configure --prefix="$SAGE_INST_LOCAL" && make && $SAGE_SUDO make install' >> spkg-install
    elif [ -f setup.py ]; then
        echo 'python setup.py install' >> spkg-install
    else
        echo >&2 "Error: There is no spkg-install script, no setup.py, and no configure"
        echo >&2 "script, so I do not know how to install $PKG_SRC."
        exit 1
    fi
    chmod +x spkg-install
fi

echo "****************************************************"
echo "Host system:"
uname -a
echo "****************************************************"
echo "C compiler: $CC"
echo "C compiler version:"
$CC -v
echo "****************************************************"

##################################################################
# Poison the proxy variable to forbid downloads in spkg-install
##################################################################
export http_proxy=http://192.0.2.0:5187/
export https_proxy=$http_proxy
export ftp_proxy=$http_proxy
export rsync_proxy=$http_proxy

##################################################################
# We need to run sage-rebase.sh for each package installed, but it
# can be dangerous to do this while other packages are installing
# so we need to use a lock to manage when rebase is allowed to
# run.  Because of this, if multiple sage-spkg runs are waiting on
# the rebase lock, we can end up with multiple consecutive rebase
# calls that are redundant, but I don't see an obvious way around
# that.  This also unfortunately slows down parallel builds since
# all packages will eventually need to wait for this lock, but
# again there's no simple way around that.
##################################################################

if [ "$UNAME" = "CYGWIN" ]; then
    # This is a global lock - so we use SAGE_LOCAL, not SAGE_INST_LOCAL.
    if [ ! -d "$SAGE_LOCAL/var/lock" ]; then
        mkdir -p "$SAGE_LOCAL/var/lock"
    fi
    exec 200>"$SAGE_LOCAL/var/lock/rebase.lock"
    sage-flock -s $lock_type 200
fi

##################################################################
# Actually install
##################################################################

# Set the $SAGE_DESTDIR variable to be passed to the spkg-install
# script (the script itself could set this, but better to standardize
# this in one place)
export SAGE_DESTDIR="${SAGE_BUILD_DIR}/${PKG_NAME}/inst"

# The actual prefix where the installation will be staged. This is the
# directory that you need to work in if you want to change the staged
# installation tree (before final installation to $SAGE_INST_LOCAL) at the
# end of spkg-install.
export SAGE_DESTDIR_LOCAL="${SAGE_DESTDIR}${SAGE_INST_LOCAL}"

# First uninstall the previous version of this package, if any
if [ "$KEEP_EXISTING" != "yes" ]; then
    sage-spkg-uninstall "$PKG_BASE"
fi

# To work around #26996: Create lib and set a symlink so that writes into lib64/ end up in lib/
(mkdir -p "$SAGE_DESTDIR_LOCAL/lib" && cd "$SAGE_DESTDIR_LOCAL" && ln -sf lib lib64)

# Run the pre-install script, if any
if [ -f spkg-preinst ]; then
    echo "Running pre-install script for $PKG_NAME."
    time $SAGE_SUDO ./spkg-preinst
    if [ $? -ne 0 ]; then
        error_msg "Error running the preinst script for $PKG_NAME."
        exit 1
    fi
fi

if [ -f spkg-build ]; then
    # Package has both spkg-build and spkg-install; execute the latter with SAGE_SUDO
    time ./spkg-build
    if [ $? -ne 0 ]; then
        error_msg "Error building package $PKG_NAME" "make"
        exit 1
    fi
    time $SAGE_SUDO ./spkg-install
    if [ $? -ne 0 ]; then
        error_msg "Error installing package $PKG_NAME" "make"
        exit 1
    fi
else
    # Package only has spkg-install
    time ./spkg-install
    if [ $? -ne 0 ]; then
        error_msg "Error installing package $PKG_NAME" "make"
        exit 1
    fi
fi

# To work around #26996: Remove the symlink set, or we get "cp: cannot overwrite directory"
rm -f "$SAGE_DESTDIR_LOCAL/lib64"

# All spkgs should eventually support this, but fall back on old behavior in
# case DESTDIR=$SAGE_DESTDIR installation was not used
echo "Copying package files from temporary location $SAGE_DESTDIR to $SAGE_INST_LOCAL"
if [ -d "$SAGE_DESTDIR" ]; then
    # Some `find` implementations will put superfluous slashes in the
    # output if we give them a directory name with a slash; so make sure
    # any trailing slash is removed; https://trac.sagemath.org/ticket/26013
    PREFIX="${SAGE_DESTDIR_LOCAL%/}"

    rm -f "$PREFIX"/lib/*.la
    if [ $? -ne 0 ]; then
        error_msg "Error deleting unnecessary libtool archive files"
        exit 1
    fi

    # Generate installed file manifest
    FILE_LIST="$(cd "$PREFIX" && find . -type f -o -type l | sed 's|^\./||' | sort)"

    # Copy files into $SAGE_INST_LOCAL
    $SAGE_SUDO cp -Rp "$PREFIX/." "$SAGE_INST_LOCAL"
    if [ $? -ne 0 ]; then
        error_msg "Error copying files for $PKG_NAME."
        exit 1
    fi

    # Remove the $SAGE_DESTDIR entirely once all files have been moved to their
    # final location.
    rm -rf "$SAGE_DESTDIR"
fi


# At this stage the path in $SAGE_DESTDIR no longer exists, so the variable
# should be unset
unset SAGE_DESTDIR
unset SAGE_DESTDIR_LOCAL


# Some spkg scripts, if they exist, should also be installed to
# $SAGE_SPKG_SCRIPTS; they are not included in the package's manifest, but are
# removed by sage-spkg-uninstall
INSTALLED_SCRIPTS_DEST="$SAGE_SPKG_SCRIPTS/$PKG_BASE"

if [ -f spkg-piprm-requirements.txt ]; then
    INSTALLED_SCRIPTS="$INSTALLED_SCRIPTS piprm-requirements.txt"
else
    # No packages to uninstall with pip, so remove the prepared uninstall script
    rm -f spkg-piprm spkg-piprm.in
fi

for script in $INSTALLED_SCRIPTS; do
    script="spkg-$script"

    if [ -f "$script" ]; then
        mkdir -p "$INSTALLED_SCRIPTS_DEST"
        if [ $? -ne 0 ]; then
            error_msg "Error creating the spkg scripts directory $INSTALLED_SCRIPTS_DEST."
            exit 1
        fi

        cp -a "$script" "$INSTALLED_SCRIPTS_DEST"
        if [ $? -ne 0 ]; then
            error_msg "Error copying the $script script to $INSTALLED_SCRIPTS_DEST."
            exit 1
        fi
    fi
done


# Run the post-install script, if any
if [ -f spkg-postinst ]; then
    echo "Running post-install script for $PKG_NAME."
    time $SAGE_SUDO ./spkg-postinst
    if [ $? -ne 0 ]; then
        error_msg "Error running the postinst script for $PKG_NAME."
        exit 1
    fi
fi

if [ "$UNAME" = "CYGWIN" ]; then
    # Drop our sage-spkg's shared lock, and try to call sage-rebase.sh
    # under an exclusive lock
    sage-flock -u 200

    # Rebase after installing each package--in case any packages load this
    # package at build time we need to ensure during the build that no binaries
    # have conflicting address spaces
    echo "Waiting for rebase lock"
    sage-flock -x "$SAGE_LOCAL/var/lock/rebase.lock" \
        sage-rebase.sh "$SAGE_LOCAL" 2>/dev/null
fi


# Note: spkg-check tests are run after the package has been copied into
# SAGE_INST_LOCAL.  It might make more sense to run the tests before, but the
# spkg-check scripts were written before use of DESTDIR installs, and so
# fail in many cases.  This might be good to change later.

if [ "$SAGE_CHECK" = "yes" -o "$SAGE_CHECK" = "warn" ]; then
    if [ -f spkg-check ]; then
        echo "Running the test suite for $PKG_NAME..."
        time ./spkg-check
        if [ $? -ne 0 ]; then
            TEST_SUITE_RESULT="failed"
            if [ "$SAGE_CHECK" = "warn" ]; then
                # The following warning message must be consistent with SAGE_ROOT/build/make/install (see trac:32781)
                error_msg "Warning: Failures testing package $PKG_NAME (ignored)" "make check"
            else
                error_msg "Error testing package $PKG_NAME" "make check"
                exit 1
            fi
        else
            TEST_SUITE_RESULT="passed"
            echo "Passed the test suite for $PKG_NAME."
        fi
    else
        echo "Package $PKG_NAME has no test suite."
        TEST_SUITE_RESULT="not available"
    fi
fi

# For each line in $FILE_LIST, enclose in double quotes:
NEW_LIST=""
for f in $FILE_LIST; do
         NEW_LIST+="\"$f\"
"
done
# Now remove the last line (it's blank), indent each line (skipping
# the first) and append a comma (skipping the last).
FILE_LIST="$(echo "$NEW_LIST" | sed '$d' | sed '2,$s/^/        /; $!s/$/,/')"

# Mark that the new package has been installed (and tested, if
# applicable).
PKG_NAME_INSTALLED="$SAGE_SPKG_INST/$PKG_NAME"
cat > "$PKG_NAME_INSTALLED" << __EOF__
{
    "package_name": "$PKG_BASE",
    "package_version": "$PKG_VER",
    "install_date": "$(date)",
    "system_uname": "$(uname -a)",
    "sage_version": "$(cat "${SAGE_ROOT}/VERSION.txt")",
    "test_result": "$TEST_SUITE_RESULT",
    "files": [
        $FILE_LIST
    ]
}
__EOF__


echo "Successfully installed $PKG_NAME"


##################################################################
# Delete the temporary build directory if required
##################################################################
if [ "x$SAGE_KEEP_BUILT_SPKGS" != "xyes" ]; then
    echo "Deleting temporary build directory"
    echo "$SAGE_BUILD_DIR/$PKG_NAME"
    # On Solaris, the current working directory cannot be deleted,
    # so we "cd" out of $SAGE_BUILD_DIR/$PKG_NAME. See #12637.
    cd "$SAGE_BUILD_DIR"
    rm -rf "$SAGE_BUILD_DIR/$PKG_NAME"
else
    echo "You can safely delete the temporary build directory"
    echo "$SAGE_BUILD_DIR/$PKG_NAME"
fi


echo "Finished installing $PKG_NAME"
