summaryrefslogtreecommitdiff
path: root/eclass
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
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')
-rw-r--r--eclass/eapi7-ver.eclass126
-rwxr-xr-xeclass/tests/eapi7-ver.sh112
-rwxr-xr-xeclass/tests/eapi7-ver_benchmark.sh34
3 files changed, 269 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
}
diff --git a/eclass/tests/eapi7-ver.sh b/eclass/tests/eapi7-ver.sh
index 8a96e4d29b1b..fd085a415b6e 100755
--- a/eclass/tests/eapi7-ver.sh
+++ b/eclass/tests/eapi7-ver.sh
@@ -17,6 +17,15 @@ teq() {
tend ${?} "returned: ${got}"
}
+teqr() {
+ local expected=$1; shift
+ tbegin "$* -> ${expected}"
+ "$@"
+ local ret=$?
+ [[ ${ret} -eq ${expected} ]]
+ tend $? "returned: ${ret}"
+}
+
txf() {
tbegin "XFAIL: ${*}"
local got=$("${@}" 2>&1)
@@ -63,3 +72,106 @@ teq 1.2.3 ver_rs 3-5 . 1.2.3
txf ver_cut foo 1.2.3
txf ver_rs -3 _ a1b2c3d4e5
txf ver_rs 5-3 _ a1b2c3d4e5
+
+# Tests from Portage's test_vercmp.py
+teqr 0 ver_test 6.0 -gt 5.0
+teqr 0 ver_test 5.0 -gt 5
+teqr 0 ver_test 1.0-r1 -gt 1.0-r0
+teqr 0 ver_test 999999999999999999 -gt 999999999999999998 # 18 digits
+teqr 0 ver_test 1.0.0 -gt 1.0
+teqr 0 ver_test 1.0.0 -gt 1.0b
+teqr 0 ver_test 1b -gt 1
+teqr 0 ver_test 1b_p1 -gt 1_p1
+teqr 0 ver_test 1.1b -gt 1.1
+teqr 0 ver_test 12.2.5 -gt 12.2b
+teqr 0 ver_test 4.0 -lt 5.0
+teqr 0 ver_test 5 -lt 5.0
+teqr 0 ver_test 1.0_pre2 -lt 1.0_p2
+teqr 0 ver_test 1.0_alpha2 -lt 1.0_p2
+teqr 0 ver_test 1.0_alpha1 -lt 1.0_beta1
+teqr 0 ver_test 1.0_beta3 -lt 1.0_rc3
+teqr 0 ver_test 1.001000000000000001 -lt 1.001000000000000002
+teqr 0 ver_test 1.00100000000 -lt 1.001000000000000001
+teqr 0 ver_test 999999999999999998 -lt 999999999999999999
+teqr 0 ver_test 1.01 -lt 1.1
+teqr 0 ver_test 1.0-r0 -lt 1.0-r1
+teqr 0 ver_test 1.0 -lt 1.0-r1
+teqr 0 ver_test 1.0 -lt 1.0.0
+teqr 0 ver_test 1.0b -lt 1.0.0
+teqr 0 ver_test 1_p1 -lt 1b_p1
+teqr 0 ver_test 1 -lt 1b
+teqr 0 ver_test 1.1 -lt 1.1b
+teqr 0 ver_test 12.2b -lt 12.2.5
+teqr 0 ver_test 4.0 -eq 4.0
+teqr 0 ver_test 1.0 -eq 1.0
+teqr 0 ver_test 1.0-r0 -eq 1.0
+teqr 0 ver_test 1.0 -eq 1.0-r0
+teqr 0 ver_test 1.0-r0 -eq 1.0-r0
+teqr 0 ver_test 1.0-r1 -eq 1.0-r1
+teqr 1 ver_test 1 -eq 2
+teqr 1 ver_test 1.0_alpha -eq 1.0_pre
+teqr 1 ver_test 1.0_beta -eq 1.0_alpha
+teqr 1 ver_test 1 -eq 0.0
+teqr 1 ver_test 1.0-r0 -eq 1.0-r1
+teqr 1 ver_test 1.0-r1 -eq 1.0-r0
+teqr 1 ver_test 1.0 -eq 1.0-r1
+teqr 1 ver_test 1.0-r1 -eq 1.0
+teqr 1 ver_test 1.0 -eq 1.0.0
+teqr 1 ver_test 1_p1 -eq 1b_p1
+teqr 1 ver_test 1b -eq 1
+teqr 1 ver_test 1.1b -eq 1.1
+teqr 1 ver_test 12.2b -eq 12.2
+
+# A subset of tests from Paludis
+teqr 0 ver_test 1.0_alpha -gt 1_alpha
+teqr 0 ver_test 1.0_alpha -gt 1
+teqr 0 ver_test 1.0_alpha -lt 1.0
+teqr 0 ver_test 1.2.0.0_alpha7-r4 -gt 1.2_alpha7-r4
+teqr 0 ver_test 0001 -eq 1
+teqr 0 ver_test 01 -eq 001
+teqr 0 ver_test 0001.1 -eq 1.1
+teqr 0 ver_test 01.01 -eq 1.01
+teqr 0 ver_test 1.010 -eq 1.01
+teqr 0 ver_test 1.00 -eq 1.0
+teqr 0 ver_test 1.0100 -eq 1.010
+teqr 0 ver_test 1-r00 -eq 1-r0
+
+# Additional tests
+teqr 0 ver_test 0_rc99 -lt 0
+teqr 0 ver_test 011 -eq 11
+teqr 0 ver_test 019 -eq 19
+teqr 0 ver_test 1.2 -eq 001.2
+teqr 0 ver_test 1.2 -gt 1.02
+teqr 0 ver_test 1.2a -lt 1.2b
+teqr 0 ver_test 1.2_pre1 -gt 1.2_pre1_beta2
+teqr 0 ver_test 1.2_pre1 -lt 1.2_pre1_p2
+teqr 0 ver_test 1.00 -lt 1.0.0
+teqr 0 ver_test 1.010 -eq 1.01
+teqr 0 ver_test 1.01 -lt 1.1
+teqr 0 ver_test 1.2_pre08-r09 -eq 1.2_pre8-r9
+teqr 0 ver_test 0 -lt 576460752303423488 # 2**59
+#teqr 0 ver_test 0 -lt 9223372036854775808 # 2**63 fails, integer rollover
+
+# Bad number or ordering of arguments
+txf ver_test 1
+txf ver_test 1 -lt 2 3
+txf ver_test -lt 1 2
+
+# Bad operators
+txf ver_test 1 "<" 2
+txf ver_test 1 lt 2
+txf ver_test 1 -foo 2
+
+# Malformed versions
+txf ver_test "" -ne 1
+txf ver_test 1. -ne 1
+txf ver_test 1ab -ne 1
+txf ver_test b -ne 1
+txf ver_test 1-r1_pre -ne 1
+txf ver_test 1-pre1 -ne 1
+txf ver_test 1_foo -ne 1
+txf ver_test 1_pre1.1 -ne 1
+txf ver_test 1-r1.0 -ne 1
+txf ver_test cvs.9999 -ne 9999
+
+texit
diff --git a/eclass/tests/eapi7-ver_benchmark.sh b/eclass/tests/eapi7-ver_benchmark.sh
index 1de26444c9b3..c46713713368 100755
--- a/eclass/tests/eapi7-ver_benchmark.sh
+++ b/eclass/tests/eapi7-ver_benchmark.sh
@@ -76,6 +76,38 @@ replacing_versionator() {
done >/dev/null
}
+comparing() {
+ local x
+ for x in {1..1000}; do
+ ver_test 1b_p1 -le 1_p1
+ ver_test 1.1b -le 1.1
+ ver_test 12.2.5 -le 12.2b
+ ver_test 4.0 -le 5.0
+ ver_test 5 -le 5.0
+ ver_test 1.0_pre2 -le 1.0_p2
+ ver_test 1.0_alpha2 -le 1.0_p2
+ ver_test 1.0_alpha1 -le 1.0_beta1
+ ver_test 1.0_beta3 -le 1.0_rc3
+ ver_test 1.001000000000000001 -le 1.001000000000000002
+ done
+}
+
+comparing_versionator() {
+ local x
+ for x in {1..100}; do
+ version_is_at_least 1b_p1 1_p1
+ version_is_at_least 1.1b 1.1
+ version_is_at_least 12.2.5 12.2b
+ version_is_at_least 4.0 5.0
+ version_is_at_least 5 5.0
+ version_is_at_least 1.0_pre2 1.0_p2
+ version_is_at_least 1.0_alpha2 1.0_p2
+ version_is_at_least 1.0_alpha1 1.0_beta1
+ version_is_at_least 1.0_beta3 1.0_rc3
+ version_is_at_least 1.001000000000000001 1.001000000000000002
+ done
+}
+
get_times() {
local factor=${1}; shift
echo "${*}"
@@ -111,3 +143,5 @@ get_times 1 cutting
get_times 10 cutting_versionator
get_times 1 replacing
get_times 10 replacing_versionator
+get_times 1 comparing
+get_times 10 comparing_versionator