summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Müller <ulm@gentoo.org>2017-09-20 21:28:22 +0200
committerUlrich Müller <ulm@gentoo.org>2017-09-26 20:46:26 +0200
commit8a8ce07898a3aabce36291d13ea8a313ebd32d79 (patch)
treebe9cf91621f34d4d44d327058fa6f81ee2ec752f /eclass/eapi7-ver.eclass
parentdev-lang/mercury: fix failing foreign-decl-line-number unit test due to GCC d... (diff)
downloadgentoo-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.eclass126
1 files changed, 123 insertions, 3 deletions
diff --git a/eclass/eapi7-ver.eclass b/eclass/eapi7-ver.eclass
index 6f8f0c0a1c3..1ad1cbe2edc 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
}