diff options
author | Ulrich Müller <ulm@gentoo.org> | 2017-09-20 21:28:22 +0200 |
---|---|---|
committer | Ulrich Müller <ulm@gentoo.org> | 2017-09-26 20:46:26 +0200 |
commit | 8a8ce07898a3aabce36291d13ea8a313ebd32d79 (patch) | |
tree | be9cf91621f34d4d44d327058fa6f81ee2ec752f /eclass/eapi7-ver.eclass | |
parent | dev-lang/mercury: fix failing foreign-decl-line-number unit test due to GCC d... (diff) | |
download | gentoo-8a8ce07898a3aabce36291d13ea8a313ebd32d79.tar.gz gentoo-8a8ce07898a3aabce36291d13ea8a313ebd32d79.tar.bz2 gentoo-8a8ce07898a3aabce36291d13ea8a313ebd32d79.zip |
eapi7-ver.eclass: Initial implementation of ver_test().
This should strictly follow Algorithms 3.1 to 3.7 specified in PMS:
https://projects.gentoo.org/pms/6/pms.html#x1-310003.3
Diffstat (limited to 'eclass/eapi7-ver.eclass')
-rw-r--r-- | eclass/eapi7-ver.eclass | 126 |
1 files changed, 123 insertions, 3 deletions
diff --git a/eclass/eapi7-ver.eclass b/eclass/eapi7-ver.eclass index 6f8f0c0a1c37..1ad1cbe2edc2 100644 --- a/eclass/eapi7-ver.eclass +++ b/eclass/eapi7-ver.eclass @@ -16,8 +16,6 @@ # # https://bugs.gentoo.org/482170 # -# Note: version comparison function is not included currently. -# # @ROFF .SS # Version strings # @@ -185,5 +183,127 @@ ver_rs() { # revision parts), and the comparison is performed according to # the algorithm specified in the PMS. ver_test() { - die "${FUNCNAME}: not implemented" + local v1 v2 op i tail result + local -a v1comp v2comp + local match=( + "+([0-9])*(.+([0-9]))" # numeric components + "[a-z]" # letter component + "*(@(_alpha|_beta|_pre|_rc|_p)*([0-9]))" # suffixes + "-r+([0-9])" # revision + ) + + local LC_ALL=C shopt_save=$(shopt -p extglob) + shopt -s extglob + + if [[ $# -eq 2 ]]; then + v1=${PVR} + elif [[ $# -eq 3 ]]; then + v1=$1; shift + else + die "${FUNCNAME}: bad number of arguments" + fi + op=$1 + v2=$2 + + case ${op} in + -eq|-ne|-lt|-le|-gt|-ge) ;; + *) die "${FUNCNAME}: invalid operator: ${op}" ;; + esac + + # Test for both versions being valid, and split them into parts + for (( i=0; i<4; i++ )); do + tail=${v1##${match[i]}} + v1comp[i]=${v1%"${tail}"} + v1=${tail} + tail=${v2##${match[i]}} + v2comp[i]=${v2%"${tail}"} + v2=${tail} + done + # There must not be any remaining tail, and the numeric part + # must be non-empty. All other parts are optional. + [[ -z ${v1} && -z ${v2} && -n ${v1comp[0]} && -n ${v2comp[0]} ]] \ + || die "${FUNCNAME}: invalid version" + + # Compare numeric components (PMS algorithm 3.2) + _ver_cmp_num() { + local a=(${1//./ }) b=(${2//./ }) + local an=${#a[@]} bn=${#b[@]} + local i + # First component + [[ 10#${a[0]} -gt 10#${b[0]} ]] && return 2 + [[ 10#${a[0]} -lt 10#${b[0]} ]] && return 1 + for (( i=1; i<an && i<bn; i++ )); do + # Other components (PMS algorithm 3.3) + if [[ ${a[i]} == 0* || ${b[i]} == 0* ]]; then + local ap=${a[i]%%*(0)} bp=${b[i]%%*(0)} + [[ ${ap} > ${bp} ]] && return 2 + [[ ${ap} < ${bp} ]] && return 1 + else + [[ ${a[i]} -gt ${b[i]} ]] && return 2 + [[ ${a[i]} -lt ${b[i]} ]] && return 1 + fi + done + [[ ${an} -gt ${bn} ]] && return 2 + [[ ${an} -lt ${bn} ]] && return 1 + return 0 + } + + # Compare letter components (PMS algorithm 3.4) + _ver_cmp_let() { + local a=$1 b=$2 + [[ ${a} > ${b} ]] && return 2 + [[ ${a} < ${b} ]] && return 1 + return 0 + } + + # Compare suffixes (PMS algorithm 3.5) + _ver_cmp_suf() { + local a=(${1//_/ }) b=(${2//_/ }) + local an=${#a[@]} bn=${#b[@]} + local i + for (( i=0; i<an && i<bn; i++ )); do + # Compare each suffix (PMS algorithm 3.6) + if [[ ${a[i]%%*([0-9])} == "${b[i]%%*([0-9])}" ]]; then + [[ 10#${a[i]##*([a-z])} -gt 10#${b[i]##*([a-z])} ]] && return 2 + [[ 10#${a[i]##*([a-z])} -lt 10#${b[i]##*([a-z])} ]] && return 1 + else + # Check for p first + [[ ${a[i]} == p*([0-9]) ]] && return 2 + [[ ${b[i]} == p*([0-9]) ]] && return 1 + # Hack: Use that alpha < beta < pre < rc alphabetically + [[ ${a[i]} > ${b[i]} ]] && return 2 || return 1 + fi + done + if [[ ${an} -gt ${bn} ]]; then + [[ ${a[bn]} == p*([0-9]) ]] && return 2 || return 1 + elif [[ ${an} -lt ${bn} ]]; then + [[ ${b[an]} == p*([0-9]) ]] && return 1 || return 2 + fi + return 0 + } + + # Compare revision components (PMS algorithm 3.7) + _ver_cmp_rev() { + local a=${1#-r} b=${2#-r} + [[ 10#${a} -gt 10#${b} ]] && return 2 + [[ 10#${a} -lt 10#${b} ]] && return 1 + return 0 + } + + # Version comparison top-level logic (PMS algorithm 3.1) + _ver_cmp_num "${v1comp[0]}" "${v2comp[0]}" && + _ver_cmp_let "${v1comp[1]}" "${v2comp[1]}" && + _ver_cmp_suf "${v1comp[2]}" "${v2comp[2]}" && + _ver_cmp_rev "${v1comp[3]}" "${v2comp[3]}" + + case $? in + 0) result=0 ;; # a = b + 1) result=-1 ;; # a < b + 2) result=1 ;; # a > b + *) die "${FUNCNAME}: invalid return code: $?" ;; + esac + + ${shopt_save} + + test "${result}" "${op}" 0 } |