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

Diff of /eclass/versionator.eclass

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

Revision 1.11 Revision 1.12
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.11 2006/08/30 16:14:13 spb Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/versionator.eclass,v 1.12 2007/01/10 05:49:10 antarus 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
34# 34#
35# There's also: 35# There's also:
36# version_is_at_least want have 36# version_is_at_least want have
37# which may be buggy, so use with caution. 37# which may be buggy, so use with caution.
38 38
39# Quick function to toggle the shopts required for some functions on and off
40# Used because we can't set extglob in global scope anymore (QA Violation)
41__versionator_shopt_toggle() {
42 VERSIONATOR_RECURSION=${VERSIONATOR_RECURSION:-0}
43 case "$1" in
44 "on")
45 if [[ $VERSIONATOR_RECURSION -lt 1 ]] ; then
46 VERSIONATOR_OLD_EXTGLOB=$(shopt -p extglob)
39shopt -s extglob 47 shopt -s extglob
48 fi
49 VERSIONATOR_RECURSION=$(( $VERSIONATOR_RECURSION + 1 ))
50 ;;
51 "off")
52 VERSIONATOR_RECURSION=$(( $VERSIONATOR_RECURSION - 1 ))
53 if [[ $VERSIONATOR_RECURSION -lt 1 ]] ; then
54 eval $VERSIONATOR_OLD_EXTGLOB
55 fi
56 ;;
57 esac
58 return 0
59}
40 60
41# Split up a version string into its component parts. If no parameter is 61# Split up a version string into its component parts. If no parameter is
42# supplied, defaults to $PV. 62# supplied, defaults to $PV.
43# 0.8.3 -> 0 . 8 . 3 63# 0.8.3 -> 0 . 8 . 3
44# 7c -> 7 c 64# 7c -> 7 c
45# 3.0_p2 -> 3 . 0 _ p2 65# 3.0_p2 -> 3 . 0 _ p2
46# 20040905 -> 20040905 66# 20040905 -> 20040905
47# 3.0c-r1 -> 3 . 0 c - r1 67# 3.0c-r1 -> 3 . 0 c - r1
48get_all_version_components() { 68get_all_version_components() {
69 __versionator_shopt_toggle on
49 local ver_str=${1:-${PV}} result result_idx=0 70 local ver_str=${1:-${PV}} result result_idx=0
50 result=( ) 71 result=( )
51 72
52 # sneaky cache trick cache to avoid having to parse the same thing several 73 # sneaky cache trick cache to avoid having to parse the same thing several
53 # times. 74 # times.
54 if [[ "${VERSIONATOR_CACHE_VER_STR}" == "${ver_str}" ]] ; then 75 if [[ "${VERSIONATOR_CACHE_VER_STR}" == "${ver_str}" ]] ; then
55 echo ${VERSIONATOR_CACHE_RESULT} 76 echo ${VERSIONATOR_CACHE_RESULT}
77 __versionator_shopt_toggle off
56 return 78 return
57 fi 79 fi
58 export VERSIONATOR_CACHE_VER_STR="${ver_str}" 80 export VERSIONATOR_CACHE_VER_STR="${ver_str}"
59 81
60 while [[ -n "$ver_str" ]] ; do 82 while [[ -n "$ver_str" ]] ; do
90 esac 112 esac
91 done 113 done
92 114
93 export VERSIONATOR_CACHE_RESULT="${result[@]}" 115 export VERSIONATOR_CACHE_RESULT="${result[@]}"
94 echo ${result[@]} 116 echo ${result[@]}
117 __versionator_shopt_toggle off
95} 118}
96 119
97# Get the important version components, excluding '.', '-' and '_'. Defaults to 120# Get the important version components, excluding '.', '-' and '_'. Defaults to
98# $PV if no parameter is supplied. 121# $PV if no parameter is supplied.
99# 0.8.3 -> 0 8 3 122# 0.8.3 -> 0 8 3
100# 7c -> 7 c 123# 7c -> 7 c
101# 3.0_p2 -> 3 0 p2 124# 3.0_p2 -> 3 0 p2
102# 20040905 -> 20040905 125# 20040905 -> 20040905
103# 3.0c-r1 -> 3 0 c r1 126# 3.0c-r1 -> 3 0 c r1
104get_version_components() { 127get_version_components() {
128 __versionator_shopt_toggle on
105 local c="$(get_all_version_components "${1:-${PV}}")" 129 local c="$(get_all_version_components "${1:-${PV}}")"
106 c=( ${c[@]//[-._]/ } ) 130 c=( ${c[@]//[-._]/ } )
107 echo ${c[@]} 131 echo ${c[@]}
132 __versionator_shopt_toggle off
108} 133}
109 134
110# Get the major version of a value. Defaults to $PV if no parameter is supplied. 135# Get the major version of a value. Defaults to $PV if no parameter is supplied.
111# 0.8.3 -> 0 136# 0.8.3 -> 0
112# 7c -> 7 137# 7c -> 7
113# 3.0_p2 -> 3 138# 3.0_p2 -> 3
114# 20040905 -> 20040905 139# 20040905 -> 20040905
115# 3.0c-r1 -> 3 140# 3.0c-r1 -> 3
116get_major_version() { 141get_major_version() {
142 __versionator_shopt_toggle on
117 local c 143 local c
118 c=( $(get_all_version_components "${1:-${PV}}" ) ) 144 c=( $(get_all_version_components "${1:-${PV}}" ) )
119 echo ${c[0]} 145 echo ${c[0]}
146 __versionator_shopt_toggle off
120} 147}
121 148
122# Get a particular component or range of components from the version. If no 149# Get a particular component or range of components from the version. If no
123# version parameter is supplied, defaults to $PV. 150# version parameter is supplied, defaults to $PV.
124# 1 1.2.3 -> 1 151# 1 1.2.3 -> 1
125# 1-2 1.2.3 -> 1.2 152# 1-2 1.2.3 -> 1.2
126# 2- 1.2.3 -> 2.3 153# 2- 1.2.3 -> 2.3
127get_version_component_range() { 154get_version_component_range() {
155 __versionator_shopt_toggle on
128 local c v="${2:-${PV}}" range="${1}" range_start range_end i=-1 j=0 156 local c v="${2:-${PV}}" range="${1}" range_start range_end i=-1 j=0
129 c=( $(get_all_version_components ${v} ) ) 157 c=( $(get_all_version_components ${v} ) )
130 range_start="${range%-*}" ; range_start="${range_start:-1}" 158 range_start="${range%-*}" ; range_start="${range_start:-1}"
131 range_end="${range#*-}" ; range_end="${range_end:-${#c[@]}}" 159 range_end="${range#*-}" ; range_end="${range_end:-${#c[@]}}"
132 160
133 while (( j < ${range_start} )) ; do 161 while (( j < ${range_start} )) ; do
134 i=$(($i + 1)) 162 i=$(($i + 1))
135 [[ $i -gt ${#c[@]} ]] && return 163 [[ $i -gt ${#c[@]} ]] && __versionator_shopt_toggle off && return
136 [[ -n "${c[${i}]//[-._]}" ]] && j=$(($j + 1)) 164 [[ -n "${c[${i}]//[-._]}" ]] && j=$(($j + 1))
137 done 165 done
138 166
139 while (( j <= ${range_end} )) ; do 167 while (( j <= ${range_end} )) ; do
140 echo -n ${c[$i]} 168 echo -n ${c[$i]}
141 [[ $i -gt ${#c[@]} ]] && return 169 [[ $i -gt ${#c[@]} ]] && __versionator_shopt_toggle off && return
142 [[ -n "${c[${i}]//[-._]}" ]] && j=$(($j + 1)) 170 [[ -n "${c[${i}]//[-._]}" ]] && j=$(($j + 1))
143 i=$(($i + 1)) 171 i=$(($i + 1))
144 done 172 done
173 __versionator_shopt_toggle off
145} 174}
146 175
147# Get everything after the major version and its separator (if present) of a 176# Get everything after the major version and its separator (if present) of a
148# value. Defaults to $PV if no parameter is supplied. 177# value. Defaults to $PV if no parameter is supplied.
149# 0.8.3 -> 8.3 178# 0.8.3 -> 8.3
150# 7c -> c 179# 7c -> c
151# 3.0_p2 -> 0_p2 180# 3.0_p2 -> 0_p2
152# 20040905 -> (empty string) 181# 20040905 -> (empty string)
153# 3.0c-r1 -> 0c-r1 182# 3.0c-r1 -> 0c-r1
154get_after_major_version() { 183get_after_major_version() {
184 __versionator_shopt_toggle on
155 echo $(get_version_component_range 2- "${1:-${PV}}" ) 185 echo $(get_version_component_range 2- "${1:-${PV}}" )
186 __versionator_shopt_toggle off
156} 187}
157 188
158# Replace the $1th separator with $2 in $3 (defaults to $PV if $3 is not 189# Replace the $1th separator with $2 in $3 (defaults to $PV if $3 is not
159# supplied). If there are fewer than $1 separators, don't change anything. 190# supplied). If there are fewer than $1 separators, don't change anything.
160# 1 '_' 1.2.3 -> 1_2.3 191# 1 '_' 1.2.3 -> 1_2.3
161# 2 '_' 1.2.3 -> 1.2_3 192# 2 '_' 1.2.3 -> 1.2_3
162# 1 '_' 1b-2.3 -> 1b_2.3 193# 1 '_' 1b-2.3 -> 1b_2.3
163# Rather than being a number, $1 can be a separator character such as '-', '.' 194# Rather than being a number, $1 can be a separator character such as '-', '.'
164# or '_'. In this case, the first separator of this kind is selected. 195# or '_'. In this case, the first separator of this kind is selected.
165replace_version_separator() { 196replace_version_separator() {
197 __versionator_shopt_toggle on
166 local w i c found=0 v="${3:-${PV}}" 198 local w i c found=0 v="${3:-${PV}}"
167 w=${1:-1} 199 w=${1:-1}
168 c=( $(get_all_version_components ${v} ) ) 200 c=( $(get_all_version_components ${v} ) )
169 if [[ "${w//[[:digit:]]/}" == "${w}" ]] ; then 201 if [[ "${w//[[:digit:]]/}" == "${w}" ]] ; then
170 # it's a character, not an index 202 # it's a character, not an index
185 fi 217 fi
186 done 218 done
187 fi 219 fi
188 c=${c[@]} 220 c=${c[@]}
189 echo ${c// } 221 echo ${c// }
222 __versionator_shopt_toggle off
190} 223}
191 224
192# Replace all version separators in $2 (defaults to $PV) with $1. 225# Replace all version separators in $2 (defaults to $PV) with $1.
193# '_' 1b.2.3 -> 1b_2_3 226# '_' 1b.2.3 -> 1b_2_3
194replace_all_version_separators() { 227replace_all_version_separators() {
228 __versionator_shopt_toggle on
195 local c 229 local c
196 c=( $(get_all_version_components "${2:-${PV}}" ) ) 230 c=( $(get_all_version_components "${2:-${PV}}" ) )
197 c="${c[@]//[-._]/$1}" 231 c="${c[@]//[-._]/$1}"
198 echo ${c// } 232 echo ${c// }
233 __versionator_shopt_toggle off
199} 234}
200 235
201# Delete the $1th separator in $2 (defaults to $PV if $2 is not supplied). If 236# Delete the $1th separator in $2 (defaults to $PV if $2 is not supplied). If
202# there are fewer than $1 separators, don't change anything. 237# there are fewer than $1 separators, don't change anything.
203# 1 1.2.3 -> 12.3 238# 1 1.2.3 -> 12.3
204# 2 1.2.3 -> 1.23 239# 2 1.2.3 -> 1.23
205# 1 1b-2.3 -> 1b2.3 240# 1 1b-2.3 -> 1b2.3
206# Rather than being a number, $1 can be a separator character such as '-', '.' 241# Rather than being a number, $1 can be a separator character such as '-', '.'
207# or '_'. In this case, the first separator of this kind is deleted. 242# or '_'. In this case, the first separator of this kind is deleted.
208delete_version_separator() { 243delete_version_separator() {
244 __versionator_shopt_toggle on
209 replace_version_separator "${1}" "" "${2}" 245 replace_version_separator "${1}" "" "${2}"
246 __versionator_shopt_toggle off
210} 247}
211 248
212# Delete all version separators in $1 (defaults to $PV). 249# Delete all version separators in $1 (defaults to $PV).
213# 1b.2.3 -> 1b23 250# 1b.2.3 -> 1b23
214delete_all_version_separators() { 251delete_all_version_separators() {
252 __versionator_shopt_toggle on
215 replace_all_version_separators "" "${1}" 253 replace_all_version_separators "" "${1}"
254 __versionator_shopt_toggle off
216} 255}
217 256
218# How many version components are there in $1 (defaults to $PV)? 257# How many version components are there in $1 (defaults to $PV)?
219# 1.0.1 -> 3 258# 1.0.1 -> 3
220# 3.0c-r1 -> 4 259# 3.0c-r1 -> 4
221# 260#
222get_version_component_count() { 261get_version_component_count() {
262 __versionator_shopt_toggle on
223 local a 263 local a
224 a=( $(get_version_components "${1:-${PV}}" ) ) 264 a=( $(get_version_components "${1:-${PV}}" ) )
225 echo ${#a[@]} 265 echo ${#a[@]}
266 __versionator_shopt_toggle off
226} 267}
227 268
228# What is the index of the last version component in $1 (defaults to $PV)? 269# What is the index of the last version component in $1 (defaults to $PV)?
229# Equivalent to get_version_component_count - 1. 270# Equivalent to get_version_component_count - 1.
230# 1.0.1 -> 3 271# 1.0.1 -> 3
231# 3.0c-r1 -> 4 272# 3.0c-r1 -> 4
232# 273#
233get_last_version_component_index() { 274get_last_version_component_index() {
275 __versionator_shopt_toggle on
234 echo $(( $(get_version_component_count "${1:-${PV}}" ) - 1 )) 276 echo $(( $(get_version_component_count "${1:-${PV}}" ) - 1 ))
277 __versionator_shopt_toggle off
235} 278}
236 279
237# Is $2 (defaults to $PVR) at least version $1? Intended for use in eclasses 280# Is $2 (defaults to $PVR) at least version $1? Intended for use in eclasses
238# only. May not be reliable, be sure to do very careful testing before actually 281# only. May not be reliable, be sure to do very careful testing before actually
239# using this. Prod ciaranm if you find something it can't handle. 282# using this. Prod ciaranm if you find something it can't handle.
240version_is_at_least() { 283version_is_at_least() {
284 __versionator_shopt_toggle on
241 local want_s="$1" have_s="${2:-${PVR}}" r 285 local want_s="$1" have_s="${2:-${PVR}}" r
242 version_compare "${want_s}" "${have_s}" 286 version_compare "${want_s}" "${have_s}"
243 r=$? 287 r=$?
244 case $r in 288 case $r in
245 1|2) 289 1|2)
290 __versionator_shopt_toggle off
246 return 0 291 return 0
247 ;; 292 ;;
248 3) 293 3)
294 __versionator_shopt_toggle off
249 return 1 295 return 1
250 ;; 296 ;;
251 *) 297 *)
298 __versionator_shopt_toggle off
252 die "versionator compare bug [atleast, ${want_s}, ${have_s}, ${r}]" 299 die "versionator compare bug [atleast, ${want_s}, ${have_s}, ${r}]"
253 ;; 300 ;;
254 esac 301 esac
302 __versionator_shopt_toggle off
255} 303}
256 304
257# Takes two parameters (a, b) which are versions. If a is an earlier version 305# Takes two parameters (a, b) which are versions. If a is an earlier version
258# than b, returns 1. If a is identical to b, return 2. If b is later than a, 306# than b, returns 1. If a is identical to b, return 2. If b is later than a,
259# return 3. You probably want version_is_at_least rather than this function. 307# return 3. You probably want version_is_at_least rather than this function.
260# May not be very reliable. Test carefully before using this. 308# May not be very reliable. Test carefully before using this.
261version_compare() { 309version_compare() {
310 __versionator_shopt_toggle on
262 local ver_a=${1} ver_b=${2} parts_a parts_b cur_idx_a=0 cur_idx_b=0 311 local ver_a=${1} ver_b=${2} parts_a parts_b cur_idx_a=0 cur_idx_b=0
263 parts_a=( $(get_all_version_components "${ver_a}" ) ) 312 parts_a=( $(get_all_version_components "${ver_a}" ) )
264 parts_b=( $(get_all_version_components "${ver_b}" ) ) 313 parts_b=( $(get_all_version_components "${ver_b}" ) )
265 314
266 ### compare number parts. 315 ### compare number parts.
302 # if a component is blank, make it zero. 351 # if a component is blank, make it zero.
303 [[ -z ${cur_tok_a} ]] && cur_tok_a=0 352 [[ -z ${cur_tok_a} ]] && cur_tok_a=0
304 [[ -z ${cur_tok_b} ]] && cur_tok_b=0 353 [[ -z ${cur_tok_b} ]] && cur_tok_b=0
305 354
306 # compare 355 # compare
307 [[ ${cur_tok_a} -lt ${cur_tok_b} ]] && return 1 356 [[ ${cur_tok_a} -lt ${cur_tok_b} ]] && __versionator_shopt_toggle off && return 1
308 [[ ${cur_tok_a} -gt ${cur_tok_b} ]] && return 3 357 [[ ${cur_tok_a} -gt ${cur_tok_b} ]] && __versionator_shopt_toggle off && return 3
309 done 358 done
310 359
311 ### number parts equal. compare letter parts. 360 ### number parts equal. compare letter parts.
312 local letter_a= 361 local letter_a=
313 letter_a=${parts_a[${cur_idx_a}]} 362 letter_a=${parts_a[${cur_idx_a}]}
324 else 373 else
325 letter_b="@" 374 letter_b="@"
326 fi 375 fi
327 376
328 # compare 377 # compare
329 [[ ${letter_a} < ${letter_b} ]] && return 1 378 [[ ${letter_a} < ${letter_b} ]] && __versionator_shopt_toggle off && return 1
330 [[ ${letter_a} > ${letter_b} ]] && return 3 379 [[ ${letter_a} > ${letter_b} ]] && __versionator_shopt_toggle off && return 3
331 380
332 ### letter parts equal. compare suffixes in order. 381 ### letter parts equal. compare suffixes in order.
333 local suffix rule part r_lt r_gt 382 local suffix rule part r_lt r_gt
334 for rule in "alpha=1" "beta=1" "pre=1" "rc=1" "p=3" "r=3" ; do 383 for rule in "alpha=1" "beta=1" "pre=1" "rc=1" "p=3" "r=3" ; do
335 suffix=${rule%%=*} 384 suffix=${rule%%=*}
350 suffix_b=${part#${suffix}}0 399 suffix_b=${part#${suffix}}0
351 done 400 done
352 401
353 [[ -z ${suffix_a} ]] && [[ -z ${suffix_b} ]] && continue 402 [[ -z ${suffix_a} ]] && [[ -z ${suffix_b} ]] && continue
354 403
355 [[ -z ${suffix_a} ]] && return ${r_gt} 404 [[ -z ${suffix_a} ]] && __versionator_shopt_toggle off && return ${r_gt}
356 [[ -z ${suffix_b} ]] && return ${r_lt} 405 [[ -z ${suffix_b} ]] && __versionator_shopt_toggle off && return ${r_lt}
357 406
358 # avoid octal problems 407 # avoid octal problems
359 suffix_a=${suffix_a##+(0)} ; suffix_a=${suffix_a:-0} 408 suffix_a=${suffix_a##+(0)} ; suffix_a=${suffix_a:-0}
360 suffix_b=${suffix_b##+(0)} ; suffix_b=${suffix_b:-0} 409 suffix_b=${suffix_b##+(0)} ; suffix_b=${suffix_b:-0}
361 410
362 [[ ${suffix_a} -lt ${suffix_b} ]] && return 1 411 [[ ${suffix_a} -lt ${suffix_b} ]] && __versionator_shopt_toggle off && return 1
363 [[ ${suffix_a} -gt ${suffix_b} ]] && return 3 412 [[ ${suffix_a} -gt ${suffix_b} ]] && __versionator_shopt_toggle off && return 3
364 done 413 done
365 414
366 ### no differences. 415 ### no differences.
416 __versionator_shopt_toggle off
367 return 2 417 return 2
368} 418}
369 419
370# Returns its parameters sorted, highest version last. We're using a quadratic 420# Returns its parameters sorted, highest version last. We're using a quadratic
371# algorithm for simplicity, so don't call it with more than a few dozen items. 421# algorithm for simplicity, so don't call it with more than a few dozen items.
372# Uses version_compare, so be careful. 422# Uses version_compare, so be careful.
373version_sort() { 423version_sort() {
424 __versionator_shopt_toggle on
374 local items= left=0 425 local items= left=0
375 items=( $@ ) 426 items=( $@ )
376 while [[ ${left} -lt ${#items[@]} ]] ; do 427 while [[ ${left} -lt ${#items[@]} ]] ; do
377 local lowest_idx=${left} 428 local lowest_idx=${left}
378 local idx=$(( ${lowest_idx} + 1 )) 429 local idx=$(( ${lowest_idx} + 1 ))
385 items[${lowest_idx}]=${items[${left}]} 436 items[${lowest_idx}]=${items[${left}]}
386 items[${left}]=${tmp} 437 items[${left}]=${tmp}
387 left=$(( ${left} + 1 )) 438 left=$(( ${left} + 1 ))
388 done 439 done
389 echo ${items[@]} 440 echo ${items[@]}
441 __versionator_shopt_toggle off
390} 442}
391 443
392__versionator__test_version_compare() { 444__versionator__test_version_compare() {
445 __versionator_shopt_toggle on
393 local lt=1 eq=2 gt=3 p q 446 local lt=1 eq=2 gt=3 p q
394 447
395 __versionator__test_version_compare_t() { 448 __versionator__test_version_compare_t() {
396 version_compare "${1}" "${3}" 449 version_compare "${1}" "${3}"
397 local r=$? 450 local r=$?
491 __versionator__test_version_compare_t "7.2${p}1" $lt "7.2${p}2" 544 __versionator__test_version_compare_t "7.2${p}1" $lt "7.2${p}2"
492 __versionator__test_version_compare_t "7.2${p}2" $gt "7.2${p}1" 545 __versionator__test_version_compare_t "7.2${p}2" $gt "7.2${p}1"
493 __versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2" 546 __versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2"
494 __versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3" 547 __versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3"
495 done 548 done
496 549 __versionator_shopt_toggle off
497} 550}
498 551

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12

  ViewVC Help
Powered by ViewVC 1.1.20