Gentoo Archives: gentoo-commits

From: "Ulrich Müller" <ulm@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: eclass/, eclass/tests/
Date: Tue, 26 Sep 2017 18:46:36
Message-Id: 1506451586.8a8ce07898a3aabce36291d13ea8a313ebd32d79.ulm@gentoo
1 commit: 8a8ce07898a3aabce36291d13ea8a313ebd32d79
2 Author: Ulrich Müller <ulm <AT> gentoo <DOT> org>
3 AuthorDate: Wed Sep 20 19:28:22 2017 +0000
4 Commit: Ulrich Müller <ulm <AT> gentoo <DOT> org>
5 CommitDate: Tue Sep 26 18:46:26 2017 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8a8ce078
7
8 eapi7-ver.eclass: Initial implementation of ver_test().
9
10 This should strictly follow Algorithms 3.1 to 3.7 specified in PMS:
11 https://projects.gentoo.org/pms/6/pms.html#x1-310003.3
12
13 eclass/eapi7-ver.eclass | 126 +++++++++++++++++++++++++++++++++++-
14 eclass/tests/eapi7-ver.sh | 112 ++++++++++++++++++++++++++++++++
15 eclass/tests/eapi7-ver_benchmark.sh | 34 ++++++++++
16 3 files changed, 269 insertions(+), 3 deletions(-)
17
18 diff --git a/eclass/eapi7-ver.eclass b/eclass/eapi7-ver.eclass
19 index 6f8f0c0a1c3..1ad1cbe2edc 100644
20 --- a/eclass/eapi7-ver.eclass
21 +++ b/eclass/eapi7-ver.eclass
22 @@ -16,8 +16,6 @@
23 #
24 # https://bugs.gentoo.org/482170
25 #
26 -# Note: version comparison function is not included currently.
27 -#
28 # @ROFF .SS
29 # Version strings
30 #
31 @@ -185,5 +183,127 @@ ver_rs() {
32 # revision parts), and the comparison is performed according to
33 # the algorithm specified in the PMS.
34 ver_test() {
35 - die "${FUNCNAME}: not implemented"
36 + local v1 v2 op i tail result
37 + local -a v1comp v2comp
38 + local match=(
39 + "+([0-9])*(.+([0-9]))" # numeric components
40 + "[a-z]" # letter component
41 + "*(@(_alpha|_beta|_pre|_rc|_p)*([0-9]))" # suffixes
42 + "-r+([0-9])" # revision
43 + )
44 +
45 + local LC_ALL=C shopt_save=$(shopt -p extglob)
46 + shopt -s extglob
47 +
48 + if [[ $# -eq 2 ]]; then
49 + v1=${PVR}
50 + elif [[ $# -eq 3 ]]; then
51 + v1=$1; shift
52 + else
53 + die "${FUNCNAME}: bad number of arguments"
54 + fi
55 + op=$1
56 + v2=$2
57 +
58 + case ${op} in
59 + -eq|-ne|-lt|-le|-gt|-ge) ;;
60 + *) die "${FUNCNAME}: invalid operator: ${op}" ;;
61 + esac
62 +
63 + # Test for both versions being valid, and split them into parts
64 + for (( i=0; i<4; i++ )); do
65 + tail=${v1##${match[i]}}
66 + v1comp[i]=${v1%"${tail}"}
67 + v1=${tail}
68 + tail=${v2##${match[i]}}
69 + v2comp[i]=${v2%"${tail}"}
70 + v2=${tail}
71 + done
72 + # There must not be any remaining tail, and the numeric part
73 + # must be non-empty. All other parts are optional.
74 + [[ -z ${v1} && -z ${v2} && -n ${v1comp[0]} && -n ${v2comp[0]} ]] \
75 + || die "${FUNCNAME}: invalid version"
76 +
77 + # Compare numeric components (PMS algorithm 3.2)
78 + _ver_cmp_num() {
79 + local a=(${1//./ }) b=(${2//./ })
80 + local an=${#a[@]} bn=${#b[@]}
81 + local i
82 + # First component
83 + [[ 10#${a[0]} -gt 10#${b[0]} ]] && return 2
84 + [[ 10#${a[0]} -lt 10#${b[0]} ]] && return 1
85 + for (( i=1; i<an && i<bn; i++ )); do
86 + # Other components (PMS algorithm 3.3)
87 + if [[ ${a[i]} == 0* || ${b[i]} == 0* ]]; then
88 + local ap=${a[i]%%*(0)} bp=${b[i]%%*(0)}
89 + [[ ${ap} > ${bp} ]] && return 2
90 + [[ ${ap} < ${bp} ]] && return 1
91 + else
92 + [[ ${a[i]} -gt ${b[i]} ]] && return 2
93 + [[ ${a[i]} -lt ${b[i]} ]] && return 1
94 + fi
95 + done
96 + [[ ${an} -gt ${bn} ]] && return 2
97 + [[ ${an} -lt ${bn} ]] && return 1
98 + return 0
99 + }
100 +
101 + # Compare letter components (PMS algorithm 3.4)
102 + _ver_cmp_let() {
103 + local a=$1 b=$2
104 + [[ ${a} > ${b} ]] && return 2
105 + [[ ${a} < ${b} ]] && return 1
106 + return 0
107 + }
108 +
109 + # Compare suffixes (PMS algorithm 3.5)
110 + _ver_cmp_suf() {
111 + local a=(${1//_/ }) b=(${2//_/ })
112 + local an=${#a[@]} bn=${#b[@]}
113 + local i
114 + for (( i=0; i<an && i<bn; i++ )); do
115 + # Compare each suffix (PMS algorithm 3.6)
116 + if [[ ${a[i]%%*([0-9])} == "${b[i]%%*([0-9])}" ]]; then
117 + [[ 10#${a[i]##*([a-z])} -gt 10#${b[i]##*([a-z])} ]] && return 2
118 + [[ 10#${a[i]##*([a-z])} -lt 10#${b[i]##*([a-z])} ]] && return 1
119 + else
120 + # Check for p first
121 + [[ ${a[i]} == p*([0-9]) ]] && return 2
122 + [[ ${b[i]} == p*([0-9]) ]] && return 1
123 + # Hack: Use that alpha < beta < pre < rc alphabetically
124 + [[ ${a[i]} > ${b[i]} ]] && return 2 || return 1
125 + fi
126 + done
127 + if [[ ${an} -gt ${bn} ]]; then
128 + [[ ${a[bn]} == p*([0-9]) ]] && return 2 || return 1
129 + elif [[ ${an} -lt ${bn} ]]; then
130 + [[ ${b[an]} == p*([0-9]) ]] && return 1 || return 2
131 + fi
132 + return 0
133 + }
134 +
135 + # Compare revision components (PMS algorithm 3.7)
136 + _ver_cmp_rev() {
137 + local a=${1#-r} b=${2#-r}
138 + [[ 10#${a} -gt 10#${b} ]] && return 2
139 + [[ 10#${a} -lt 10#${b} ]] && return 1
140 + return 0
141 + }
142 +
143 + # Version comparison top-level logic (PMS algorithm 3.1)
144 + _ver_cmp_num "${v1comp[0]}" "${v2comp[0]}" &&
145 + _ver_cmp_let "${v1comp[1]}" "${v2comp[1]}" &&
146 + _ver_cmp_suf "${v1comp[2]}" "${v2comp[2]}" &&
147 + _ver_cmp_rev "${v1comp[3]}" "${v2comp[3]}"
148 +
149 + case $? in
150 + 0) result=0 ;; # a = b
151 + 1) result=-1 ;; # a < b
152 + 2) result=1 ;; # a > b
153 + *) die "${FUNCNAME}: invalid return code: $?" ;;
154 + esac
155 +
156 + ${shopt_save}
157 +
158 + test "${result}" "${op}" 0
159 }
160
161 diff --git a/eclass/tests/eapi7-ver.sh b/eclass/tests/eapi7-ver.sh
162 index 8a96e4d29b1..fd085a415b6 100755
163 --- a/eclass/tests/eapi7-ver.sh
164 +++ b/eclass/tests/eapi7-ver.sh
165 @@ -17,6 +17,15 @@ teq() {
166 tend ${?} "returned: ${got}"
167 }
168
169 +teqr() {
170 + local expected=$1; shift
171 + tbegin "$* -> ${expected}"
172 + "$@"
173 + local ret=$?
174 + [[ ${ret} -eq ${expected} ]]
175 + tend $? "returned: ${ret}"
176 +}
177 +
178 txf() {
179 tbegin "XFAIL: ${*}"
180 local got=$("${@}" 2>&1)
181 @@ -63,3 +72,106 @@ teq 1.2.3 ver_rs 3-5 . 1.2.3
182 txf ver_cut foo 1.2.3
183 txf ver_rs -3 _ a1b2c3d4e5
184 txf ver_rs 5-3 _ a1b2c3d4e5
185 +
186 +# Tests from Portage's test_vercmp.py
187 +teqr 0 ver_test 6.0 -gt 5.0
188 +teqr 0 ver_test 5.0 -gt 5
189 +teqr 0 ver_test 1.0-r1 -gt 1.0-r0
190 +teqr 0 ver_test 999999999999999999 -gt 999999999999999998 # 18 digits
191 +teqr 0 ver_test 1.0.0 -gt 1.0
192 +teqr 0 ver_test 1.0.0 -gt 1.0b
193 +teqr 0 ver_test 1b -gt 1
194 +teqr 0 ver_test 1b_p1 -gt 1_p1
195 +teqr 0 ver_test 1.1b -gt 1.1
196 +teqr 0 ver_test 12.2.5 -gt 12.2b
197 +teqr 0 ver_test 4.0 -lt 5.0
198 +teqr 0 ver_test 5 -lt 5.0
199 +teqr 0 ver_test 1.0_pre2 -lt 1.0_p2
200 +teqr 0 ver_test 1.0_alpha2 -lt 1.0_p2
201 +teqr 0 ver_test 1.0_alpha1 -lt 1.0_beta1
202 +teqr 0 ver_test 1.0_beta3 -lt 1.0_rc3
203 +teqr 0 ver_test 1.001000000000000001 -lt 1.001000000000000002
204 +teqr 0 ver_test 1.00100000000 -lt 1.001000000000000001
205 +teqr 0 ver_test 999999999999999998 -lt 999999999999999999
206 +teqr 0 ver_test 1.01 -lt 1.1
207 +teqr 0 ver_test 1.0-r0 -lt 1.0-r1
208 +teqr 0 ver_test 1.0 -lt 1.0-r1
209 +teqr 0 ver_test 1.0 -lt 1.0.0
210 +teqr 0 ver_test 1.0b -lt 1.0.0
211 +teqr 0 ver_test 1_p1 -lt 1b_p1
212 +teqr 0 ver_test 1 -lt 1b
213 +teqr 0 ver_test 1.1 -lt 1.1b
214 +teqr 0 ver_test 12.2b -lt 12.2.5
215 +teqr 0 ver_test 4.0 -eq 4.0
216 +teqr 0 ver_test 1.0 -eq 1.0
217 +teqr 0 ver_test 1.0-r0 -eq 1.0
218 +teqr 0 ver_test 1.0 -eq 1.0-r0
219 +teqr 0 ver_test 1.0-r0 -eq 1.0-r0
220 +teqr 0 ver_test 1.0-r1 -eq 1.0-r1
221 +teqr 1 ver_test 1 -eq 2
222 +teqr 1 ver_test 1.0_alpha -eq 1.0_pre
223 +teqr 1 ver_test 1.0_beta -eq 1.0_alpha
224 +teqr 1 ver_test 1 -eq 0.0
225 +teqr 1 ver_test 1.0-r0 -eq 1.0-r1
226 +teqr 1 ver_test 1.0-r1 -eq 1.0-r0
227 +teqr 1 ver_test 1.0 -eq 1.0-r1
228 +teqr 1 ver_test 1.0-r1 -eq 1.0
229 +teqr 1 ver_test 1.0 -eq 1.0.0
230 +teqr 1 ver_test 1_p1 -eq 1b_p1
231 +teqr 1 ver_test 1b -eq 1
232 +teqr 1 ver_test 1.1b -eq 1.1
233 +teqr 1 ver_test 12.2b -eq 12.2
234 +
235 +# A subset of tests from Paludis
236 +teqr 0 ver_test 1.0_alpha -gt 1_alpha
237 +teqr 0 ver_test 1.0_alpha -gt 1
238 +teqr 0 ver_test 1.0_alpha -lt 1.0
239 +teqr 0 ver_test 1.2.0.0_alpha7-r4 -gt 1.2_alpha7-r4
240 +teqr 0 ver_test 0001 -eq 1
241 +teqr 0 ver_test 01 -eq 001
242 +teqr 0 ver_test 0001.1 -eq 1.1
243 +teqr 0 ver_test 01.01 -eq 1.01
244 +teqr 0 ver_test 1.010 -eq 1.01
245 +teqr 0 ver_test 1.00 -eq 1.0
246 +teqr 0 ver_test 1.0100 -eq 1.010
247 +teqr 0 ver_test 1-r00 -eq 1-r0
248 +
249 +# Additional tests
250 +teqr 0 ver_test 0_rc99 -lt 0
251 +teqr 0 ver_test 011 -eq 11
252 +teqr 0 ver_test 019 -eq 19
253 +teqr 0 ver_test 1.2 -eq 001.2
254 +teqr 0 ver_test 1.2 -gt 1.02
255 +teqr 0 ver_test 1.2a -lt 1.2b
256 +teqr 0 ver_test 1.2_pre1 -gt 1.2_pre1_beta2
257 +teqr 0 ver_test 1.2_pre1 -lt 1.2_pre1_p2
258 +teqr 0 ver_test 1.00 -lt 1.0.0
259 +teqr 0 ver_test 1.010 -eq 1.01
260 +teqr 0 ver_test 1.01 -lt 1.1
261 +teqr 0 ver_test 1.2_pre08-r09 -eq 1.2_pre8-r9
262 +teqr 0 ver_test 0 -lt 576460752303423488 # 2**59
263 +#teqr 0 ver_test 0 -lt 9223372036854775808 # 2**63 fails, integer rollover
264 +
265 +# Bad number or ordering of arguments
266 +txf ver_test 1
267 +txf ver_test 1 -lt 2 3
268 +txf ver_test -lt 1 2
269 +
270 +# Bad operators
271 +txf ver_test 1 "<" 2
272 +txf ver_test 1 lt 2
273 +txf ver_test 1 -foo 2
274 +
275 +# Malformed versions
276 +txf ver_test "" -ne 1
277 +txf ver_test 1. -ne 1
278 +txf ver_test 1ab -ne 1
279 +txf ver_test b -ne 1
280 +txf ver_test 1-r1_pre -ne 1
281 +txf ver_test 1-pre1 -ne 1
282 +txf ver_test 1_foo -ne 1
283 +txf ver_test 1_pre1.1 -ne 1
284 +txf ver_test 1-r1.0 -ne 1
285 +txf ver_test cvs.9999 -ne 9999
286 +
287 +texit
288
289 diff --git a/eclass/tests/eapi7-ver_benchmark.sh b/eclass/tests/eapi7-ver_benchmark.sh
290 index 1de26444c9b..c4671371336 100755
291 --- a/eclass/tests/eapi7-ver_benchmark.sh
292 +++ b/eclass/tests/eapi7-ver_benchmark.sh
293 @@ -76,6 +76,38 @@ replacing_versionator() {
294 done >/dev/null
295 }
296
297 +comparing() {
298 + local x
299 + for x in {1..1000}; do
300 + ver_test 1b_p1 -le 1_p1
301 + ver_test 1.1b -le 1.1
302 + ver_test 12.2.5 -le 12.2b
303 + ver_test 4.0 -le 5.0
304 + ver_test 5 -le 5.0
305 + ver_test 1.0_pre2 -le 1.0_p2
306 + ver_test 1.0_alpha2 -le 1.0_p2
307 + ver_test 1.0_alpha1 -le 1.0_beta1
308 + ver_test 1.0_beta3 -le 1.0_rc3
309 + ver_test 1.001000000000000001 -le 1.001000000000000002
310 + done
311 +}
312 +
313 +comparing_versionator() {
314 + local x
315 + for x in {1..100}; do
316 + version_is_at_least 1b_p1 1_p1
317 + version_is_at_least 1.1b 1.1
318 + version_is_at_least 12.2.5 12.2b
319 + version_is_at_least 4.0 5.0
320 + version_is_at_least 5 5.0
321 + version_is_at_least 1.0_pre2 1.0_p2
322 + version_is_at_least 1.0_alpha2 1.0_p2
323 + version_is_at_least 1.0_alpha1 1.0_beta1
324 + version_is_at_least 1.0_beta3 1.0_rc3
325 + version_is_at_least 1.001000000000000001 1.001000000000000002
326 + done
327 +}
328 +
329 get_times() {
330 local factor=${1}; shift
331 echo "${*}"
332 @@ -111,3 +143,5 @@ get_times 1 cutting
333 get_times 10 cutting_versionator
334 get_times 1 replacing
335 get_times 10 replacing_versionator
336 +get_times 1 comparing
337 +get_times 10 comparing_versionator