mirror of https://github.com/astral-sh/uv
100 lines
2.8 KiB
Bash
Executable File
100 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Download required Python versions and install to `bin`
|
|
# Uses prebuilt Python distributions from indygreg/python-build-standalone
|
|
#
|
|
# Requirements
|
|
#
|
|
# macOS
|
|
#
|
|
# brew install zstd coreutils
|
|
#
|
|
# Ubuntu
|
|
#
|
|
# apt install zstd
|
|
#
|
|
# Arch Linux
|
|
#
|
|
# pacman -S zstd
|
|
#
|
|
# Usage
|
|
#
|
|
# ./scripts/bootstrap/install
|
|
#
|
|
# The Python versions are installed from `.python_versions`.
|
|
# Python versions are linked in-order such that the _last_ defined version will be the default.
|
|
#
|
|
# Version metadata can be updated with `fetch-versions` which requires Python 3.12
|
|
|
|
set -eu pipefail
|
|
|
|
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
|
|
|
# Setup some file paths
|
|
this_dir=$(realpath "$(dirname "$0")")
|
|
root_dir=$(dirname "$(dirname "$this_dir")")
|
|
bin_dir="$root_dir/bin"
|
|
install_dir="$bin_dir/versions"
|
|
versions_file="$root_dir/.python-versions"
|
|
versions_metadata="$this_dir/versions.json"
|
|
|
|
# Determine system metadata
|
|
os=$(uname | tr '[:upper:]' '[:lower:]')
|
|
arch=$(arch)
|
|
interpreter='cpython'
|
|
|
|
# macOS is horrible
|
|
realpath="$(which grealpath || which realpath)"
|
|
|
|
# Read requested versions into an array
|
|
readarray -t versions < "$versions_file"
|
|
|
|
# Install each version
|
|
for version in "${versions[@]}"; do
|
|
key="$interpreter-$version-$os-$arch"
|
|
echo "Installing $key"
|
|
|
|
url=$(cat "$versions_metadata" | jq --arg key "$key" '.[$key] | .url' -r)
|
|
|
|
if [ "$url" == 'null' ]; then
|
|
echo "No matching download for $key"
|
|
exit 1
|
|
fi
|
|
|
|
filename=$(basename $url)
|
|
echo "Downloading $(urldecode $filename)"
|
|
curl -L --progress-bar -o $filename $url --output-dir "$this_dir"
|
|
|
|
expected_sha=$(cat "$versions_metadata" | jq --arg key "$key" '.[$key] | .sha256' -r)
|
|
if [ "$expected_sha" == 'null' ]; then
|
|
echo "WARNING: no checksum for $key"
|
|
else
|
|
echo -n "Verifying checksum..."
|
|
echo "$expected_sha $this_dir/$filename" | sha256sum -c --quiet
|
|
echo " OK"
|
|
fi
|
|
|
|
install_key="$install_dir/$interpreter@$version"
|
|
rm -rf "$install_key"
|
|
echo "Extracting to $($realpath --relative-to=$root_dir $install_key)"
|
|
mkdir -p "$install_key"
|
|
zstd -d "$this_dir/$filename" --stdout | tar -x -C "$install_key"
|
|
|
|
# Setup the installation
|
|
mv "$install_key/python/"* "$install_key"
|
|
link=$($realpath --relative-to=$bin_dir "$install_key/install/bin/python3")
|
|
minor=$(cat "$versions_metadata" | jq --arg key "$key" '.[$key] | .minor' -r)
|
|
|
|
# Link as all version tuples, later versions in the file will take precedence
|
|
ln -sf "./$link" "$bin_dir/python$version"
|
|
ln -sf "./$link" "$bin_dir/python3.$minor"
|
|
ln -sf "./$link" "$bin_dir/python3"
|
|
ln -sf "./$link" "$bin_dir/python"
|
|
echo "Installed as python$version"
|
|
|
|
# Cleanup
|
|
rmdir "$install_key/python/"
|
|
rm "$this_dir/$filename"
|
|
done
|
|
|
|
echo "Done!" |