2022-10-29 20:38:40 -04:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
# Summary: Print the latest installed or known version with the given prefix
|
2024-07-20 15:06:13 -04:00
|
|
|
# Usage: pyenv latest [-k|--known] <prefix>
|
2022-10-29 20:38:40 -04:00
|
|
|
#
|
|
|
|
# -k/--known Select from all known versions instead of installed
|
2024-07-20 15:06:13 -04:00
|
|
|
# -b/--bypass (internal) On a resolution failure, do not print an error message
|
|
|
|
# but rather print the argument unchanged
|
|
|
|
# -f/--force (internal) Same as -b but also do not return a failure exit code
|
2022-10-29 20:38:40 -04:00
|
|
|
|
|
|
|
set -e
|
|
|
|
[ -n "$PYENV_DEBUG" ] && set -x
|
|
|
|
|
|
|
|
while [[ $# -gt 0 ]]
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-k|--known)
|
|
|
|
FROM_KNOWN=1
|
|
|
|
shift
|
|
|
|
;;
|
2024-07-20 15:06:13 -04:00
|
|
|
-b|--bypass)
|
|
|
|
BYPASS=1
|
|
|
|
shift
|
|
|
|
;;
|
|
|
|
-f|--force)
|
|
|
|
FORCE=1
|
|
|
|
BYPASS=1
|
2022-10-29 20:38:40 -04:00
|
|
|
shift
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
|
|
|
prefix=$1
|
|
|
|
exitcode=0
|
|
|
|
|
|
|
|
IFS=$'\n'
|
|
|
|
|
|
|
|
if [[ -z $FROM_KNOWN ]]; then
|
2023-02-02 10:14:42 -05:00
|
|
|
DEFINITION_CANDIDATES=( $(pyenv-versions --bare --skip-envs) )
|
2022-10-29 20:38:40 -04:00
|
|
|
else
|
|
|
|
DEFINITION_CANDIDATES=( $(python-build --definitions ) )
|
|
|
|
fi
|
2022-11-09 20:46:14 -05:00
|
|
|
|
2023-06-19 20:04:06 -04:00
|
|
|
if printf '%s\n' "${DEFINITION_CANDIDATES[@]}" 2>/dev/null | grep -qxFe "$prefix"; then
|
2022-11-09 20:46:14 -05:00
|
|
|
echo "$prefix"
|
|
|
|
exit $exitcode;
|
|
|
|
fi
|
|
|
|
|
2024-10-11 09:28:10 -04:00
|
|
|
suffix=""
|
|
|
|
if [[ $prefix =~ ^(.*[0-9])t$ ]]; then
|
|
|
|
suffix="t"
|
|
|
|
prefix="${BASH_REMATCH[1]}"
|
|
|
|
fi
|
|
|
|
|
2022-10-29 20:38:40 -04:00
|
|
|
# https://stackoverflow.com/questions/11856054/is-there-an-easy-way-to-pass-a-raw-string-to-grep/63483807#63483807
|
|
|
|
prefix_re="$(sed 's/[^\^]/[&]/g;s/[\^]/\\&/g' <<< "$prefix")"
|
2024-10-11 09:28:10 -04:00
|
|
|
suffix_re="$(sed 's/[^\^]/[&]/g;s/[\^]/\\&/g' <<< "$suffix")"
|
2022-10-29 20:38:40 -04:00
|
|
|
# FIXME: more reliable and readable would probably be to loop over them and transform in pure Bash
|
|
|
|
DEFINITION_CANDIDATES=(\
|
|
|
|
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \
|
2024-10-11 09:28:10 -04:00
|
|
|
grep -Ee "^$prefix_re[-.].*$suffix_re\$" || true))
|
2022-10-29 20:38:40 -04:00
|
|
|
|
|
|
|
DEFINITION_CANDIDATES=(\
|
|
|
|
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \
|
2024-10-11 09:28:10 -04:00
|
|
|
sed -E -e '/-dev$/d' -e '/-src$/d' -e '/-latest$/d' -e '/(a|b|rc)[0-9]+$/d' \
|
|
|
|
$(if [[ -z $suffix ]]; then echo "-e /[0-9]t\$/d"; fi)
|
|
|
|
));
|
2022-10-29 20:38:40 -04:00
|
|
|
|
|
|
|
# Compose a sorting key, followed by | and original value
|
|
|
|
DEFINITION_CANDIDATES=(\
|
|
|
|
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \
|
|
|
|
awk \
|
|
|
|
'{ if (match($0,"^[[:alnum:]]+-"))
|
|
|
|
{ print substr($0,0,RLENGTH-1) "." substr($0,RLENGTH+1) "..|" $0; }
|
|
|
|
else
|
|
|
|
{ print $0 "...|" $0; }
|
|
|
|
}'))
|
|
|
|
DEFINITION_CANDIDATES=(\
|
|
|
|
$(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" \
|
|
|
|
| sort -t. -k1,1r -k 2,2nr -k 3,3nr -k4,4nr \
|
|
|
|
| cut -f2 -d $'|' \
|
|
|
|
|| true))
|
|
|
|
DEFINITION="${DEFINITION_CANDIDATES[0]}"
|
|
|
|
|
|
|
|
if [[ -n "$DEFINITION" ]]; then
|
|
|
|
echo "$DEFINITION"
|
|
|
|
else
|
2024-07-20 15:06:13 -04:00
|
|
|
if [[ -z $BYPASS ]]; then
|
2022-10-29 20:38:40 -04:00
|
|
|
echo "pyenv: no $([[ -z $FROM_KNOWN ]] && echo installed || echo known) versions match the prefix \`$prefix'" >&2
|
2024-07-20 15:06:13 -04:00
|
|
|
else
|
|
|
|
echo "$prefix"
|
|
|
|
fi
|
|
|
|
if [[ -z $FORCE ]]; then
|
|
|
|
exitcode=1
|
2022-10-29 20:38:40 -04:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
exit $exitcode
|