Gentoo Archives: gentoo-dev

From: Ulrich Mueller <ulm@g.o>
To: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] [PATCH] eapi7-ver.eclass: 'Early adopter' version of EAPI 7 version manip
Date: Thu, 21 Sep 2017 17:47:55
Message-Id: 22979.64317.961723.534824@a1i15.kph.uni-mainz.de
In Reply to: Re: [gentoo-dev] [PATCH] eapi7-ver.eclass: 'Early adopter' version of EAPI 7 version manip by "Michał Górny"
1 >>>>> On Tue, 19 Sep 2017, Michał Górny wrote:
2
3 >> EAPI 7 is introducing new version manipulation and comparison functions
4 >> that aim to replace versionator.eclass. This eclass provides an 'early
5 >> adopter' versions of those routines.
6 >>
7 >> It serves two goals:
8 >>
9 >> a. getting wider review and some real-life testing before
10 >> the specification is set in stone, and
11 >>
12 >> b. making it possible to adapt ebuilds to the new routines early,
13 >> reducing the future work of EAPI 7 porting.
14 >>
15 >> For more details on the new logic, please see the eclass documentation.
16 >> Long story short, we are introducing three functions:
17 >>
18 >> 1. ver_cut -- to get substrings of the version string,
19 >>
20 >> 2. ver_rs -- to replace version separators via indices,
21 >>
22 >> 3. ver_test -- to compare two version numbers.
23 >>
24 >> The third function is not implemented in the eclass. It's meant to reuse
25 >> the algorithms from the package manager, and the final implementation
26 >> will most likely reuse the code from the package manager (e.g. via IPC).
27
28 Meanwhile the ver_test function has been added to the eclass in the
29 eapi7-ver branch. Please review the patch included below.
30
31 > Merged now, with some documentation fixes and additional benchmark to
32 > compare it with versionator.eclass. [...]
33
34 For completeness, here are benchmark results for ver_test(),
35 in comparison with version_is_at_least().
36
37 comparing
38 real 6.78 6.80 6.81 6.76 6.75 => 6.78 avg
39 user 6.73 6.75 6.75 6.71 6.69 => 6.73 avg
40 comparing_versionator
41 real 196.60 197.80 197.40 199.10 198.60 => 197.90 avg
42 user 80.10 80.10 80.00 80.40 80.60 => 80.24 avg
43
44 Ulrich
45
46 -- 8< --
47 From 9c4953e2d2bdef1244cff025672489bf9c9ff72b Mon Sep 17 00:00:00 2001
48 From: =?UTF-8?q?Ulrich=20M=C3=BCller?= <ulm@g.o>
49 Date: Wed, 20 Sep 2017 21:28:22 +0200
50 Subject: [PATCH] eapi7-ver.eclass: Implement ver_test().
51 MIME-Version: 1.0
52 Content-Type: text/plain; charset=UTF-8
53 Content-Transfer-Encoding: 8bit
54
55 This should strictly follow Algorithms 3.1 to 3.7 specified in PMS:
56 https://projects.gentoo.org/pms/6/pms.html#x1-310003.3
57
58 Thanks to Michał Górny for many optimizations, and for pointing out
59 how much my initial implementation sucked. ;-)
60 ---
61 eclass/eapi7-ver.eclass | 111 +++++++++++++++++++++++++++++++++++-
62 eclass/tests/eapi7-ver.sh | 107 ++++++++++++++++++++++++++++++++++
63 eclass/tests/eapi7-ver_benchmark.sh | 34 +++++++++++
64 3 files changed, 251 insertions(+), 1 deletion(-)
65
66 diff --git a/eclass/eapi7-ver.eclass b/eclass/eapi7-ver.eclass
67 index 6f8f0c0a1c37..ead9fac5e807 100644
68 --- a/eclass/eapi7-ver.eclass
69 +++ b/eclass/eapi7-ver.eclass
70 @@ -176,6 +176,94 @@ ver_rs() {
71 echo "${comp[*]}"
72 }
73
74 +# @FUNCTION: _ver_compare
75 +# @USAGE: <va> <vb>
76 +# @RETURN: 1 if <va> < <vb>, 2 if <va> = <vb>, 3 if <va> > <vb>
77 +# @INTERNAL
78 +# @DESCRIPTION:
79 +# Compare two versions <va> and <vb>. If <va> is less than, equal to,
80 +# or greater than <vb>, return 1, 2, or 3 as exit status, respectively.
81 +_ver_compare() {
82 + local va=${1} vb=${2} a an al as ar b bn bl bs br re
83 +
84 + re="^([0-9]+(\.[0-9]+)*)([a-z]?)((_(alpha|beta|pre|rc|p)[0-9]*)*)(-r[0-9]+)?$"
85 +
86 + [[ ${va} =~ ${re} ]] || die "${FUNCNAME}: invalid version: ${va}"
87 + an=${BASH_REMATCH[1]}
88 + al=${BASH_REMATCH[3]}
89 + as=${BASH_REMATCH[4]}
90 + ar=${BASH_REMATCH[7]}
91 +
92 + [[ ${vb} =~ ${re} ]] || die "${FUNCNAME}: invalid version: ${vb}"
93 + bn=${BASH_REMATCH[1]}
94 + bl=${BASH_REMATCH[3]}
95 + bs=${BASH_REMATCH[4]}
96 + br=${BASH_REMATCH[7]}
97 +
98 + # Compare numeric components (PMS algorithm 3.2)
99 + # First component
100 + a=${an%%.*}
101 + b=${bn%%.*}
102 + [[ 10#${a} -gt 10#${b} ]] && return 3
103 + [[ 10#${a} -lt 10#${b} ]] && return 1
104 +
105 + while [[ ${an} == *.* && ${bn} == *.* ]]; do
106 + # Other components (PMS algorithm 3.3)
107 + an=${an#*.}
108 + bn=${bn#*.}
109 + a=${an%%.*}
110 + b=${bn%%.*}
111 + if [[ ${a} == 0* || ${b} == 0* ]]; then
112 + # Remove trailing zeros
113 + while [[ ${a} == *0 ]]; do a=${a::-1}; done
114 + while [[ ${b} == *0 ]]; do b=${b::-1}; done
115 + [[ ${a} > ${b} ]] && return 3
116 + [[ ${a} < ${b} ]] && return 1
117 + else
118 + [[ ${a} -gt ${b} ]] && return 3
119 + [[ ${a} -lt ${b} ]] && return 1
120 + fi
121 + done
122 + [[ ${an} == *.* ]] && return 3
123 + [[ ${bn} == *.* ]] && return 1
124 +
125 + # Compare letter components (PMS algorithm 3.4)
126 + [[ ${al} > ${bl} ]] && return 3
127 + [[ ${al} < ${bl} ]] && return 1
128 +
129 + # Compare suffixes (PMS algorithm 3.5)
130 + as=${as#_}${as:+_}
131 + bs=${bs#_}${bs:+_}
132 + while [[ -n ${as} && -n ${bs} ]]; do
133 + # Compare each suffix (PMS algorithm 3.6)
134 + a=${as%%_*}
135 + b=${bs%%_*}
136 + if [[ ${a%%[0-9]*} == "${b%%[0-9]*}" ]]; then
137 + [[ 10#${a##*[a-z]} -gt 10#${b##*[a-z]} ]] && return 3
138 + [[ 10#${a##*[a-z]} -lt 10#${b##*[a-z]} ]] && return 1
139 + else
140 + # Check for p first
141 + [[ ${a%%[0-9]*} == p ]] && return 3
142 + [[ ${b%%[0-9]*} == p ]] && return 1
143 + # Hack: Use that alpha < beta < pre < rc alphabetically
144 + [[ ${a} > ${b} ]] && return 3 || return 1
145 + fi
146 + as=${as#*_}
147 + bs=${bs#*_}
148 + done
149 + if [[ -n ${as} ]]; then
150 + [[ ${as} == p[_0-9]* ]] && return 3 || return 1
151 + elif [[ -n ${bs} ]]; then
152 + [[ ${bs} == p[_0-9]* ]] && return 1 || return 3
153 + fi
154 +
155 + # Compare revision components (PMS algorithm 3.7)
156 + [[ 10#${ar#-r} -gt 10#${br#-r} ]] && return 3
157 + [[ 10#${ar#-r} -lt 10#${br#-r} ]] && return 1
158 +
159 + return 2
160 +}
161 +
162 # @FUNCTION: ver_test
163 # @USAGE: [<v1>] <op> <v2>
164 # @DESCRIPTION:
165 @@ -185,5 +273,26 @@ ver_rs() {
166 # revision parts), and the comparison is performed according to
167 # the algorithm specified in the PMS.
168 ver_test() {
169 - die "${FUNCNAME}: not implemented"
170 + local LC_ALL=C
171 + local va op vb
172 +
173 + if [[ $# -eq 3 ]]; then
174 + va=${1}
175 + shift
176 + else
177 + va=${PVR}
178 + fi
179 +
180 + [[ $# -eq 2 ]] || die "${FUNCNAME}: bad number of arguments"
181 +
182 + op=${1}
183 + vb=${2}
184 +
185 + case ${op} in
186 + -eq|-ne|-lt|-le|-gt|-ge) ;;
187 + *) die "${FUNCNAME}: invalid operator: ${op}" ;;
188 + esac
189 +
190 + _ver_compare "${va}" "${vb}"
191 + test $? "${op}" 2
192 }
193 diff --git a/eclass/tests/eapi7-ver.sh b/eclass/tests/eapi7-ver.sh
194 index 8a96e4d29b1b..144bb2bddc3e 100755
195 --- a/eclass/tests/eapi7-ver.sh
196 +++ b/eclass/tests/eapi7-ver.sh
197 @@ -17,6 +17,15 @@ teq() {
198 tend ${?} "returned: ${got}"
199 }
200
201 +teqr() {
202 + local expected=$1; shift
203 + tbegin "$* -> ${expected}"
204 + "$@"
205 + local ret=$?
206 + [[ ${ret} -eq ${expected} ]]
207 + tend $? "returned: ${ret}"
208 +}
209 +
210 txf() {
211 tbegin "XFAIL: ${*}"
212 local got=$("${@}" 2>&1)
213 @@ -63,3 +72,101 @@ teq 1.2.3 ver_rs 3-5 . 1.2.3
214 txf ver_cut foo 1.2.3
215 txf ver_rs -3 _ a1b2c3d4e5
216 txf ver_rs 5-3 _ a1b2c3d4e5
217 +
218 +# Tests from Portage's test_vercmp.py
219 +teqr 0 ver_test 6.0 -gt 5.0
220 +teqr 0 ver_test 5.0 -gt 5
221 +teqr 0 ver_test 1.0-r1 -gt 1.0-r0
222 +teqr 0 ver_test 999999999999999999 -gt 999999999999999998 # 18 digits
223 +teqr 0 ver_test 1.0.0 -gt 1.0
224 +teqr 0 ver_test 1.0.0 -gt 1.0b
225 +teqr 0 ver_test 1b -gt 1
226 +teqr 0 ver_test 1b_p1 -gt 1_p1
227 +teqr 0 ver_test 1.1b -gt 1.1
228 +teqr 0 ver_test 12.2.5 -gt 12.2b
229 +teqr 0 ver_test 4.0 -lt 5.0
230 +teqr 0 ver_test 5 -lt 5.0
231 +teqr 0 ver_test 1.0_pre2 -lt 1.0_p2
232 +teqr 0 ver_test 1.0_alpha2 -lt 1.0_p2
233 +teqr 0 ver_test 1.0_alpha1 -lt 1.0_beta1
234 +teqr 0 ver_test 1.0_beta3 -lt 1.0_rc3
235 +teqr 0 ver_test 1.001000000000000001 -lt 1.001000000000000002
236 +teqr 0 ver_test 1.00100000000 -lt 1.001000000000000001
237 +teqr 0 ver_test 999999999999999998 -lt 999999999999999999
238 +teqr 0 ver_test 1.01 -lt 1.1
239 +teqr 0 ver_test 1.0-r0 -lt 1.0-r1
240 +teqr 0 ver_test 1.0 -lt 1.0-r1
241 +teqr 0 ver_test 1.0 -lt 1.0.0
242 +teqr 0 ver_test 1.0b -lt 1.0.0
243 +teqr 0 ver_test 1_p1 -lt 1b_p1
244 +teqr 0 ver_test 1 -lt 1b
245 +teqr 0 ver_test 1.1 -lt 1.1b
246 +teqr 0 ver_test 12.2b -lt 12.2.5
247 +teqr 0 ver_test 4.0 -eq 4.0
248 +teqr 0 ver_test 1.0 -eq 1.0
249 +teqr 0 ver_test 1.0-r0 -eq 1.0
250 +teqr 0 ver_test 1.0 -eq 1.0-r0
251 +teqr 0 ver_test 1.0-r0 -eq 1.0-r0
252 +teqr 0 ver_test 1.0-r1 -eq 1.0-r1
253 +teqr 1 ver_test 1 -eq 2
254 +teqr 1 ver_test 1.0_alpha -eq 1.0_pre
255 +teqr 1 ver_test 1.0_beta -eq 1.0_alpha
256 +teqr 1 ver_test 1 -eq 0.0
257 +teqr 1 ver_test 1.0-r0 -eq 1.0-r1
258 +teqr 1 ver_test 1.0-r1 -eq 1.0-r0
259 +teqr 1 ver_test 1.0 -eq 1.0-r1
260 +teqr 1 ver_test 1.0-r1 -eq 1.0
261 +teqr 1 ver_test 1.0 -eq 1.0.0
262 +teqr 1 ver_test 1_p1 -eq 1b_p1
263 +teqr 1 ver_test 1b -eq 1
264 +teqr 1 ver_test 1.1b -eq 1.1
265 +teqr 1 ver_test 12.2b -eq 12.2
266 +
267 +# A subset of tests from Paludis
268 +teqr 0 ver_test 1.0_alpha -gt 1_alpha
269 +teqr 0 ver_test 1.0_alpha -gt 1
270 +teqr 0 ver_test 1.0_alpha -lt 1.0
271 +teqr 0 ver_test 1.2.0.0_alpha7-r4 -gt 1.2_alpha7-r4
272 +teqr 0 ver_test 0001 -eq 1
273 +teqr 0 ver_test 01 -eq 001
274 +teqr 0 ver_test 0001.1 -eq 1.1
275 +teqr 0 ver_test 01.01 -eq 1.01
276 +teqr 0 ver_test 1.010 -eq 1.01
277 +teqr 0 ver_test 1.00 -eq 1.0
278 +teqr 0 ver_test 1.0100 -eq 1.010
279 +teqr 0 ver_test 1-r00 -eq 1-r0
280 +
281 +# Additional tests
282 +teqr 0 ver_test 0_rc99 -lt 0
283 +teqr 0 ver_test 011 -eq 11
284 +teqr 0 ver_test 019 -eq 19
285 +teqr 0 ver_test 1.2 -eq 001.2
286 +teqr 0 ver_test 1.2 -gt 1.02
287 +teqr 0 ver_test 1.2a -lt 1.2b
288 +teqr 0 ver_test 1.2_pre1 -gt 1.2_pre1_beta2
289 +teqr 0 ver_test 1.2_pre1 -lt 1.2_pre1_p2
290 +teqr 0 ver_test 1.00 -lt 1.0.0
291 +teqr 0 ver_test 1.010 -eq 1.01
292 +teqr 0 ver_test 1.01 -lt 1.1
293 +teqr 0 ver_test 1.2_pre08-r09 -eq 1.2_pre8-r9
294 +
295 +# Bad number or ordering of arguments
296 +txf ver_test 1
297 +txf ver_test 1 -lt 2 3
298 +txf ver_test -lt 1 2
299 +
300 +# Bad operators
301 +txf ver_test 1 "<" 2
302 +txf ver_test 1 lt 2
303 +txf ver_test 1 -foo 2
304 +
305 +# Malformed versions
306 +txf ver_test "" -ne 1
307 +txf ver_test 1. -ne 1
308 +txf ver_test 1ab -ne 1
309 +txf ver_test b -ne 1
310 +txf ver_test 1-r1_pre -ne 1
311 +txf ver_test 1-pre1 -ne 1
312 +txf ver_test 1_foo -ne 1
313 +txf ver_test 1_pre1.1 -ne 1
314 +txf ver_test 1-r1.0 -ne 1
315 diff --git a/eclass/tests/eapi7-ver_benchmark.sh b/eclass/tests/eapi7-ver_benchmark.sh
316 index 1de26444c9b3..c46713713368 100755
317 --- a/eclass/tests/eapi7-ver_benchmark.sh
318 +++ b/eclass/tests/eapi7-ver_benchmark.sh
319 @@ -76,6 +76,38 @@ replacing_versionator() {
320 done >/dev/null
321 }
322
323 +comparing() {
324 + local x
325 + for x in {1..1000}; do
326 + ver_test 1b_p1 -le 1_p1
327 + ver_test 1.1b -le 1.1
328 + ver_test 12.2.5 -le 12.2b
329 + ver_test 4.0 -le 5.0
330 + ver_test 5 -le 5.0
331 + ver_test 1.0_pre2 -le 1.0_p2
332 + ver_test 1.0_alpha2 -le 1.0_p2
333 + ver_test 1.0_alpha1 -le 1.0_beta1
334 + ver_test 1.0_beta3 -le 1.0_rc3
335 + ver_test 1.001000000000000001 -le 1.001000000000000002
336 + done
337 +}
338 +
339 +comparing_versionator() {
340 + local x
341 + for x in {1..100}; do
342 + version_is_at_least 1b_p1 1_p1
343 + version_is_at_least 1.1b 1.1
344 + version_is_at_least 12.2.5 12.2b
345 + version_is_at_least 4.0 5.0
346 + version_is_at_least 5 5.0
347 + version_is_at_least 1.0_pre2 1.0_p2
348 + version_is_at_least 1.0_alpha2 1.0_p2
349 + version_is_at_least 1.0_alpha1 1.0_beta1
350 + version_is_at_least 1.0_beta3 1.0_rc3
351 + version_is_at_least 1.001000000000000001 1.001000000000000002
352 + done
353 +}
354 +
355 get_times() {
356 local factor=${1}; shift
357 echo "${*}"
358 @@ -111,3 +143,5 @@ get_times 1 cutting
359 get_times 10 cutting_versionator
360 get_times 1 replacing
361 get_times 10 replacing_versionator
362 +get_times 1 comparing
363 +get_times 10 comparing_versionator
364 --
365 2.14.1

Replies