From 78a12725a409436d479c2af260d6e49dc97eaa87 Mon Sep 17 00:00:00 2001 From: Marc Culler Date: Sat, 9 Jan 2021 12:14:00 -0600 Subject: [PATCH 1/2] Modify relocate-once.py to make Sage relocatable and add a patch containing changes to Sage that are needed to make this work. --- binary_pkg/templates/relocate-once.py | 80 +++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/binary_pkg/templates/relocate-once.py b/binary_pkg/templates/relocate-once.py index 0963a64..dbda7c2 100644 --- a/binary_pkg/templates/relocate-once.py +++ b/binary_pkg/templates/relocate-once.py @@ -1,10 +1,12 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Rewrite Paths -This script can be used exactly once to move the directory to a -different location. +This script replaces incidences of the root path installed by buildbot with the +path to a symlink which points to the root of this installation. The installation +is identified by a uuid created in this script, which runs only once because it +deletes itself upon successful completion. """ from __future__ import (absolute_import, division, print_function, @@ -13,11 +15,13 @@ import os import getopt import sys +import uuid +buildbot_path = "{{search_string}}" def usage(): - print("relocate-once.py -d ") - + print("relocate-once.py -d") + try: opts, args = getopt.getopt(sys.argv[1:], "hd:", ["help", "destination="]) @@ -25,9 +29,9 @@ def usage(): usage() sys.exit(2) - -ROOT_PATH = DESTINATION = os.path.abspath(os.path.dirname(__file__)) - +ROOT_PATH = os.path.abspath(os.path.dirname(__file__)) +DESTINATION = "" + for opt, arg in opts: if opt in ('-h', '--help'): usage() @@ -38,14 +42,60 @@ def usage(): {% include 'patch.py' %} +if not DESTINATION: + print(""" +This appears to be a brand new Sage installation. Some configuration is needed +before it can be used. +""") + # Generate an identifier for this Sage installation. + install_uuid = uuid.uuid4().hex + if os.geteuid() == 0: + # Always make the installation public if Sage is being installed by root. + DESTINATION = '/var/tmp/sage-%s'%install_uuid + else: + print(""" +Normally Sage is installed for use by all users. In that case an administrator +password is needed to complete the configuration process. If you are not an +administrator for this system you may install a private version of Sage. +""") + answer = None + print("Would you like to create a private Sage installation?") + try: + while answer not in ("yes", "no"): + answer = input("Please answer yes or no (or ^C to exit): ") + except KeyboardInterrupt: + sys.exit(3) + if answer == "yes": + print("Creating a private Sage installation for %s."%os.environ["USER"]) + home = os.getenv("HOME") + if not home or not os.path.exists(home): + print("No home directory! Private installation is not possible.") + sys.exit(1) + dot_sage = os.path.join(home, '.sage') + if not os.path.exists(dot_sage): + os.mkdir(dot_sage, mode=0o700) + locations = os.path.join(home, '.sage', 'locations') + os.mkdir(locations, mode=0o755) + DESTINATION = os.path.join(locations, install_uuid) + else: + DESTINATION = '/var/tmp/sage-%s'%install_uuid + # Save the installation-specific symlink in a bash script which + # can be sourced by the sage startup script. + script_path = os.path.join(ROOT_PATH, "runpath.sh") + with open(script_path, "w") as script: + script.write('SAGE_SYMLINK="%s"\n'%DESTINATION) + os.chmod(script_path, 0o755) + # Create the symlink. + os.symlink(ROOT_PATH, DESTINATION) + print(""" -Rewriting paths for your new installation directory -=================================================== +Configuring your new Sage installation +====================================== This might take a few minutes but only has to be done once. """) - -p = SearchAndReplace(ROOT_PATH, '{{search_string}}', DESTINATION) + +p = SearchAndReplace(ROOT_PATH, buildbot_path, DESTINATION) {% for filename, patches in patches.items() %} {% if isinstance(patches, SearchReplacePatch) %} @@ -60,3 +110,9 @@ def usage(): {% endfor %} os.remove(__file__) + +# If we are being run as root, exit with status 2 as a signal to the sage +# script that it should exit, to avoid messing up the permissions on the +# user's .sage directory. +if os.geteuid() == 0: + sys.exit(2) From eab5d5c6fec662a0c4fb2fb57d8423ee0e85091f Mon Sep 17 00:00:00 2001 From: Marc Culler Date: Sat, 9 Jan 2021 12:15:07 -0600 Subject: [PATCH 2/2] Actually add the patch. --- relocate-sage.patch | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 relocate-sage.patch diff --git a/relocate-sage.patch b/relocate-sage.patch new file mode 100644 index 0000000..a2c447a --- /dev/null +++ b/relocate-sage.patch @@ -0,0 +1,75 @@ +diff --git a/sage b/sage +index 3fad670c83..871c02cca7 100755 +--- a/sage ++++ b/sage +@@ -124,16 +124,46 @@ fi + + export SAGE_ROOT + +-# If this is a freshly-unpacked binary tarball then run the installer ++# If this is a freshly-unpacked binary tarball then run the installer. ++# For multi-user installations this must be done by a superuser, since ++# it will create the symlink for this Sage installation. + # Note: relocate-once.py deletes itself upon successful completion + if [ -x "$SAGE_ROOT/relocate-once.py" ]; then + "$SAGE_ROOT/relocate-once.py" ++ if [ $? -eq 3 ]; then ++ echo >&2 "\nAborted." ++ exit 1 ++ fi ++ if [ $? -eq 2 ]; then ++ echo >&2 "You may now restart sage as a normal user." ++ exit 0 ++ fi + if [ $? -ne 0 ]; then + echo >&2 "Error running the script 'relocate-once.py'." + exit 1 + fi + fi + ++# Check that the installation-specific symlink points to this sage ++# root directory and reset it if necessessary. If the symlink is ++# in /var/tmp then it must be owned by root, so we use sudo ++# to reset it. ++. "$SAGE_ROOT"/runpath.sh ++OLD_ROOT=`readlink $SAGE_SYMLINK` ++if [ "$SAGE_ROOT" != "$OLD_ROOT" ]; then ++ echo "This sage installation has been moved!" ++ echo old location: $OLD_ROOT ++ echo new location: $SAGE_ROOT ++ echo "Reconfiguring Sage for its new home ..." ++ if [ "$(dirname "$SAGE_SYMLINK")" == "/var/tmp" ]; then ++ sudo -p "Please enter your admin password: " rm -f $SAGE_SYMLINK ++ sudo ln -s "$SAGE_ROOT" "$SAGE_SYMLINK" ++ else ++ rm -f $SAGE_SYMLINK ++ ln -s "$SAGE_ROOT" "$SAGE_SYMLINK" ++ fi ++fi ++ + # Run the actual Sage script + if [ -x "$SAGE_ROOT/src/bin/sage" ]; then + exec "$SAGE_ROOT/src/bin/sage" "$@" +diff --git a/src/bin/sage-env b/src/bin/sage-env +index 1f02564f5c..6ac935ce25 100644 +--- a/src/bin/sage-env ++++ b/src/bin/sage-env +@@ -138,12 +138,14 @@ NEW_SAGE_ROOT=`cd "$NEW_SAGE_ROOT" && pwd -P` + + # Warn if NEW_SAGE_ROOT does not equal the old SAGE_ROOT + if [ "$SAGE_ROOT" != "$NEW_SAGE_ROOT" -a -n "$SAGE_ROOT" ]; then +- echo >&2 "Warning: overwriting SAGE_ROOT environment variable:" +- echo >&2 "Old SAGE_ROOT=$SAGE_ROOT" +- echo >&2 "New SAGE_ROOT=$NEW_SAGE_ROOT" ++ # But don't warn if we are just dereferencing the symlink ++ if ! [[ -L "$SAGE_ROOT" ]]; then ++ echo >&2 "Warning: overwriting SAGE_ROOT environment variable:" ++ echo >&2 "Old SAGE_ROOT=$SAGE_ROOT" ++ echo >&2 "New SAGE_ROOT=$NEW_SAGE_ROOT" ++ fi + fi + +- + # Don't execute the commands more than once for the same version of + # sage-env. Check this after checking the validity of SAGE_ROOT, but + # before modifying its value.