@@ -248,6 +248,48 @@ find_version_from_git_tags() {
248248 echo " ${variable_name} =${! variable_name} "
249249}
250250
251+ # Use semver logic to decrement a version number then look for the closest match
252+ find_prev_version_from_git_tags () {
253+ local variable_name=$1
254+ local current_version=${! variable_name}
255+ local repository=$2
256+ # Normally a "v" is used before the version number, but support alternate cases
257+ local prefix=${3:- " tags/v" }
258+ # Some repositories use "_" instead of "." for version number part separation, support that
259+ local separator=${4:- " ." }
260+ # Some tools release versions that omit the last digit (e.g. go)
261+ local last_part_optional=${5:- " false" }
262+ # Some repositories may have tags that include a suffix (e.g. actions/node-versions)
263+ local version_suffix_regex=$6
264+ # Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios.
265+ set +e
266+ major=" $( echo " ${current_version} " | grep -oE ' ^[0-9]+' || echo ' ' ) "
267+ minor=" $( echo " ${current_version} " | grep -oP ' ^[0-9]+\.\K[0-9]+' || echo ' ' ) "
268+ breakfix=" $( echo " ${current_version} " | grep -oP ' ^[0-9]+\.[0-9]+\.\K[0-9]+' 2> /dev/null || echo ' ' ) "
269+
270+ if [ " ${minor} " = " 0" ] && [ " ${breakfix} " = " 0" ]; then
271+ (( major= major- 1 ))
272+ declare -g ${variable_name} =" ${major} "
273+ # Look for latest version from previous major release
274+ find_version_from_git_tags " ${variable_name} " " ${repository} " " ${prefix} " " ${separator} " " ${last_part_optional} "
275+ # Handle situations like Go's odd version pattern where "0" releases omit the last part
276+ elif [ " ${breakfix} " = " " ] || [ " ${breakfix} " = " 0" ]; then
277+ (( minor= minor- 1 ))
278+ declare -g ${variable_name} =" ${major} .${minor} "
279+ # Look for latest version from previous minor release
280+ find_version_from_git_tags " ${variable_name} " " ${repository} " " ${prefix} " " ${separator} " " ${last_part_optional} "
281+ else
282+ (( breakfix= breakfix- 1 ))
283+ if [ " ${breakfix} " = " 0" ] && [ " ${last_part_optional} " = " true" ]; then
284+ declare -g ${variable_name} =" ${major} .${minor} "
285+ else
286+ declare -g ${variable_name} =" ${major} .${minor} .${breakfix} "
287+ fi
288+ fi
289+ set -e
290+ }
291+
292+
251293# Use Oryx to install something using a partial version match
252294oryx_install () {
253295 local platform=$1
@@ -368,6 +410,29 @@ install_openssl3() {
368410 rm -rf /tmp/openssl3
369411}
370412
413+ install_prev_vers_cpython () {
414+ VERSION=$1
415+ echo -e " \n(!) Failed to fetch the latest artifacts for cpython ${VERSION} ..."
416+ find_prev_version_from_git_tags VERSION https://github.com/python/cpython
417+ echo -e " \nAttempting to install ${VERSION} "
418+ install_cpython " ${VERSION} "
419+ }
420+
421+ install_cpython () {
422+ VERSION=$1
423+ INSTALL_PATH=" ${PYTHON_INSTALL_PATH} /${VERSION} "
424+ if [ -d " ${INSTALL_PATH} " ]; then
425+ echo " (!) Python version ${VERSION} already exists."
426+ exit 1
427+ fi
428+ mkdir -p /tmp/python-src ${INSTALL_PATH}
429+ cd /tmp/python-src
430+ cpython_tgz_filename=" Python-${VERSION} .tgz"
431+ cpython_tgz_url=" https://www.python.org/ftp/python/${VERSION} /${cpython_tgz_filename} "
432+ echo " Downloading ${cpython_tgz_filename} ..."
433+ curl -sSL -o " /tmp/python-src/${cpython_tgz_filename} " " ${cpython_tgz_url} "
434+ }
435+
371436install_from_source () {
372437 VERSION=$1
373438 echo " (*) Building Python ${VERSION} from source..."
@@ -378,13 +443,6 @@ install_from_source() {
378443 # Find version using soft match
379444 find_version_from_git_tags VERSION " https://github.com/python/cpython"
380445
381- INSTALL_PATH=" ${PYTHON_INSTALL_PATH} /${VERSION} "
382-
383- if [ -d " ${INSTALL_PATH} " ]; then
384- echo " (!) Python version ${VERSION} already exists."
385- exit 1
386- fi
387-
388446 # Some platforms/os versions need modern versions of openssl installed
389447 # via common package repositories, for now rhel-7 family, use case statement to
390448 # make it easy to expand
@@ -396,23 +454,21 @@ install_from_source() {
396454 ;;
397455 esac
398456
399- # Download tgz of source
400- mkdir -p /tmp/python-src ${INSTALL_PATH}
401- cd /tmp/python-src
402- local tgz_filename=" Python-${VERSION} .tgz"
403- local tgz_url=" https://www.python.org/ftp/python/${VERSION} /${tgz_filename} "
404- echo " Downloading ${tgz_filename} ..."
405- curl -sSL -o " /tmp/python-src/${tgz_filename} " " ${tgz_url} "
406-
457+ install_cpython " ${VERSION} "
458+ if [ -f " /tmp/python-src/${cpython_tgz_filename} " ]; then
459+ if grep -q " 404 Not Found" " /tmp/python-src/${cpython_tgz_filename} " ; then
460+ install_prev_vers_cpython " ${VERSION} "
461+ fi
462+ fi ;
407463 # Verify signature
408464 if [[ ${VERSION_CODENAME} = " centos7" ]] || [[ ${VERSION_CODENAME} = " rhel7" ]]; then
409465 receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
410466 else
411467 receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
412468 fi
413- echo " Downloading ${tgz_filename } .asc..."
414- curl -sSL -o " /tmp/python-src/${tgz_filename } .asc" " ${tgz_url } .asc"
415- gpg --verify " ${tgz_filename } .asc"
469+ echo " Downloading ${cpython_tgz_filename } .asc..."
470+ curl -sSL -o " /tmp/python-src/${cpython_tgz_filename } .asc" " ${cpython_tgz_url } .asc"
471+ gpg --verify " ${cpython_tgz_filename } .asc"
416472
417473 # Update min protocol for testing only - https://bugs.python.org/issue41561
418474 if [ -f /etc/pki/tls/openssl.cnf ]; then
@@ -424,7 +480,7 @@ install_from_source() {
424480 export OPENSSL_CONF=/tmp/python-src/openssl.cnf
425481
426482 # Untar and build
427- tar -xzf " /tmp/python-src/${tgz_filename } " -C " /tmp/python-src" --strip-components=1
483+ tar -xzf " /tmp/python-src/${cpython_tgz_filename } " -C " /tmp/python-src" --strip-components=1
428484 local config_args=" "
429485 if [ " ${OPTIMIZE_BUILD_FROM_SOURCE} " = " true" ]; then
430486 config_args=" ${config_args} --enable-optimizations"
0 commit comments