Lines 315-381
version_is_at_least() {
Link Here
|
315 |
version_compare() { |
315 |
version_compare() { |
316 |
eshopts_push -s extglob |
316 |
eshopts_push -s extglob |
317 |
local ver_a=${1} ver_b=${2} parts_a parts_b cur_idx_a=0 cur_idx_b=0 |
317 |
local ver_a=${1} ver_b=${2} parts_a parts_b cur_idx_a=0 cur_idx_b=0 |
|
|
318 |
local cur_tok_a cur_tok_b num_part_a num_part_b prev_idx_a prev_idx_b |
318 |
parts_a=( $(get_all_version_components "${ver_a}" ) ) |
319 |
parts_a=( $(get_all_version_components "${ver_a}" ) ) |
319 |
parts_b=( $(get_all_version_components "${ver_b}" ) ) |
320 |
parts_b=( $(get_all_version_components "${ver_b}" ) ) |
320 |
|
321 |
|
321 |
### compare number parts. |
322 |
### compare number parts. |
322 |
local inf_loop=0 |
323 |
local inf_loop=0 |
323 |
while true ; do |
324 |
while true ; do |
324 |
inf_loop=$(( ${inf_loop} + 1 )) |
325 |
(( inf_loop++ )) |
325 |
[[ ${inf_loop} -gt 20 ]] && \ |
326 |
(( inf_loop > 20 )) && \ |
326 |
die "versionator compare bug [numbers, ${ver_a}, ${ver_b}]" |
327 |
die "versionator compare bug [numbers, ${ver_a}, ${ver_b}]" |
327 |
|
328 |
|
|
|
329 |
# Store the current index to test later |
330 |
prev_idx_a=$cur_idx_a |
331 |
prev_idx_b=$cur_idx_b |
332 |
|
328 |
# grab the current number components |
333 |
# grab the current number components |
329 |
local cur_tok_a=${parts_a[${cur_idx_a}]} |
334 |
cur_tok_a=${parts_a[cur_idx_a]} |
330 |
local cur_tok_b=${parts_b[${cur_idx_b}]} |
335 |
cur_tok_b=${parts_b[cur_idx_b]} |
331 |
|
336 |
|
332 |
# number? |
337 |
# number? |
333 |
if [[ -n ${cur_tok_a} ]] && [[ -z ${cur_tok_a//[[:digit:]]} ]] ; then |
338 |
if [[ -n ${cur_tok_a} ]] && [[ -z ${cur_tok_a//[[:digit:]]} ]] ; then |
334 |
cur_idx_a=$(( ${cur_idx_a} + 1 )) |
339 |
(( cur_idx_a++ )) |
335 |
[[ ${parts_a[${cur_idx_a}]} == "." ]] \ |
340 |
[[ ${parts_a[cur_idx_a]} == "." ]] \ |
336 |
&& cur_idx_a=$(( ${cur_idx_a} + 1 )) |
341 |
&& (( cur_idx_a++ )) |
337 |
else |
342 |
else |
338 |
cur_tok_a="" |
343 |
cur_tok_a="" |
339 |
fi |
344 |
fi |
340 |
|
345 |
|
341 |
if [[ -n ${cur_tok_b} ]] && [[ -z ${cur_tok_b//[[:digit:]]} ]] ; then |
346 |
if [[ -n ${cur_tok_b} ]] && [[ -z ${cur_tok_b//[[:digit:]]} ]] ; then |
342 |
cur_idx_b=$(( ${cur_idx_b} + 1 )) |
347 |
(( cur_idx_b++ )) |
343 |
[[ ${parts_b[${cur_idx_b}]} == "." ]] \ |
348 |
[[ ${parts_b[cur_idx_b]} == "." ]] \ |
344 |
&& cur_idx_b=$(( ${cur_idx_b} + 1 )) |
349 |
&& (( cur_idx_b++ )) |
345 |
else |
350 |
else |
346 |
cur_tok_b="" |
351 |
cur_tok_b="" |
347 |
fi |
352 |
fi |
348 |
|
353 |
|
349 |
# done with number components? |
354 |
# done with number components? |
350 |
[[ -z ${cur_tok_a} ]] && [[ -z ${cur_tok_b} ]] && break |
355 |
[[ -z ${cur_tok_a} && -z ${cur_tok_b} ]] && break |
351 |
|
356 |
|
352 |
# to avoid going into octal mode, strip any leading zeros. otherwise |
357 |
# if a component is blank, then it is the lesser value |
353 |
# bash will throw a hissy fit on versions like 6.3.068. |
358 |
[[ -z ${cur_tok_a} ]] && eshopts_pop && return 1 |
354 |
cur_tok_a=${cur_tok_a##+(0)} |
359 |
[[ -z ${cur_tok_b} ]] && eshopts_pop && return 3 |
355 |
cur_tok_b=${cur_tok_b##+(0)} |
360 |
|
356 |
|
361 |
# According to PMS, if we are *not* in the first number part, and either |
357 |
# if a component is blank, make it zero. |
362 |
# token begins with "0", then we use a different algorithm (that |
358 |
[[ -z ${cur_tok_a} ]] && cur_tok_a=0 |
363 |
# effectively does floating point comparison) |
359 |
[[ -z ${cur_tok_b} ]] && cur_tok_b=0 |
364 |
if [[ ${prev_idx_a} != 0 && ${prev_idx_b} != 0 ]] \ |
360 |
|
365 |
&& [[ ${cur_tok_a} == 0* || ${cur_tok_b} == 0* ]] ; then |
361 |
# compare |
366 |
|
362 |
[[ ${cur_tok_a} -lt ${cur_tok_b} ]] && eshopts_pop && return 1 |
367 |
# strip trailing zeros |
363 |
[[ ${cur_tok_a} -gt ${cur_tok_b} ]] && eshopts_pop && return 3 |
368 |
cur_tok_a=${cur_tok_a%%+(0)} |
|
|
369 |
cur_tok_b=${cur_tok_b%%+(0)} |
370 |
|
371 |
# do a *string* comparison of the resulting values: 2 > 11 |
372 |
[[ ${cur_tok_a} < ${cur_tok_b} ]] && eshopts_pop && return 1 |
373 |
[[ ${cur_tok_a} > ${cur_tok_b} ]] && eshopts_pop && return 3 |
374 |
else |
375 |
# to avoid going into octal mode, strip any leading zeros. otherwise |
376 |
# bash will throw a hissy fit on versions like 6.3.068. |
377 |
cur_tok_a=${cur_tok_a##+(0)} |
378 |
cur_tok_b=${cur_tok_b##+(0)} |
379 |
|
380 |
# now if a component is blank, it was originally 0 -- make it so |
381 |
: ${cur_tok_a:=0} |
382 |
: ${cur_tok_b:=0} |
383 |
|
384 |
# compare |
385 |
(( cur_tok_a < cur_tok_b )) && eshopts_pop && return 1 |
386 |
(( cur_tok_a > cur_tok_b )) && eshopts_pop && return 3 |
387 |
fi |
364 |
done |
388 |
done |
365 |
|
389 |
|
366 |
### number parts equal. compare letter parts. |
390 |
### number parts equal. compare letter parts. |
367 |
local letter_a= |
391 |
local letter_a= |
368 |
letter_a=${parts_a[${cur_idx_a}]} |
392 |
letter_a=${parts_a[cur_idx_a]} |
369 |
if [[ ${#letter_a} -eq 1 ]] && [[ -z ${letter_a/[a-z]} ]] ; then |
393 |
if [[ ${#letter_a} -eq 1 ]] && [[ -z ${letter_a/[a-z]} ]] ; then |
370 |
cur_idx_a=$(( ${cur_idx_a} + 1 )) |
394 |
(( cur_idx_a++ )) |
371 |
else |
395 |
else |
372 |
letter_a="@" |
396 |
letter_a="@" |
373 |
fi |
397 |
fi |
374 |
|
398 |
|
375 |
local letter_b= |
399 |
local letter_b= |
376 |
letter_b=${parts_b[${cur_idx_b}]} |
400 |
letter_b=${parts_b[cur_idx_b]} |
377 |
if [[ ${#letter_b} -eq 1 ]] && [[ -z ${letter_b/[a-z]} ]] ; then |
401 |
if [[ ${#letter_b} -eq 1 ]] && [[ -z ${letter_b/[a-z]} ]] ; then |
378 |
cur_idx_b=$(( ${cur_idx_b} + 1 )) |
402 |
(( cur_idx_b++ )) |
379 |
else |
403 |
else |
380 |
letter_b="@" |
404 |
letter_b="@" |
381 |
fi |
405 |
fi |
Lines 385-422
version_compare() {
Link Here
|
385 |
[[ ${letter_a} > ${letter_b} ]] && eshopts_pop && return 3 |
409 |
[[ ${letter_a} > ${letter_b} ]] && eshopts_pop && return 3 |
386 |
|
410 |
|
387 |
### letter parts equal. compare suffixes in order. |
411 |
### letter parts equal. compare suffixes in order. |
388 |
local suffix rule part r_lt r_gt |
412 |
inf_loop=0 |
389 |
for rule in "alpha=1" "beta=1" "pre=1" "rc=1" "p=3" "r=3" ; do |
413 |
while true ; do |
390 |
suffix=${rule%%=*} |
414 |
(( inf_loop++ )) |
391 |
r_lt=${rule##*=} |
415 |
(( inf_loop > 20 )) && \ |
392 |
[[ ${r_lt} -eq 1 ]] && r_gt=3 || r_gt=1 |
416 |
die "versionator compare bug [numbers, ${ver_a}, ${ver_b}]" |
393 |
|
417 |
[[ ${parts_a[cur_idx_a]} == "_" ]] && (( cur_idx_a++ )) |
394 |
local suffix_a= |
418 |
[[ ${parts_b[cur_idx_b]} == "_" ]] && (( cur_idx_b++ )) |
395 |
for part in ${parts_a[@]} ; do |
|
|
396 |
[[ ${part#${suffix}} != ${part} ]] && \ |
397 |
[[ -z ${part##${suffix}*([[:digit:]])} ]] && \ |
398 |
suffix_a=${part#${suffix}}0 |
399 |
done |
400 |
|
419 |
|
401 |
local suffix_b= |
420 |
cur_tok_a=${parts_a[cur_idx_a]} |
402 |
for part in ${parts_b[@]} ; do |
421 |
cur_tok_b=${parts_b[cur_idx_b]} |
403 |
[[ ${part#${suffix}} != ${part} ]] && \ |
422 |
local num_part_a=0 |
404 |
[[ -z ${part##${suffix}*([[:digit:]])} ]] && \ |
423 |
local num_part_b=0 |
405 |
suffix_b=${part#${suffix}}0 |
424 |
|
406 |
done |
425 |
if has ${cur_tok_a%%+([0-9])} "alpha" "beta" "pre" "rc" "p"; then |
|
|
426 |
(( cur_idx_a++)) |
427 |
num_part_a=${cur_tok_a##+([a-z])} |
428 |
# I don't like octal |
429 |
num_part_a=${num_part_a##+(0)} |
430 |
: ${num_part_a:=0} |
431 |
cur_tok_a=${cur_tok_a%%+([0-9])} |
432 |
else |
433 |
cur_tok_a="" |
434 |
fi |
435 |
|
436 |
if has ${cur_tok_b%%+([0-9])} alpha beta pre rc p; then |
437 |
(( cur_idx_b++)) |
438 |
num_part_b=${cur_tok_b##+([a-z])} |
439 |
# I still don't like octal |
440 |
num_part_b=${num_part_b##+(0)} |
441 |
: ${num_part_b:=0} |
442 |
cur_tok_b=${cur_tok_b%%+([0-9])} |
443 |
else |
444 |
cur_tok_b="" |
445 |
fi |
407 |
|
446 |
|
408 |
[[ -z ${suffix_a} ]] && [[ -z ${suffix_b} ]] && continue |
447 |
if [[ ${cur_tok_a} != ${cur_tok_b} ]]; then |
|
|
448 |
local suffix |
449 |
for suffix in alpha beta pre rc "" p; do |
450 |
[[ ${cur_tok_a} == ${suffix} ]] && eshopts_pop && return 1 |
451 |
[[ ${cur_tok_b} == ${suffix} ]] && eshopts_pop && return 3 |
452 |
done |
453 |
elif [[ -z ${cur_tok_a} && -z ${cur_tok_b} ]]; then |
454 |
break |
455 |
else |
456 |
(( num_part_a < num_part_b )) && eshopts_pop && return 1 |
457 |
(( num_part_a > num_part_b )) && eshopts_pop && return 3 |
458 |
fi |
459 |
done |
409 |
|
460 |
|
410 |
[[ -z ${suffix_a} ]] && eshopts_pop && return ${r_gt} |
461 |
# At this point, the only thing that should be left is the -r# part |
411 |
[[ -z ${suffix_b} ]] && eshopts_pop && return ${r_lt} |
462 |
[[ ${parts_a[cur_idx_a]} == "-" ]] && (( cur_idx_a++ )) |
|
|
463 |
[[ ${parts_b[cur_idx_b]} == "-" ]] && (( cur_idx_b++ )) |
464 |
|
465 |
# Sanity check |
466 |
if [[ -n ${parts_a[cur_idx_a]} && ${parts_a[cur_idx_a]} != r+([0-9]) ]] || \ |
467 |
[[ -n ${parts_b[cur_idx_b]} && ${parts_b[cur_idx_b]} != r+([0-9]) ]]; then |
468 |
die "versionator compare bug [numbers ${ver_a}, ${ver_b}]" |
469 |
fi |
412 |
|
470 |
|
413 |
# avoid octal problems |
471 |
num_part_a=${parts_a[cur_idx_a]#r} |
414 |
suffix_a=${suffix_a##+(0)} ; suffix_a=${suffix_a:-0} |
472 |
num_part_a=${num_part_a##+(0)} |
415 |
suffix_b=${suffix_b##+(0)} ; suffix_b=${suffix_b:-0} |
473 |
: ${num_part_a:=0} |
|
|
474 |
num_part_b=${parts_b[cur_idx_b]#r} |
475 |
num_part_b=${num_part_b##+(0)} |
476 |
: ${num_part_b:=0} |
416 |
|
477 |
|
417 |
[[ ${suffix_a} -lt ${suffix_b} ]] && eshopts_pop && return 1 |
478 |
(( num_part_a < num_part_b )) && eshopts_pop && return 1 |
418 |
[[ ${suffix_a} -gt ${suffix_b} ]] && eshopts_pop && return 3 |
479 |
(( num_part_a > num_part_b )) && eshopts_pop && return 3 |
419 |
done |
|
|
420 |
|
480 |
|
421 |
### no differences. |
481 |
### no differences. |
422 |
eshopts_pop |
482 |
eshopts_pop |
Lines 470-475
version_format_string() {
Link Here
|
470 |
|
530 |
|
471 |
__versionator__test_version_compare() { |
531 |
__versionator__test_version_compare() { |
472 |
eshopts_push -s extglob |
532 |
eshopts_push -s extglob |
|
|
533 |
|
473 |
local lt=1 eq=2 gt=3 p q |
534 |
local lt=1 eq=2 gt=3 p q |
474 |
|
535 |
|
475 |
__versionator__test_version_compare_t() { |
536 |
__versionator__test_version_compare_t() { |
Lines 507-513
__versionator__test_version_compare() {
Link Here
|
507 |
1.2.3 $lt 1.2.4 |
568 |
1.2.3 $lt 1.2.4 |
508 |
1.2.4 $gt 1.2.3 |
569 |
1.2.4 $gt 1.2.3 |
509 |
|
570 |
|
510 |
1.2.0 $eq 1.2 |
571 |
1.2.0 $gt 1.2 |
511 |
1.2.1 $gt 1.2 |
572 |
1.2.1 $gt 1.2 |
512 |
1.2 $lt 1.2.1 |
573 |
1.2 $lt 1.2.1 |
513 |
|
574 |
|
Lines 531-537
__versionator__test_version_compare() {
Link Here
|
531 |
1.0_alpha6-r1 $gt 1.0_alpha6 |
592 |
1.0_alpha6-r1 $gt 1.0_alpha6 |
532 |
1.0_beta6-r1 $gt 1.0_alpha6-r2 |
593 |
1.0_beta6-r1 $gt 1.0_alpha6-r2 |
533 |
|
594 |
|
534 |
1.0_pre1 $lt 1.0-p1 |
595 |
1.0_pre1 $lt 1.0_p1 |
535 |
|
596 |
|
536 |
1.0p $gt 1.0_p1 |
597 |
1.0p $gt 1.0_p1 |
537 |
1.0r $gt 1.0-r1 |
598 |
1.0r $gt 1.0-r1 |
Lines 544-550
__versionator__test_version_compare() {
Link Here
|
544 |
done |
605 |
done |
545 |
|
606 |
|
546 |
|
607 |
|
547 |
for q in "alpha beta pre rc=${lt};${gt}" "p r=${gt};${lt}" ; do |
608 |
for q in "alpha beta pre rc=${lt};${gt}" "p=${gt};${lt}" ; do |
548 |
for p in ${q%%=*} ; do |
609 |
for p in ${q%%=*} ; do |
549 |
local c=${q##*=} |
610 |
local c=${q##*=} |
550 |
local alt=${c%%;*} agt=${c##*;} |
611 |
local alt=${c%%;*} agt=${c##*;} |
Lines 564-569
__versionator__test_version_compare() {
Link Here
|
564 |
__versionator__test_version_compare_t "1_${p}7" $eq "1_${p}7" |
625 |
__versionator__test_version_compare_t "1_${p}7" $eq "1_${p}7" |
565 |
__versionator__test_version_compare_t "1_${p}7" $gt "1_${p}6" |
626 |
__versionator__test_version_compare_t "1_${p}7" $gt "1_${p}6" |
566 |
__versionator__test_version_compare_t "1_${p}09" $eq "1_${p}9" |
627 |
__versionator__test_version_compare_t "1_${p}09" $eq "1_${p}9" |
|
|
628 |
|
629 |
__versionator__test_version_compare_t "1_${p}7-r0" $eq "1_${p}7" |
630 |
__versionator__test_version_compare_t "1_${p}7-r0" $lt "1_${p}7-r1" |
631 |
__versionator__test_version_compare_t "1_${p}7-r0" $lt "1_${p}7-r01" |
632 |
__versionator__test_version_compare_t "1_${p}7-r01" $eq "1_${p}7-r1" |
633 |
__versionator__test_version_compare_t "1_${p}8-r1" $gt "1_${p}7-r100" |
634 |
|
635 |
__versionator__test_version_compare_t "1_${p}_alpha" $lt "1_${p}_beta" |
567 |
done |
636 |
done |
568 |
done |
637 |
done |
569 |
|
638 |
|
Lines 573-577
__versionator__test_version_compare() {
Link Here
|
573 |
__versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2" |
642 |
__versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2" |
574 |
__versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3" |
643 |
__versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3" |
575 |
done |
644 |
done |
|
|
645 |
|
646 |
# The following tests all come from portage's test cases: |
647 |
__versionator__test_version_compare_t "6.0" $gt "5.0" |
648 |
__versionator__test_version_compare_t "5.0" $gt "5" |
649 |
__versionator__test_version_compare_t "1.0-r1" $gt "1.0-r0" |
650 |
__versionator__test_version_compare_t "1.0-r1" $gt "1.0" |
651 |
__versionator__test_version_compare_t "999999999999999999999999999999" $gt "999999999999999999999999999998" |
652 |
__versionator__test_version_compare_t "1.0.0" $gt "1.0" |
653 |
__versionator__test_version_compare_t "1.0.0" $gt "1.0b" |
654 |
__versionator__test_version_compare_t "1b" $gt "1" |
655 |
__versionator__test_version_compare_t "1b_p1" $gt "1_p1" |
656 |
__versionator__test_version_compare_t "1.1b" $gt "1.1" |
657 |
__versionator__test_version_compare_t "12.2.5" $gt "12.2b" |
658 |
|
659 |
__versionator__test_version_compare_t "4.0" $lt "5.0" |
660 |
__versionator__test_version_compare_t "5" $lt "5.0" |
661 |
__versionator__test_version_compare_t "1.0_pre2" $lt "1.0_p2" |
662 |
__versionator__test_version_compare_t "1.0_alpha2" $lt "1.0_p2" |
663 |
__versionator__test_version_compare_t "1.0_alpha1" $lt "1.0_beta1" |
664 |
__versionator__test_version_compare_t "1.0_beta3" $lt "1.0_rc3" |
665 |
__versionator__test_version_compare_t "1.001000000000000000001" $lt "1.001000000000000000002" |
666 |
__versionator__test_version_compare_t "1.00100000000" $lt "1.0010000000000000001" |
667 |
__versionator__test_version_compare_t "999999999999999999999999999998" $lt "999999999999999999999999999999" |
668 |
__versionator__test_version_compare_t "1.01" $lt "1.1" |
669 |
__versionator__test_version_compare_t "1.0-r0" $lt "1.0-r1" |
670 |
__versionator__test_version_compare_t "1.0" $lt "1.0-r1" |
671 |
__versionator__test_version_compare_t "1.0" $lt "1.0.0" |
672 |
__versionator__test_version_compare_t "1.0b" $lt "1.0.0" |
673 |
__versionator__test_version_compare_t "1_p1" $lt "1b_p1" |
674 |
__versionator__test_version_compare_t "1" $lt "1b" |
675 |
__versionator__test_version_compare_t "1.1" $lt "1.1b" |
676 |
__versionator__test_version_compare_t "12.2b" $lt "12.2.5" |
677 |
|
678 |
__versionator__test_version_compare_t "4.0" $eq "4.0" |
679 |
__versionator__test_version_compare_t "1.0" $eq "1.0" |
680 |
__versionator__test_version_compare_t "1.0-r0" $eq "1.0" |
681 |
__versionator__test_version_compare_t "1.0" $eq "1.0-r0" |
682 |
__versionator__test_version_compare_t "1.0-r0" $eq "1.0-r0" |
683 |
__versionator__test_version_compare_t "1.0-r1" $eq "1.0-r1" |
684 |
|
685 |
# The following were just tests for != in portage, we need something a bit |
686 |
# more precise |
687 |
__versionator__test_version_compare_t "1" $lt "2" |
688 |
__versionator__test_version_compare_t "1.0_alpha" $lt "1.0_pre" |
689 |
__versionator__test_version_compare_t "1.0_beta" $gt "1.0_alpha" |
690 |
__versionator__test_version_compare_t "0" $lt "0.0" |
691 |
__versionator__test_version_compare_t "1.0-r0" $lt "1.0-r1" |
692 |
__versionator__test_version_compare_t "1.0-r1" $gt "1.0-r0" |
693 |
__versionator__test_version_compare_t "1.0" $lt "1.0-r1" |
694 |
__versionator__test_version_compare_t "1.0-r1" $gt "1.0" |
695 |
__versionator__test_version_compare_t "1_p1" $lt "1b_p1" |
696 |
__versionator__test_version_compare_t "1b" $gt "1" |
697 |
__versionator__test_version_compare_t "1.1b" $gt "1.1" |
698 |
__versionator__test_version_compare_t "12.2b" $gt "12.2" |
699 |
|
700 |
# The following tests all come from paludis's test cases: |
701 |
__versionator__test_version_compare_t "1.0" $gt "1" |
702 |
__versionator__test_version_compare_t "1" $lt "1.0" |
703 |
__versionator__test_version_compare_t "1.0_alpha" $gt "1_alpha" |
704 |
__versionator__test_version_compare_t "1.0_alpha" $gt "1" |
705 |
__versionator__test_version_compare_t "1.0_alpha" $lt "1.0" |
706 |
__versionator__test_version_compare_t "1.2.0.0_alpha7-r4" $gt "1.2_alpha7-r4" |
707 |
|
708 |
__versionator__test_version_compare_t "0001" $eq "1" |
709 |
__versionator__test_version_compare_t "01" $eq "001" |
710 |
__versionator__test_version_compare_t "0001.1" $eq "1.1" |
711 |
__versionator__test_version_compare_t "01.01" $eq "1.01" |
712 |
__versionator__test_version_compare_t "1.010" $eq "1.01" |
713 |
__versionator__test_version_compare_t "1.00" $eq "1.0" |
714 |
__versionator__test_version_compare_t "1.0100" $eq "1.010" |
715 |
__versionator__test_version_compare_t "1" $eq "1-r0" |
716 |
__versionator__test_version_compare_t "1-r00" $eq "1-r0" |
717 |
|
576 |
eshopts_pop |
718 |
eshopts_pop |
577 |
} |
719 |
} |