diff --git a/src/usr/local/buildpack/tools/python.sh b/src/usr/local/buildpack/tools/python.sh deleted file mode 100644 index 013ef06f54..0000000000 --- a/src/usr/local/buildpack/tools/python.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash - -set -e - -check_semver "${TOOL_VERSION}" - - -if [[ ! "${MAJOR}" || ! "${MINOR}" || ! "${PATCH}" ]]; then - echo Invalid version: "${TOOL_VERSION}" - exit 1 -fi - -tool_path=$(find_versioned_tool_path) - -if [[ -z "${tool_path}" ]]; then - INSTALL_DIR=$(get_install_dir) - base_path=${INSTALL_DIR}/${TOOL_NAME} - tool_path=${base_path}/${TOOL_VERSION} - - mkdir -p "${base_path}" - - file=/tmp/python.tar.xz - - ARCH=$(uname -p) - PYTHON_URL="https://github.com/containerbase/python-prebuild/releases/download" - - version_codename=$(get_distro) - - curl -sSfLo ${file} "${PYTHON_URL}/${TOOL_VERSION}/python-${TOOL_VERSION}-${version_codename}-${ARCH}.tar.xz" || echo 'Ignore download error' - - if [[ -f ${file} ]]; then - echo 'Using prebuild python' - tar -C "${base_path}" -xf ${file} - rm ${file} - else - echo 'No prebuild python found' >&2 - exit 1 - fi - - fix_python_shebangs() { - # https://github.com/koalaman/shellcheck/wiki/SC2044 - while IFS= read -r -d '' file - do - case "$(head -1 "${file}")" in - "#!"*"/bin/python" ) - sed -i "1 s:.*:#\!${tool_path}\/bin\/python:" "${file}" - ;; - "#!"*"/bin/python${MAJOR}" ) - sed -i "1 s:.*:#\!${tool_path}\/bin\/python${MAJOR}:" "${file}" - ;; - "#!"*"/bin/python${MAJOR}.${MINOR}" ) - sed -i "1 s:.*:#\!${tool_path}\/bin\/python${MAJOR}.${MINOR}:" "${file}" - ;; - esac - done < <(find "${tool_path}/bin" -type f -exec grep -Iq . {} \; -print0) - } - - fix_python_shebangs - - PYTHONHOME=${tool_path} "${tool_path}/bin/pip" install --upgrade pip - - # clean cache https://pip.pypa.io/en/stable/reference/pip_cache/#pip-cache - PYTHONHOME=${tool_path} "${tool_path}/bin/pip" cache purge -fi - -reset_tool_env -# TODO: fix me, currently required for global pip -export_tool_path "${tool_path}/bin" -export_tool_path "${USER_HOME}/.local/bin" - -function python_shell_wrapper () { - local install_dir - local tool_target - local tool_wrapper - - install_dir=$(get_install_dir) - tool_wrapper="${install_dir}/bin/${1}" - tool_target="${tool_path}/bin/$1" - check_command "${tool_target}" - cat > "$tool_wrapper" <<- EOM -#!/bin/bash - -export PYTHONHOME=${tool_path} PATH=${tool_path}/bin:\$PATH - -${tool_target} "\$@" -EOM - chmod 775 "$tool_wrapper" -} - -python_shell_wrapper "${TOOL_NAME}" -python_shell_wrapper "${TOOL_NAME}${MAJOR}" -python_shell_wrapper "${TOOL_NAME}${MAJOR}.${MINOR}" -python_shell_wrapper pip -python_shell_wrapper "pip${MAJOR}" -python_shell_wrapper "pip${MAJOR}.${MINOR}" - -python --version -pip --version diff --git a/src/usr/local/buildpack/tools/v2/python.sh b/src/usr/local/buildpack/tools/v2/python.sh new file mode 100644 index 0000000000..88ec3bbee5 --- /dev/null +++ b/src/usr/local/buildpack/tools/v2/python.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# sets the correct shebang for python +fix_python_shebangs() { + # https://github.com/koalaman/shellcheck/wiki/SC2044 + while IFS= read -r -d '' file + do + case "$(head -1 "${file}")" in + "#!"*"/bin/python" ) + sed -i "1 s:.*:#\!${versioned_tool_path}\/bin\/python:" "${file}" + ;; + "#!"*"/bin/python${MAJOR}" ) + sed -i "1 s:.*:#\!${versioned_tool_path}\/bin\/python${MAJOR}:" "${file}" + ;; + "#!"*"/bin/python${MAJOR}.${MINOR}" ) + sed -i "1 s:.*:#\!${versioned_tool_path}\/bin\/python${MAJOR}.${MINOR}:" "${file}" + ;; + esac + done < <(find "${versioned_tool_path}/bin" -type f -exec grep -Iq . {} \; -print0) +} + +function install_tool () { + local versioned_tool_path + local file + local url + local arch + local version_codename + + versioned_tool_path=$(create_versioned_tool_path) + arch=$(uname -p) + url="https://github.com/containerbase/python-prebuild/releases/download" + version_codename=$(get_distro) + + create_folder "${versioned_tool_path}/bin" + + file=$(get_from_url "${url}/${TOOL_VERSION}/python-${TOOL_VERSION}-${version_codename}-${arch}.tar.xz") + + if [[ -f ${file} ]]; then + echo 'Using prebuild python' + tar -C "${versioned_tool_path}" --strip 1 -xf "${file}" + else + echo 'No prebuild python found' >&2 + exit 1 + fi + + fix_python_shebangs + + # install latest pip + PYTHONHOME=${versioned_tool_path} "${versioned_tool_path}/bin/pip" install --upgrade pip + + # clean cache https://pip.pypa.io/en/stable/reference/pip_cache/#pip-cache + PYTHONHOME=${versioned_tool_path} "${versioned_tool_path}/bin/pip" cache purge +} + +function link_tool () { + local versioned_tool_path + versioned_tool_path=$(find_versioned_tool_path) + + reset_tool_env + + # export python vars + export_tool_env PYTHONHOME "${versioned_tool_path}" + export_tool_path "${versioned_tool_path}/bin" + export_tool_path "${USER_HOME}/.local/bin" + + # TODO: fix me, currently required for global pip + shell_wrapper "${TOOL_NAME}" "${versioned_tool_path}/bin" + shell_wrapper "${TOOL_NAME}${MAJOR}" "${versioned_tool_path}/bin" + shell_wrapper "${TOOL_NAME}${MAJOR}.${MINOR}" "${versioned_tool_path}/bin" + shell_wrapper pip "${versioned_tool_path}/bin" + shell_wrapper "pip${MAJOR}" "${versioned_tool_path}/bin" + shell_wrapper "pip${MAJOR}.${MINOR}" "${versioned_tool_path}/bin" + + python --version + pip --version +} diff --git a/test/bash/tools/python.bats b/test/bash/tools/python.bats new file mode 100644 index 0000000000..7c2c9361b6 --- /dev/null +++ b/test/bash/tools/python.bats @@ -0,0 +1,171 @@ +setup_file () { + export TEST_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" >/dev/null 2>&1 && pwd)" + + # set up the cache + load "$TEST_DIR/../cache.sh" + export BUILDPACK_CACHE_DIR="$(create_temp_dir TEST_CACHE_DIR)" +} + +setup() { + load '../../../node_modules/bats-support/load' + load '../../../node_modules/bats-assert/load' + + TEST_ROOT_DIR=$(mktemp -u) + + load "$TEST_DIR/../../../src/usr/local/buildpack/util.sh" + + # load v2 overwrites + load "$TEST_DIR/../../../src/usr/local/buildpack/utils/v2/overrides.sh" + + # load test overwrites + load "$TEST_DIR/../util.sh" + + # set directories for test + ROOT_DIR="${TEST_ROOT_DIR}/root" + BIN_DIR="${TEST_ROOT_DIR}/bin" + + setup_directories + + # set default test user + TEST_ROOT_USER=1000 + + # load python + load "$TEST_DIR/../../../src/usr/local/buildpack/tools/v2/python.sh" + +} + +teardown() { + rm -rf "${TEST_ROOT_DIR}" +} + +teardown_file () { + clean_temp_dir $BUILDPACK_CACHE_DIR TEST_CACHE_DIR +} + +@test "python: check_tool_requirements" { + TOOL_NAME=python + + TOOL_VERSION=foobar \ + run check_tool_requirements + assert_failure + + TOOL_VERSION=1.2.3 \ + run check_tool_requirements + assert_success +} + +@test "python: check_tool_installed" { + local TOOL_NAME=python + local TOOL_VERSION + + # renovate: datasource=github-releases lookupName=containerbase/python-prebuild + TOOL_VERSION=3.10.5 + + run check_tool_installed + assert_failure + + # needed to export versions + check_tool_requirements + + + run install_tool + assert_success + + run check_tool_installed + assert_success +} + +@test "python: install_tool" { + local TOOL_NAME=python + local TOOL_VERSION + + # renovate: datasource=github-releases lookupName=containerbase/python-prebuild + TOOL_VERSION=3.10.5 + + # needed to export versions + check_tool_requirements + + run install_tool + assert_success + + local versioned_tool_path=$(find_versioned_tool_path) + + PATH="${versioned_tool_path}/bin" \ + run python --version + assert_success + assert_output --partial "${TOOL_VERSION}" + + # don't update + TOOL_VERSION=3.10.4 + + # needed to export versions + check_tool_requirements + + run install_tool + assert_success + + local versioned_tool_path=$(find_versioned_tool_path) + + PATH="${versioned_tool_path}/bin" \ + run python --version + assert_success + assert_output --partial "${TOOL_VERSION}" +} + +@test "python: link_tool" { + local TOOL_NAME=python + local TOOL_VERSION + local bin_path=$(get_bin_path) + + # renovate: datasource=github-releases lookupName=containerbase/python-prebuild + TOOL_VERSION=3.10.5 + + # needed to export versions + check_tool_requirements + + run install_tool + assert_success + + PATH="${bin_path}:$PATH" \ + run link_tool + assert_success + assert_output --partial "${TOOL_VERSION}" + + PATH="${bin_path}" \ + run python --version + assert_success + assert_output --partial "${TOOL_VERSION}" + + local versioned_tool_path=$(find_versioned_tool_path) + + PATH="${versioned_tool_path}/bin" \ + run python --version + assert_success + assert_output --partial "${TOOL_VERSION}" + + # don't update + TOOL_VERSION=3.10.4 + + # needed to export versions + check_tool_requirements + + run install_tool + assert_success + + PATH="${bin_path}:$PATH" \ + run link_tool + assert_success + assert_output --partial "${TOOL_VERSION}" + + local versioned_tool_path=$(find_versioned_tool_path) + + PATH="${versioned_tool_path}/bin" \ + run python --version + assert_success + assert_output --partial "${TOOL_VERSION}" + + PATH="${bin_path}" \ + run python --version + assert_success + assert_output --partial "${TOOL_VERSION}" +}