#!/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: see usage() below.
#
# 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 Issue #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.
Modes of operation (provide at most one):
-d, --download-only: only download the package
-b, --build-and-stage-only: build and install (stage) only,
do not run post-install or check
-p, --post-install-only: unload the staged installation
directory and run other post-installation steps only
-x, --check-only: exclusively run the test suite;
this may assume that:
* the package has been installed already and/or that
* the build directory has not been deleted
-e, --erase-build-directory-only: erase (delete) the
build directory only
--info: print information on the package only
--help: print this help only
Other options:
-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)
-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
-s: save (do not delete) the build directory,
even when the installation was successful
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
}
exit_with_error_msg()
{
error_msg "$@"
exit 1
}
# Handle -n, -t, -q options for recursive make
# See Issue #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
if [ $# -eq 0 ]; then
usage
exit 0
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 || exit_with_error_msg "Error setting environment variables by sourcing sage-env"
. sage-build-env-config
. sage-build-env || exit_with_error_msg "Error setting environment variables by sourcing sage-build-env"
# 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
##################################################################
# Parse options
INFO=0
YES=0
KEEP_EXISTING=0
INSTALL=1
POST_INSTALL=1
ERASE_ONLY=0
MODE_SWITCHES=
while true; do
case "$1" in
--info)
MODE_SWITCHES+=", $1"
INFO=1;;
--help)
usage
exit 0;;
-y)
YES=1;;
-n)
YES=-1;;
-d|--download-only)
MODE_SWITCHES+=", $1"
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;;
-b|--build-and-stage-only)
MODE_SWITCHES+=", $1"
POST_INSTALL=0; export SAGE_CHECK=no;;
-p|--post-install-only)
MODE_SWITCHES+=", $1"
INSTALL=0; export SAGE_CHECK=no;;
-x|--check-only)
MODE_SWITCHES+=", $1"
INSTALL=0; POST_INSTALL=0; export SAGE_CHECK=yes;;
-k|--keep-existing)
KEEP_EXISTING=yes;;
-e|--erase-build-directory-only)
MODE_SWITCHES+=", $1"
ERASE_ONLY=1;;
-o|--allow-upstream)
SAGE_DOWNLOAD_FILE_OPTIONS+=" --allow-upstream";;
-*)
echo >&2 "Error: unknown option '$1'"
exit 2;;
*) break;;
esac
shift
done
MODE_SWITCHES=${MODE_SWITCHES#, }
case "$MODE_SWITCHES" in
*,*)
echo >&2 "Error: at most one of the mode switches may be given, got $MODE_SWITCHES"
echo >&2
usage
exit 1
;;
esac
# 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"
export 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".
# VERSION, if provided, must match the version in build/pkgs.
PKG_VER="${PKG_NAME#${PKG_BASE}}"
export PKG_VER="${PKG_VER#-}"
eval $(sage-package properties --format=shell $PKG_BASE)
eval PKG_SCRIPTS=\$path_$PKG_BASE \
PKG_TYPE=\$type_$PKG_BASE \
PKG_SRC_TYPE=\$source_$PKG_BASE \
LOCAL_PKG_VER=\$version_with_patchlevel_$PKG_BASE
if [ -n "$PKG_VER" -a "$PKG_VER" != "$LOCAL_PKG_VER" ]; then
echo >&2 "Error: Selecting a different version of a package is no longer supported"
exit 1
fi
if [ -z "$PKG_VER" ]; then
export PKG_NAME="${PKG_BASE}"
else
export PKG_NAME="${PKG_BASE}-${PKG_VER}"
fi
# 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}"
INSTALLED_SCRIPTS_DEST="$SAGE_SPKG_SCRIPTS/$PKG_BASE"
INSTALLED_SCRIPTS="prerm piprm postrm check"
WRAPPED_SCRIPTS="build install preinst pipinst postinst $INSTALLED_SCRIPTS"
warning_for_experimental_packages() { ############################
case "$PKG_TYPE:$PKG_SRC_TYPE" in
experimental:normal|experimental:wheel)
if [ $YES != 1 ]; then
echo "Error: The package $PKG_NAME is marked as experimental."
echo "Use 'sage -i -y $PKG_BASE' to force installation of this package"
echo "or use the configure option --enable-experimental-packages"
exit 1
fi;;
esac
} ############################## warning_for_experimental_packages
ensure_pkg_src() { ###############################################
case "$PKG_SRC_TYPE" in
normal|wheel)
PKG_SRC=$(sage-package download $SAGE_DOWNLOAD_FILE_OPTIONS $PKG_BASE) || exit_with_error_msg "Error downloading tarball of $PKG_BASE"
# 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
;;
none)
echo >&2
echo >&2 "Note: $PKG_BASE is a dummy package that the Sage distribution uses"
echo >&2 "to provide information about equivalent system packages."
echo >&2 "It cannot be installed using the Sage distribution."
echo >&2 "Please install it manually, for example using the system packages"
echo >&2 "recommended at the end of a run of './configure'"
echo >&2 "See below for package-specific information."
echo >&2
sage-spkg-info $PKG_BASE
echo >&2
echo >&2 "Error: $PKG_BASE is a dummy package and "
echo >&2 "cannot be installed using the Sage distribution."
exit 1
;;
esac
} ################################################# ensure_pkg_src
setup_directories() { ############################################
for dir in "$SAGE_SPKG_INST" "$SAGE_SPKG_SCRIPTS" "$SAGE_BUILD_DIR"; do
mkdir -p "$dir" || exit_with_error_msg "Error creating directory $dir"
done
# Issue #5852: check write permissions
if [ ! -w "$SAGE_BUILD_DIR" ]; then
exit_with_error_msg "Error: no write access to build directory $SAGE_BUILD_DIR"
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
exit_with_error_msg "Error: no write access to installation directory $SAGE_INST_LOCAL"
fi
# 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 || exit_with_error_msg "Error creating directory $SAGE_BUILD_DIR/old"
rm -rf old/"$PKG_NAME"
mv "$PKG_NAME" old/
fi
fi
if [ -e "$PKG_NAME" ]; then
exit_with_error_msg "Error (re)moving $PKG_NAME"
fi
} ############################################## setup_directories
extract_the_package() { ##########################################
cd "$SAGE_BUILD_DIR" || exit $?
echo "Setting up build directory $SAGE_BUILD_DIR/$PKG_NAME"
case "$PKG_SRC_TYPE" in
script)
# Transplant the 'src' symlink, copy scripts.
mkdir -p "$PKG_NAME"
if [ -d "$PKG_SCRIPTS"/src ]; then
ln -s $(cd "$PKG_SCRIPTS"/src && pwd -P) "$PKG_NAME"/src
fi
for a in $WRAPPED_SCRIPTS; do
if [ -r "$PKG_SCRIPTS"/spkg-$a.in ]; then
cp "$PKG_SCRIPTS"/spkg-$a.in "$PKG_NAME"/
elif [ -x "$PKG_SCRIPTS"/spkg-$a ]; then
cp "$PKG_SCRIPTS"/spkg-$a "$PKG_NAME"/
fi
done
cd "$PKG_NAME" || exit $?
;;
normal|wheel)
# Copy whole directory, resolving symlinks
cp -RLp "$PKG_SCRIPTS" "$PKG_NAME"
cd "$PKG_NAME" || exit $?
case "$PKG_SRC" in
*.whl)
# (Platform-independent) wheel
# Do not extract, do not create a src directory,
# just copy to dist/ and create a simple install script.
mkdir -p dist
cp "$PKG_SRC" dist/
if [ ! -f spkg-install.in ]; then
echo "sdh_store_and_pip_install_wheel ." > spkg-install.in
fi
;;
*)
# Source tarball
sage-uncompress-spkg -d src "$PKG_SRC" || exit_with_error_msg "Error: failed to extract $PKG_SRC"
cd src
sage-apply-patches || exit_with_error_msg "Error applying patches"
cd ..
;;
esac
;;
*)
error_msg "Unhandled source type $PKG_SRC_TYPE"
;;
esac
if [ "$SAGE_KEEP_BUILT_SPKGS" = "yes" ]; then
touch .keep
fi
} ############################################ extract_the_package
# 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"
local fallback_script_dir="$3"
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
__EOF__
if [ -n "$fallback_script_dir" ]; then
cat >> "$tmpscript" <<__EOF__
cd "\$SAGE_PKG_DIR" 2>/dev/null || cd "$fallback_script_dir"
__EOF__
else
cat >> "$tmpscript" <<__EOF__
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__
fi
cat "$script.in" >> "$tmpscript"
mv "$tmpscript" "$script"
chmod +x "$script"
trap - ERR
}
# Prepare script for uninstallation of packages that use sdh_pip_install
# or sdh_store_and_pip_install_wheel.
touch spkg-piprm.in
# Prepare script for deferred installation of packages that use sdh_pip_install
# or sdh_store_and_pip_install_wheel.
touch spkg-pipinst.in
for script in $WRAPPED_SCRIPTS; do
# 'Installed' scripts are not run immediately out of the package build
# directory, and may be run later.
# For the installed *rm scripts, set their root directory to $SAGE_ROOT.
# For the installed check scripts, some need the temporary build directory,
# others are OK with $PKG_SCRIPTS. So try to run out of the temporary
# build directory but fall back to the latter.
case $script in
check) script_dir="$(pwd)"
fallback_script_dir="$PKG_SCRIPTS"
;;
*rm) script_dir="\$SAGE_ROOT"
fallback_script_dir=
;;
*) script_dir="$(pwd)"
fallback_script_dir=
;;
esac
script="spkg-$script"
if [ -f "$script.in" ]; then
write_script_wrapper "$(pwd)/$script" "$script_dir" "$fallback_script_dir"
fi
done
} ####################################### prepare_for_installation
actually_build_and_install() { ###################################
case "$PKG_SRC" in
*.whl)
# Silence is golden.
;;
*)
echo "Host system: $(uname -a)"
echo "C compiler: $CC$($CC -v 2>&1 | while read -r line; do echo -n ", $line"; done)"
;;
esac
# Poison the proxy variable to forbid downloads in spkg-install
# for normal/wheel standard packages
case "$PKG_TYPE:$PKG_SRC_TYPE" in
standard:normal|standard:wheel)
export http_proxy=http://192.0.2.0:5187/
export https_proxy=$http_proxy
export ftp_proxy=$http_proxy
export rsync_proxy=$http_proxy
;;
esac
# Make sage-logger show the full logs
unset SAGE_SILENT_BUILD
unset V
# First uninstall the previous version of this package, if any
if [ "$KEEP_EXISTING" != "yes" ]; then
sage-spkg-uninstall "$PKG_BASE" "$SAGE_INST_LOCAL"
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
sage-logger -P spkg-preinst "$SAGE_SUDO ./spkg-preinst" || exit_with_error_msg "Error running the preinst script for $PKG_NAME."
fi
if [ -f spkg-build ]; then
# Package has both spkg-build and spkg-install; execute the latter with SAGE_SUDO
sage-logger -P spkg-build "./spkg-build" || exit_with_error_msg "Error building package $PKG_NAME" "make"
sage-logger -P spkg-install "$SAGE_SUDO ./spkg-install" || exit_with_error_msg "Error installing package $PKG_NAME" "make"
else
# Package only has spkg-install
sage-logger -P spkg-install "./spkg-install" || exit_with_error_msg "Error installing package $PKG_NAME" "make"
fi
} ##################################### actually_build_and_install
unload_destdir() { ###############################################
# 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
if [ -d "$SAGE_DESTDIR" ]; then
echo "Moving package files from temporary location $SAGE_DESTDIR to $SAGE_INST_LOCAL"
# 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://github.com/sagemath/sage/issues/26013
PREFIX="${SAGE_DESTDIR_LOCAL%/}"
rm -f "$PREFIX"/lib/*.la || exit_with_error_msg "Error deleting unnecessary libtool archive files"
# 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" || exit_with_error_msg "Error moving files for $PKG_NAME."
# Remove the $SAGE_DESTDIR entirely once all files have been moved to their
# final location.
rm -rf "$SAGE_DESTDIR"
else
echo "The temporary location $SAGE_DESTDIR does not exist; has it been unloaded already?"
exit 1
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
} ################################################# unload_destdir
install_scripts() { ##############################################
# 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
if [ ! -f "$INSTALLED_SCRIPTS_DEST"/spkg-requirements.txt ]; then
# No packages to uninstall with pip, so remove the prepared uninstall script
# and the prepared deferred installation script
rm -f spkg-piprm spkg-piprm.in spkg-pipinst spkg-pipinst.in
fi
for script in $INSTALLED_SCRIPTS; do
script="spkg-$script"
if [ -f "$script" ]; then
mkdir -p "$INSTALLED_SCRIPTS_DEST" || exit_with_error_msg "Error creating the spkg scripts directory $INSTALLED_SCRIPTS_DEST."
cp -a "$script" "$INSTALLED_SCRIPTS_DEST" || exit_with_error_msg "Error copying the $script script to $INSTALLED_SCRIPTS_DEST."
fi
done
} ################################################ install_scripts
post_install() { #################################################
# Run the post-install script, if any
# But first complete the delayed installation of wheels.
if [ -f spkg-pipinst ]; then
sage-logger -P spkg-pipinst "$SAGE_SUDO ./spkg-pipinst" || exit_with_error_msg "Error running the pipinst script for $PKG_NAME."
fi
if [ -f spkg-postinst ]; then
sage-logger -P spkg-postinst "$SAGE_SUDO ./spkg-postinst" || exit_with_error_msg "Error running the postinst script for $PKG_NAME."
fi
} ################################################### post_install
run_test_suite() { ###############################################
# 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 ! cd "$SAGE_BUILD_DIR/$PKG_NAME" 2>/dev/null; then
cd "$PKG_SCRIPTS" || exit $?
fi
if [ -f "$INSTALLED_SCRIPTS_DEST"/spkg-check ]; then
echo "Running the test suite for $PKG_NAME..."
export PKG_BASE
sage-logger -P spkg-check "$INSTALLED_SCRIPTS_DEST"/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 #32781)
error_msg "Warning: Failures testing package $PKG_NAME (ignored)" "make check"
else
exit_with_error_msg "Error testing package $PKG_NAME" "make check"
fi
else
TEST_SUITE_RESULT="passed"
echo "Passed the test suite for $PKG_NAME."
fi
elif [ -f "$PKG_SCRIPTS"/spkg-check.in -o -f "$PKG_SCRIPTS"/spkg-check ]; then
echo "The test suite for $PKG_NAME cannot be run because the script"
echo "$INSTALLED_SCRIPTS_DEST/spkg-check"
echo "is missing. Install/re-install package $PKG_NAME to run the test suite."
exit 1
else
echo "Package $PKG_NAME has no test suite."
TEST_SUITE_RESULT="not available"
fi
} ################################################# run_test_suite
write_installation_record() { ####################################
# 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__
} ###################################### write_installation_record
delete_the_temporary_build_directory() { #########################
echo "Deleting build directory $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"
} ########################### delete_the_temporary_build_directory
delete_the_temporary_build_directory_if_required() { #############
if [ ! -e "$SAGE_BUILD_DIR/$PKG_NAME/.keep" ]; then
delete_the_temporary_build_directory
else
echo "You can safely delete the build directory $SAGE_BUILD_DIR/$PKG_NAME"
fi
} ############### delete_the_temporary_build_directory_if_required
##################################################################
# MAIN
##################################################################
if [ $INFO -ne 0 ]; then
exec sage-spkg-info $PKG_BASE
fi
if [ $ERASE_ONLY = 1 ]; then
delete_the_temporary_build_directory
exit 0
fi
if [ $INSTALL = 1 ]; then
warning_for_experimental_packages
ensure_pkg_src
fi
if [ -n "$SAGE_INSTALL_FETCH_ONLY" ]; then
exit 0
fi
if [ $INSTALL = 1 ]; then
setup_directories
extract_the_package
prepare_for_installation
actually_build_and_install
fi
if [ $POST_INSTALL = 1 ]; then
cd "$SAGE_BUILD_DIR/$PKG_NAME" || exit $?
unload_destdir
install_scripts
post_install
fi
if [ "$SAGE_CHECK" = "yes" -o "$SAGE_CHECK" = "warn" ]; then
run_test_suite
fi
if [ $POST_INSTALL = 1 ]; then
write_installation_record
delete_the_temporary_build_directory_if_required
echo "Finished installing $PKG_NAME"
fi