#!/usr/bin/env bash # Summary: Print the latest installed or known version with the given prefix # Usage: pyenv latest [-k|--known] [-q|--quiet] # # -k/--known Select from all known versions instead of installed # -q/--quiet Do not print an error message on resolution failure set -e [ -n "$PYENV_DEBUG" ] && set -x while [[ $# -gt 0 ]] do case "$1" in -k|--known) FROM_KNOWN=1 shift ;; -q|--quiet) QUIET=1 shift ;; *) break ;; esac done prefix=$1 exitcode=0 IFS=$'\n' if [[ -z $FROM_KNOWN ]]; then DEFINITION_CANDIDATES=( $(pyenv-versions --bare --skip-envs) ) else DEFINITION_CANDIDATES=( $(python-build --definitions ) ) fi if printf '%s\n' "${DEFINITION_CANDIDATES[@]}" 2>/dev/null | grep -qxFe "$prefix"; then echo "$prefix" exit $exitcode; fi # 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")" # FIXME: more reliable and readable would probably be to loop over them and transform in pure Bash DEFINITION_CANDIDATES=(\ $(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \ grep -Ee "^$prefix_re[-.]" || true)) DEFINITION_CANDIDATES=(\ $(printf '%s\n' "${DEFINITION_CANDIDATES[@]}" | \ sed -E -e '/-dev$/d' -e '/-src$/d' -e '/-latest$/d' -e '/(a|b|rc)[0-9]+$/d' -e '/[0-9]+t$/d')); # 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 if [[ -z $QUIET ]]; then echo "pyenv: no $([[ -z $FROM_KNOWN ]] && echo installed || echo known) versions match the prefix \`$prefix'" >&2 fi exitcode=1 fi exit $exitcode