Last active
May 28, 2023 23:05
-
-
Save snydergd/abd38cdcb459944a5a0470185056890c to your computer and use it in GitHub Desktop.
Python downloader/installer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Summary: Installs/upgrades python installations on your machine. | |
# | |
# Prerequisites: | |
# - jq and curl to be installed and in a folder on the PATH environment variable | |
# - PLATFORM and STORAGE_FOLDER variables below to be set correctly (did not take time to automatically pick) | |
# | |
usage() { | |
echo "Usage: $0 [-v | --version <version prefix>] [-a | --additional-version] [-h | --help]" >&2; | |
echo " -v <version> -- What version to install (e.g., '3', '3.10', '3.10.0') - latest with prefix is installed" >&2; | |
echo " -a -- Don't replace current version - install additional" >&2; | |
echo " -u -- Upgrade if available -- or do nothing if already installed" >&2; | |
echo " -h -- Show this help and exit" >&2; | |
} | |
die() { | |
echo $* >&2; | |
exit 1; | |
} | |
# Substring to match in the download filename for this platform -- see download link values on the website to pick one | |
PLATFORM='embed-amd64'; | |
# Where you want the distributions to be stored | |
STORAGE_FOLDER='/c/repos/app'; | |
# www.python.org api documentation (more or less): https://github.com/python/pythondotorg/blob/main/downloads/api.py | |
RELEASE_INFO_URL="https://www.python.org/api/v2/downloads/release/"; | |
FILE_INFO_URL_BASE="https://www.python.org/api/v2/downloads/release_file/"; | |
DOWNLOAD_FOLDER="$STORAGE_FOLDER/python-current"; | |
# Defaults | |
VERSION_PREFIX=3; | |
ADDITIONAL=no; | |
UPGRADE=no; | |
while [ $# -gt 0 ]; do | |
case $1 in | |
-v | --version) | |
shift; | |
VERSION_PREFIX="$1"; | |
;; | |
-a | --additional-version) | |
ADDITIONAL=yes; | |
;; | |
-u | --upgrade) | |
UPGRADE=yes; | |
;; | |
-h | --help) | |
usage; | |
exit; | |
;; | |
*) | |
usage; | |
die "unrecognized option $1"; | |
;; | |
esac; | |
shift; | |
done; | |
if ! which jq >/dev/null 2>&1; then | |
echo "You must have jq installed and in a path in the PATH environment variable for this to work."; | |
fi; | |
echo -e "\nDetermining version information"; | |
VERSION_PREFIX_PATTERN="$(echo "$VERSION_PREFIX" | sed -e 's/[^.0-9]//g; s/\./\\\\./g')"; | |
# Sort by version (descending) then take the first (latest) one | |
JQ_PATTERN='def lpad(n): | |
tostring | | |
if n > length then | |
((n-length)*"0") + . | |
else | |
. | |
end; | |
[ | |
.[] | |
| select(.name | match(" '$VERSION_PREFIX_PATTERN'\\.\\d$"))] | |
| sort_by( | |
.name | |
| split(" ") | |
| .[1] | |
| split(".") | |
| map(select(test("\\d"))) | |
| map(tonumber | lpad(3)) | |
| join(".")) | |
| reverse | |
| .[0]'; | |
RELEASE_INFO_JSON="$(curl "$RELEASE_INFO_URL" | jq "$JQ_PATTERN" -r)"; | |
VERSION="$(echo "$RELEASE_INFO_JSON" | jq '.name | split(" ") | .[1]' -r)" | |
RELEASE_RESOURCE_URI="$(echo "$RELEASE_INFO_JSON" | jq '.resource_uri' -r)"; | |
RELEASE_NUMBER="$(basename "$RELEASE_RESOURCE_URI")"; | |
FILE_INFO_URL="${FILE_INFO_URL_BASE}?release=${RELEASE_NUMBER}"; | |
DOWNLOAD_URL=$(curl "$FILE_INFO_URL" | jq '.[].url | select(contains("'$PLATFORM'"))' -r); | |
if [ $ADDITIONAL = "yes" ]; then | |
DOWNLOAD_FOLDER="$STORAGE_FOLDER/python-$VERSION"; | |
if [ -e "$DOWNLOAD_FOLDER" ] && [ $UPGRADE != "yes" ]; then | |
die "Can't download additional version because folder already exists. Delete and run again: $DOWNLOAD_FOLDER"; | |
fi; | |
fi; | |
if [ $(echo "$DOWNLOAD_FOLDER" | tr '/' ' ' | wc -w) -lt 2 ]; then | |
die "Refusing to write to $DOWNLOAD_FOLDER because it has less than 2 slashes -- don't want to risk breaking root folder"; | |
fi; | |
if [ -e "$DOWNLOAD_FOLDER" ]; then | |
if [ -e "$DOWNLOAD_FOLDER/python" ] && [ "$("$DOWNLOAD_FOLDER/python" --version)" = "Python $VERSION" ]; then | |
echo "Version $VERSION already appears to be installed at $DOWNLOAD_FOLDER - doing nothing."; | |
exit; | |
fi; | |
rm -rf "$DOWNLOAD_FOLDER"; | |
fi; | |
echo -e "\nActually performing download/install of the software from $DOWNLOAD_URL"; | |
mkdir -p "$DOWNLOAD_FOLDER"; | |
cd "$DOWNLOAD_FOLDER"; | |
case "$DOWNLOAD_URL" in | |
*.zip) | |
curl "$DOWNLOAD_URL" -o "_archive.zip"; | |
unzip "_archive.zip"; | |
;; | |
*.tar.gz) | |
curl "$DOWNLOAD_URL" | tar -xzv; | |
;; | |
*) | |
die "Don't know how to handle file extension of download url: $DOWNLOAD_URL"; | |
;; | |
esac; | |
if echo "$DOWNLOAD_URL" | grep "embed" >/dev/null; then | |
echo -e "\nInstalling pip"; | |
PTH_FILE= | |
sed -i 's/^#//' "$DOWNLOAD_FOLDER/"python*._pth; | |
curl "https://bootstrap.pypa.io/get-pip.py" | "$DOWNLOAD_FOLDER/python" || die "Unable to install pip. See error for details."; | |
fi; | |
echo -e "\nVerifying installation"; | |
if [ "$("$DOWNLOAD_FOLDER/python" --version)" != "Python $VERSION" ]; then | |
die "Something seems to be wrong with the installation -- maybe wrong architecture? Check the platform parameter variable in the script and see any error output directly above this message to troubleshoot."; | |
fi; | |
echo -e "\nInstalled to $DOWNLOAD_FOLDER successfully! You can ues it from there explicitly or add it to your PATH environment variable to use."; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment