public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
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


             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