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 |