/[gentoo-x86]/eclass/versionator.eclass
Gentoo

Diff of /eclass/versionator.eclass

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.6 Revision 1.7
1# Copyright 1999-2004 Gentoo Foundation 1# Copyright 1999-2004 Gentoo Foundation
2# Distributed under the terms of the GNU General Public License v2 2# Distributed under the terms of the GNU General Public License v2
3# $Header: /var/cvsroot/gentoo-x86/eclass/versionator.eclass,v 1.6 2005/03/25 00:51:48 ciaranm Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/versionator.eclass,v 1.7 2005/05/21 04:56:20 ciaranm Exp $
4# 4#
5# Original Author: Ciaran McCreesh <ciaranm@gentoo.org> 5# Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
6# 6#
7# This eclass provides functions which simplify manipulating $PV and similar 7# This eclass provides functions which simplify manipulating $PV and similar
8# variables. Most functions default to working with $PV, although other 8# variables. Most functions default to working with $PV, although other
30# such as '-', '.' or '_'. In this case, the first separator of this kind is 30# such as '-', '.' or '_'. In this case, the first separator of this kind is
31# selected. 31# selected.
32# 32#
33# There's also: 33# There's also:
34# version_is_at_least want have 34# version_is_at_least want have
35# but it doesn't work in all cases, so only use it if you know what you're 35# which may be buggy, so use with caution.
36# doing.
37 36
38ECLASS=versionator 37ECLASS=versionator
39INHERITED="$INHERITED $ECLASS" 38INHERITED="$INHERITED $ECLASS"
40 39
41shopt -s extglob 40shopt -s extglob
216delete_all_version_separators() { 215delete_all_version_separators() {
217 replace_all_version_separators "" "${1}" 216 replace_all_version_separators "" "${1}"
218} 217}
219 218
220# Is $2 (defaults to $PVR) at least version $1? Intended for use in eclasses 219# Is $2 (defaults to $PVR) at least version $1? Intended for use in eclasses
221# only. Not very reliable, doesn't understand most things, make sure you test 220# only. May not be reliable, be sure to do very careful testing before actually
222# reaaaallly well before using this. Prod ciaranm if you need it to support more 221# using this. Prod ciaranm if you find something it can't handle.
223# things... WARNING: DOES NOT HANDLE 1.2b style versions. WARNING: not very well
224# tested, needs lots of work before it's totally reliable. Use with extreme
225# caution.
226version_is_at_least() { 222version_is_at_least() {
227 local want_s="$1" have_s="${2:-${PVR}}" want_c have_c 223 local want_s="$1" have_s="${2:-${PVR}}" r
228 want_c=( $(get_version_components "$want_s" ) ) 224 version_compare "${want_s}" "${have_s}"
225 r=$?
226 case $r in
227 1|2)
228 return 0
229 ;;
230 3)
231 return 1
232 ;;
233 *)
234 die "versionator compare bug [atleast, ${want_s}, ${have_s}, ${r}]"
235 ;;
236 esac
237}
238
239# Takes two parameters (a, b) which are versions. If a is an earlier version
240# than b, returns 1. If a is identical to b, return 2. If b is later than a,
241# return 3. You probably want version_is_at_least rather than this function.
242# May not be very reliable. Test carefully before using this.
243version_compare() {
244 local ver_a=${1} ver_b=${2} parts_a parts_b cur_idx_a=0 cur_idx_b=0
229 have_c=( $(get_version_components "$have_s" ) ) 245 parts_a=( $(get_all_version_components "${ver_a}" ) )
246 parts_b=( $(get_all_version_components "${ver_b}" ) )
230 247
231 # Stage 1: compare the version numbers part. 248 ### compare number parts.
232 local done_w="" done_h="" i=0 249 local inf_loop=0
233 while [[ -z "${done_w}" ]] || [[ -z "${done_h}" ]] ; do 250 while true ; do
234 local cur_w="${want_c[$i]}" cur_h="${have_c[$i]}" 251 inf_loop=$(( ${inf_loop} + 1 ))
235 local my_cur_w="${cur_w//#0}" my_cur_h="${cur_h//#0}" 252 [[ ${inf_loop} -gt 20 ]] && \
236 [[ -z "${my_cur_w##[^[:digit:]]*}" ]] && done_w="yes" 253 die "versionator compare bug [numbers, ${ver_a}, ${ver_b}]"
237 [[ -z "${my_cur_h##[^[:digit:]]*}" ]] && done_h="yes"
238 [[ -z "${done_w}" ]] || my_cur_w=0
239 [[ -z "${done_h}" ]] || my_cur_h=0
240 if [[ ${my_cur_w} -lt ${my_cur_h} ]] ; then return 0 ; fi
241 if [[ ${my_cur_w} -gt ${my_cur_h} ]] ; then return 1 ; fi
242 i=$(($i + 1))
243 done
244 254
245 local part 255 # grab the current number components
246 for part in "_alpha" "_beta" "_pre" "_rc" "_p" "-r" ; do 256 local cur_tok_a=${parts_a[${cur_idx_a}]}
247 local part_w= part_h= 257 local cur_tok_b=${parts_b[${cur_idx_b}]}
248 258
249 for (( i = 0 ; i < ${#want_c[@]} ; i = $i + 1 )) ; do 259 # number?
250 if [[ -z "${want_c[$i]##${part#[-._]}*}" ]] ; then 260 if [[ -n ${cur_tok_a} ]] && [[ -z ${cur_tok_a//[[:digit:]]} ]] ; then
251 part_w="${want_c[$i]##${part#[-._]}}" 261 cur_idx_a=$(( ${cur_idx_a} + 1 ))
252 break 262 [[ ${parts_a[${cur_idx_a}]} == "." ]] \
253 fi 263 && cur_idx_a=$(( ${cur_idx_a} + 1 ))
254 done
255 for (( i = 0 ; i < ${#have_c[@]} ; i = $i + 1 )) ; do
256 if [[ -z "${have_c[$i]##${part#[-._]}*}" ]] ; then
257 part_h="${have_c[$i]##${part#[-._]}}"
258 break
259 fi
260 done
261
262 if [[ "${part}" == "_p" ]] || [[ "${part}" == "-r" ]] ; then
263 # if present in neither want nor have, go to the next item
264 [[ -z "${part_w}" ]] && [[ -z "${part_h}" ]] && continue
265
266 [[ -z "${part_w}" ]] && [[ -n "${part_h}" ]] && return 0
267 [[ -n "${part_w}" ]] && [[ -z "${part_h}" ]] && return 1
268
269 if [[ ${part_w} -lt ${part_h} ]] ; then return 0 ; fi
270 if [[ ${part_w} -gt ${part_h} ]] ; then return 1 ; fi
271
272 else 264 else
273 # if present in neither want nor have, go to the next item 265 cur_tok_a=""
274 [[ -z "${part_w}" ]] && [[ -z "${part_h}" ]] && continue
275
276 [[ -z "${part_w}" ]] && [[ -n "${part_h}" ]] && return 1
277 [[ -n "${part_w}" ]] && [[ -z "${part_h}" ]] && return 0
278
279 if [[ ${part_w} -lt ${part_h} ]] ; then return 0 ; fi
280 if [[ ${part_w} -gt ${part_h} ]] ; then return 1 ; fi
281 fi 266 fi
267
268 if [[ -n ${cur_tok_b} ]] && [[ -z ${cur_tok_b//[[:digit:]]} ]] ; then
269 cur_idx_b=$(( ${cur_idx_b} + 1 ))
270 [[ ${parts_b[${cur_idx_b}]} == "." ]] \
271 && cur_idx_b=$(( ${cur_idx_b} + 1 ))
272 else
273 cur_tok_b=""
274 fi
275
276 # done with number components?
277 [[ -z ${cur_tok_a} ]] && [[ -z ${cur_tok_b} ]] && break
278
279 # to avoid going into octal mode, strip any leading zeros. otherwise
280 # bash will throw a hissy fit on versions like 6.3.068.
281 cur_tok_a=${cur_tok_a##+(0)}
282 cur_tok_b=${cur_tok_b##+(0)}
283
284 # if a component is blank, make it zero.
285 [[ -z ${cur_tok_a} ]] && cur_tok_a=0
286 [[ -z ${cur_tok_b} ]] && cur_tok_b=0
287
288 # compare
289 [[ ${cur_tok_a} -lt ${cur_tok_b} ]] && return 1
290 [[ ${cur_tok_a} -gt ${cur_tok_b} ]] && return 3
291 done
292
293 ### number parts equal. compare letter parts.
294 local letter_a=
295 letter_a=${parts_a[${cur_idx_a}]}
296 if [[ ${#letter_a} -eq 1 ]] && [[ -z ${letter_a/[a-z]} ]] ; then
297 cur_idx_a=$(( ${cur_idx_a} + 1 ))
298 else
299 letter_a="@"
300 fi
301
302 local letter_b=
303 letter_b=${parts_b[${cur_idx_b}]}
304 if [[ ${#letter_b} -eq 1 ]] && [[ -z ${letter_b/[a-z]} ]] ; then
305 cur_idx_b=$(( ${cur_idx_b} + 1 ))
306 else
307 letter_b="@"
308 fi
309
310 # compare
311 [[ ${letter_a} < ${letter_b} ]] && return 1
312 [[ ${letter_a} > ${letter_b} ]] && return 3
313
314 ### letter parts equal. compare suffixes in order.
315 local suffix rule part r_lt r_gt
316 for rule in "alpha=1" "beta=1" "pre=1" "rc=1" "p=3" "r=3" ; do
317 suffix=${rule%%=*}
318 r_lt=${rule##*=}
319 [[ ${r_lt} -eq 1 ]] && r_gt=3 || r_gt=1
320
321 local suffix_a=
322 for part in ${parts_a[@]} ; do
323 [[ ${part#${suffix}} != ${part} ]] && \
324 [[ -z ${part##${suffix}*([[:digit:]])} ]] && \
325 suffix_a=${part#${suffix}}0
282 done 326 done
283 327
328 local suffix_b=
329 for part in ${parts_b[@]} ; do
330 [[ ${part#${suffix}} != ${part} ]] && \
331 [[ -z ${part##${suffix}*([[:digit:]])} ]] && \
332 suffix_b=${part#${suffix}}0
333 done
334
335 [[ -z ${suffix_a} ]] && [[ -z ${suffix_b} ]] && continue
336
337 [[ -z ${suffix_a} ]] && return ${r_gt}
338 [[ -z ${suffix_b} ]] && return ${r_lt}
339
340 # avoid octal problems
341 suffix_a=${suffix_a##+(0)} ; suffix_a=${suffix_a:-0}
342 suffix_b=${suffix_b##+(0)} ; suffix_b=${suffix_b:-0}
343
344 [[ ${suffix_a} -lt ${suffix_b} ]] && return 1
345 [[ ${suffix_a} -gt ${suffix_b} ]] && return 3
346 done
347
348 ### no differences.
284 return 0 349 return 2
285} 350}
286 351
287# Test function thing. To use, source versionator.eclass and then run it. 352# Returns its parameters sorted, highest version last. We're using a quadratic
353# algorithm for simplicity, so don't call it with more than a few dozen items.
354# Uses version_compare, so be careful.
355version_sort() {
356 local items= left=0
357 items=( $@ )
358 while [[ ${left} -lt ${#items[@]} ]] ; do
359 local lowest_idx=${left}
360 local idx=$(( ${lowest_idx} + 1 ))
361 while [[ ${idx} -lt ${#items[@]} ]] ; do
362 version_compare "${items[${lowest_idx}]}" "${items[${idx}]}"
363 [[ $? -eq 3 ]] && lowest_idx=${idx}
364 idx=$(( ${idx} + 1 ))
365 done
366 local tmp=${items[${lowest_idx}]}
367 items[${lowest_idx}]=${items[${left}]}
368 items[${left}]=${tmp}
369 left=$(( ${left} + 1 ))
370 done
371 echo ${items[@]}
372}
373
288__versionator__test_version_is_at_least() { 374__versionator__test_version_compare() {
289 version_is_at_least "1.2" "1.2" || echo "test 1 failed" 375 local lt=1 eq=2 gt=3 p q
290 version_is_at_least "1.2" "1.2.3" || echo "test 2 failed"
291 version_is_at_least "1.2.3" "1.2" && echo "test 3 failed"
292 376
293 version_is_at_least "1.2_beta1" "1.2" || echo "test 4 failed" 377 __versionator__test_version_compare_t() {
294 version_is_at_least "1.2_alpha1" "1.2" || echo "test 5 failed" 378 version_compare "${1}" "${3}"
295 version_is_at_least "1.2_alpha1" "1.2_beta1" || echo "test 6 failed" 379 local r=$?
380 [[ ${r} -eq ${2} ]] || echo "FAIL: ${@} (got ${r} exp ${2})"
381 }
296 382
297 version_is_at_least "1.2" "1.2_beta1" && echo "test 7 failed" 383 echo "
298 version_is_at_least "1.2" "1.2_alpha1" && echo "test 8 failed" 384 0 $lt 1
299 version_is_at_least "1.2_beta1" "1.2_alpha1" && echo "test 9 failed" 385 1 $lt 2
386 2 $gt 1
387 2 $eq 2
388 0 $eq 0
389 10 $lt 20
390 68 $eq 068
391 068 $gt 67
392 068 $lt 69
300 393
301 version_is_at_least "1.2_beta1" "1.2_beta1" || echo "test 10 failed" 394 1.0 $lt 2.0
302 version_is_at_least "1.2_beta2" "1.2_beta1" && echo "test 11 failed" 395 2.0 $eq 2.0
303 version_is_at_least "1.2_beta2" "1.2_beta3" || echo "test 12 failed" 396 2.0 $gt 1.0
304 397
305 version_is_at_least "1.2-r1" "1.2" && echo "test 13 failed" 398 1.0 $gt 0.0
306 version_is_at_least "1.2" "1.2-r1" || echo "test 14 failed" 399 0.0 $eq 0.0
307 version_is_at_least "1.2-r1" "1.3" || echo "test 15 failed" 400 0.0 $lt 1.0
308 version_is_at_least "1.2-r1" "1.2-r2" || echo "test 16 failed"
309 version_is_at_least "1.2-r3" "1.2-r2" && echo "test 17 failed"
310 401
311 version_is_at_least "1.2-r1" "1.2_beta2-r3" && echo "test 18 failed" 402 0.1 $lt 0.2
312 version_is_at_least "1.2-r1" "1.3_beta2-r3" || echo "test 19 failed" 403 0.2 $eq 0.2
404 0.3 $gt 0.2
313 405
314 version_is_at_least "1.002" "1.2" || echo "test 20 failed" 406 1.2 $lt 2.1
315 version_is_at_least "1.2" "1.002" || echo "test 21 failed" 407 2.1 $gt 1.2
316 version_is_at_least "1.003" "1.2" && echo "test 22 failed"
317 version_is_at_least "1.3" "1.002" && echo "test 23 failed"
318 return 0
319}
320 408
409 1.2.3 $lt 1.2.4
410 1.2.4 $gt 1.2.3
411
412 1.2.0 $eq 1.2
413 1.2.1 $gt 1.2
414 1.2 $lt 1.2.1
415
416 1.2b $eq 1.2b
417 1.2b $lt 1.2c
418 1.2b $gt 1.2a
419 1.2b $gt 1.2
420 1.2 $lt 1.2a
421
422 1.3 $gt 1.2a
423 1.3 $lt 1.3a
424
425 1.0_alpha7 $lt 1.0_beta7
426 1.0_beta $lt 1.0_pre
427 1.0_pre5 $lt 1.0_rc2
428 1.0_rc2 $lt 1.0
429
430 1.0_p1 $gt 1.0
431 1.0_p1-r1 $gt 1.0_p1
432
433 1.0_alpha6-r1 $gt 1.0_alpha6
434 1.0_beta6-r1 $gt 1.0_alpha6-r2
435
436 1.0_pre1 $lt 1.0-p1
437
438 1.0p $gt 1.0_p1
439 1.0r $gt 1.0-r1
440 1.6.15 $gt 1.6.10-r2
441 1.6.10-r2 $lt 1.6.15
442
443 " | while read a b c ; do
444 [[ -z "${a}${b}${c}" ]] && continue;
445 __versionator__test_version_compare_t "${a}" "${b}" "${c}"
446 done
447
448
449 for q in "alpha beta pre rc=${lt};${gt}" "p r=${gt};${lt}" ; do
450 for p in ${q%%=*} ; do
451 local c=${q##*=}
452 local alt=${c%%;*} agt=${c##*;}
453 __versionator__test_version_compare_t "1.0" $agt "1.0_${p}"
454 __versionator__test_version_compare_t "1.0" $agt "1.0_${p}1"
455 __versionator__test_version_compare_t "1.0" $agt "1.0_${p}068"
456
457 __versionator__test_version_compare_t "2.0_${p}" $alt "2.0"
458 __versionator__test_version_compare_t "2.0_${p}1" $alt "2.0"
459 __versionator__test_version_compare_t "2.0_${p}068" $alt "2.0"
460
461 __versionator__test_version_compare_t "1.0_${p}" $eq "1.0_${p}"
462 __versionator__test_version_compare_t "0.0_${p}" $lt "0.0_${p}1"
463 __versionator__test_version_compare_t "666_${p}3" $gt "666_${p}"
464
465 __versionator__test_version_compare_t "1_${p}7" $lt "1_${p}8"
466 __versionator__test_version_compare_t "1_${p}7" $eq "1_${p}7"
467 __versionator__test_version_compare_t "1_${p}7" $gt "1_${p}6"
468 __versionator__test_version_compare_t "1_${p}09" $eq "1_${p}9"
469 done
470 done
471
472 for p in "-r" "_p" ; do
473 __versionator__test_version_compare_t "7.2${p}1" $lt "7.2${p}2"
474 __versionator__test_version_compare_t "7.2${p}2" $gt "7.2${p}1"
475 __versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2"
476 __versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3"
477 done
478
479}
480

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

  ViewVC Help
Powered by ViewVC 1.1.20