|
| 1 | +# Copyright 1999-2021 Gentoo Authors |
| 2 | +# Distributed under the terms of the GNU General Public License v2 |
| 3 | + |
| 4 | +# @AUTHOR: |
| 5 | +# Ulrich Müller <[email protected]> |
| 6 | +# Michał Górny <[email protected]> |
| 7 | + |
| 8 | +# It is a cut-down and modified version of the now-gone eapi7-ver.eclass. |
| 9 | + |
| 10 | +if [[ -z ${__GENTOO_VER_SH_INCLUDED__:-} ]]; then |
| 11 | +__GENTOO_VER_SH_INCLUDED__=x |
| 12 | + |
| 13 | +source "$(dirname "${BASH_SOURCE[0]}")/util.sh" |
| 14 | + |
| 15 | +VER_ERE="^([0-9]+(\.[0-9]+)*)([a-z]?)((_(alpha|beta|pre|rc|p)[0-9]*)*)(-r[0-9]+)?$" |
| 16 | + |
| 17 | +# @FUNCTION: _ver_compare_int |
| 18 | +# @USAGE: <a> <b> |
| 19 | +# @RETURN: 0 if <a> -eq <b>, 1 if <a> -lt <b>, 3 if <a> -gt <b> |
| 20 | +# @INTERNAL |
| 21 | +# @DESCRIPTION: |
| 22 | +# Compare two non-negative integers <a> and <b>, of arbitrary length. |
| 23 | +# If <a> is equal to, less than, or greater than <b>, return 0, 1, or 3 |
| 24 | +# as exit status, respectively. |
| 25 | +_ver_compare_int() { |
| 26 | + local a=$1 b=$2 d=$(( ${#1}-${#2} )) |
| 27 | + |
| 28 | + # Zero-pad to equal length if necessary. |
| 29 | + if [[ ${d} -gt 0 ]]; then |
| 30 | + printf -v b "%0${d}d%s" 0 "${b}" |
| 31 | + elif [[ ${d} -lt 0 ]]; then |
| 32 | + printf -v a "%0$(( -d ))d%s" 0 "${a}" |
| 33 | + fi |
| 34 | + |
| 35 | + [[ ${a} > ${b} ]] && return 3 |
| 36 | + [[ ${a} == "${b}" ]] |
| 37 | +} |
| 38 | + |
| 39 | +# @FUNCTION: _ver_compare |
| 40 | +# @USAGE: <va> <vb> |
| 41 | +# @RETURN: 1 if <va> < <vb>, 2 if <va> = <vb>, 3 if <va> > <vb> |
| 42 | +# @INTERNAL |
| 43 | +# @DESCRIPTION: |
| 44 | +# Compare two versions <va> and <vb>. If <va> is less than, equal to, |
| 45 | +# or greater than <vb>, return 1, 2, or 3 as exit status, respectively. |
| 46 | +_ver_compare() { |
| 47 | + local va=${1} vb=${2} a an al as ar b bn bl bs br re LC_ALL=C |
| 48 | + |
| 49 | + re=${VER_ERE} |
| 50 | + |
| 51 | + [[ ${va} =~ ${re} ]] || fail "${FUNCNAME}: invalid version: ${va}" |
| 52 | + an=${BASH_REMATCH[1]} |
| 53 | + al=${BASH_REMATCH[3]} |
| 54 | + as=${BASH_REMATCH[4]} |
| 55 | + ar=${BASH_REMATCH[7]} |
| 56 | + |
| 57 | + [[ ${vb} =~ ${re} ]] || fail "${FUNCNAME}: invalid version: ${vb}" |
| 58 | + bn=${BASH_REMATCH[1]} |
| 59 | + bl=${BASH_REMATCH[3]} |
| 60 | + bs=${BASH_REMATCH[4]} |
| 61 | + br=${BASH_REMATCH[7]} |
| 62 | + |
| 63 | + # Compare numeric components (PMS algorithm 3.2) |
| 64 | + # First component |
| 65 | + _ver_compare_int "${an%%.*}" "${bn%%.*}" || return |
| 66 | + |
| 67 | + while [[ ${an} == *.* && ${bn} == *.* ]]; do |
| 68 | + # Other components (PMS algorithm 3.3) |
| 69 | + an=${an#*.} |
| 70 | + bn=${bn#*.} |
| 71 | + a=${an%%.*} |
| 72 | + b=${bn%%.*} |
| 73 | + if [[ ${a} == 0* || ${b} == 0* ]]; then |
| 74 | + # Remove any trailing zeros |
| 75 | + [[ ${a} =~ 0+$ ]] && a=${a%"${BASH_REMATCH[0]}"} |
| 76 | + [[ ${b} =~ 0+$ ]] && b=${b%"${BASH_REMATCH[0]}"} |
| 77 | + [[ ${a} > ${b} ]] && return 3 |
| 78 | + [[ ${a} < ${b} ]] && return 1 |
| 79 | + else |
| 80 | + _ver_compare_int "${a}" "${b}" || return |
| 81 | + fi |
| 82 | + done |
| 83 | + [[ ${an} == *.* ]] && return 3 |
| 84 | + [[ ${bn} == *.* ]] && return 1 |
| 85 | + |
| 86 | + # Compare letter components (PMS algorithm 3.4) |
| 87 | + [[ ${al} > ${bl} ]] && return 3 |
| 88 | + [[ ${al} < ${bl} ]] && return 1 |
| 89 | + |
| 90 | + # Compare suffixes (PMS algorithm 3.5) |
| 91 | + as=${as#_}${as:+_} |
| 92 | + bs=${bs#_}${bs:+_} |
| 93 | + while [[ -n ${as} && -n ${bs} ]]; do |
| 94 | + # Compare each suffix (PMS algorithm 3.6) |
| 95 | + a=${as%%_*} |
| 96 | + b=${bs%%_*} |
| 97 | + if [[ ${a%%[0-9]*} == "${b%%[0-9]*}" ]]; then |
| 98 | + _ver_compare_int "${a##*[a-z]}" "${b##*[a-z]}" || return |
| 99 | + else |
| 100 | + # Check for p first |
| 101 | + [[ ${a%%[0-9]*} == p ]] && return 3 |
| 102 | + [[ ${b%%[0-9]*} == p ]] && return 1 |
| 103 | + # Hack: Use that alpha < beta < pre < rc alphabetically |
| 104 | + [[ ${a} > ${b} ]] && return 3 || return 1 |
| 105 | + fi |
| 106 | + as=${as#*_} |
| 107 | + bs=${bs#*_} |
| 108 | + done |
| 109 | + if [[ -n ${as} ]]; then |
| 110 | + [[ ${as} == p[_0-9]* ]] && return 3 || return 1 |
| 111 | + elif [[ -n ${bs} ]]; then |
| 112 | + [[ ${bs} == p[_0-9]* ]] && return 1 || return 3 |
| 113 | + fi |
| 114 | + |
| 115 | + # Compare revision components (PMS algorithm 3.7) |
| 116 | + _ver_compare_int "${ar#-r}" "${br#-r}" || return |
| 117 | + |
| 118 | + return 2 |
| 119 | +} |
| 120 | + |
| 121 | +# symbolic names for use with gentoo_ver_cmp_out |
| 122 | +GV_LT=1 |
| 123 | +GV_EQ=2 |
| 124 | +GV_GT=3 |
| 125 | + |
| 126 | +# Compare two versions. The result can be compared against GV_LT, GV_EQ and GV_GT variables. |
| 127 | +# |
| 128 | +# Params: |
| 129 | +# |
| 130 | +# 1 - version 1 |
| 131 | +# 2 - version 2 |
| 132 | +# 3 - name of variable to store the result in |
| 133 | +function gentoo_ver_cmp_out() { |
| 134 | + local v1 v2 |
| 135 | + v1=${1}; shift |
| 136 | + v2=${1}; shift |
| 137 | + local -n out_ref=${1}; shift |
| 138 | + |
| 139 | + out_ref=0 |
| 140 | + _ver_compare "${v1}" "${v2}" || out_ref=${?} |
| 141 | + case ${out_ref} in |
| 142 | + 1|2|3) |
| 143 | + return 0 |
| 144 | + ;; |
| 145 | + *) |
| 146 | + fail "unexpected return value ${out_ref} from _ver_compare for ${v1} and ${v2}" |
| 147 | + ;; |
| 148 | + esac |
| 149 | +} |
| 150 | + |
| 151 | +fi |
0 commit comments