From: "Ulrich Müller" <ulm@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] repo/gentoo:master commit in: eclass/, eclass/tests/
Date: Tue, 26 Sep 2017 18:46:33 +0000 (UTC) [thread overview]
Message-ID: <1506451586.8a8ce07898a3aabce36291d13ea8a313ebd32d79.ulm@gentoo> (raw)
commit: 8a8ce07898a3aabce36291d13ea8a313ebd32d79
Author: Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Wed Sep 20 19:28:22 2017 +0000
Commit: Ulrich Müller <ulm <AT> gentoo <DOT> org>
CommitDate: Tue Sep 26 18:46:26 2017 +0000
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8a8ce078
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
eclass/eapi7-ver.eclass | 126 +++++++++++++++++++++++++++++++++++-
eclass/tests/eapi7-ver.sh | 112 ++++++++++++++++++++++++++++++++
eclass/tests/eapi7-ver_benchmark.sh | 34 ++++++++++
3 files changed, 269 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
}
diff --git a/eclass/tests/eapi7-ver.sh b/eclass/tests/eapi7-ver.sh
index 8a96e4d29b1..fd085a415b6 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 1de26444c9b..c4671371336 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
next reply other threads:[~2017-09-26 18:46 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-26 18:46 Ulrich Müller [this message]
-- strict thread matches above, loose matches on Subject: below --
2024-12-15 9:47 [gentoo-commits] repo/gentoo:master commit in: eclass/, eclass/tests/ Sam James
2024-05-14 8:20 Florian Schmaus
2024-02-10 10:47 Michał Górny
2024-02-10 10:47 Michał Górny
2023-10-09 10:54 Florian Schmaus
2023-09-14 5:30 Michał Górny
2023-06-07 7:00 Ulrich Müller
2023-05-23 4:36 Michał Górny
2023-03-21 5:43 Michał Górny
2023-03-17 22:04 David Seifert
2023-02-12 19:05 Michał Górny
2022-12-24 20:16 Michał Górny
2022-10-19 11:53 Michał Górny
2022-10-10 20:52 Michał Górny
2022-09-27 20:28 Michał Górny
2022-09-27 20:28 Michał Górny
2022-09-27 20:28 Michał Górny
2022-05-09 20:33 Michał Górny
2022-04-02 16:29 Michał Górny
2022-01-09 8:09 Michał Górny
2021-08-17 1:41 Sam James
2021-06-01 17:27 Sergei Trofimovich
2020-05-28 11:41 Michał Górny
2020-03-27 23:54 Sergei Trofimovich
2020-03-20 22:33 Sergei Trofimovich
2020-01-26 22:47 Sergei Trofimovich
2019-12-30 12:59 Michał Górny
2019-12-30 12:59 Michał Górny
2019-10-19 21:20 Sergei Trofimovich
2019-06-23 8:53 Sergei Trofimovich
2018-08-15 7:31 Michał Górny
2017-08-25 13:53 Michał Górny
2016-12-18 13:47 Michał Górny
2016-06-26 15:36 Michał Górny
2016-05-29 9:23 Amadeusz Piotr Żołnowski
2016-05-22 22:06 Amadeusz Piotr Żołnowski
2016-01-08 5:14 Michał Górny
2015-11-11 10:27 Michał Górny
2015-11-11 10:27 Michał Górny
2015-11-11 10:27 Michał Górny
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1506451586.8a8ce07898a3aabce36291d13ea8a313ebd32d79.ulm@gentoo \
--to=ulm@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox