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

Diff of /eclass/versionator.eclass

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

Revision 1.1 Revision 1.1.1.1
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.1 2004/09/10 18:45:01 ciaranm Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/versionator.eclass,v 1.1.1.1 2005/11/30 09:59:28 chriswhite 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
21# get_major_version ver_str 21# get_major_version ver_str
22# get_version_component_range range ver_str 22# get_version_component_range range ver_str
23# get_after_major_version ver_str 23# get_after_major_version ver_str
24# replace_version_separator index newvalue ver_str 24# replace_version_separator index newvalue ver_str
25# replace_all_version_separators newvalue ver_str 25# replace_all_version_separators newvalue ver_str
26# delete_version_separator index ver_str
27# delete_all_version_separators ver_str
28#
29# Rather than being a number, the index parameter can be a separator character
30# such as '-', '.' or '_'. In this case, the first separator of this kind is
31# selected.
32#
33# There's also:
34# version_is_at_least want have
35# which may be buggy, so use with caution.
26 36
27ECLASS=versionator
28INHERITED="$INHERITED $ECLASS"
29 37
30shopt -s extglob 38shopt -s extglob
31 39
32# Split up a version string into its component parts. If no parameter is 40# Split up a version string into its component parts. If no parameter is
33# supplied, defaults to $PV. 41# supplied, defaults to $PV.
149# Replace the $1th separator with $2 in $3 (defaults to $PV if $3 is not 157# Replace the $1th separator with $2 in $3 (defaults to $PV if $3 is not
150# supplied). If there are fewer than $1 separators, don't change anything. 158# supplied). If there are fewer than $1 separators, don't change anything.
151# 1 '_' 1.2.3 -> 1_2.3 159# 1 '_' 1.2.3 -> 1_2.3
152# 2 '_' 1.2.3 -> 1.2_3 160# 2 '_' 1.2.3 -> 1.2_3
153# 1 '_' 1b-2.3 -> 1b_2.3 161# 1 '_' 1b-2.3 -> 1b_2.3
162# Rather than being a number, $1 can be a separator character such as '-', '.'
163# or '_'. In this case, the first separator of this kind is selected.
154replace_version_separator() { 164replace_version_separator() {
155 local i c found=0 v="${3:-${PV}}" 165 local w i c found=0 v="${3:-${PV}}"
166 w=${1:-1}
156 c=( $(get_all_version_components ${v} ) ) 167 c=( $(get_all_version_components ${v} ) )
168 if [[ "${w//[[:digit:]]/}" == "${w}" ]] ; then
169 # it's a character, not an index
157 for (( i = 0 ; i < ${#c[@]} ; i = $i + 1 )) ; do 170 for (( i = 0 ; i < ${#c[@]} ; i = $i + 1 )) ; do
158 if [[ -n "${c[${i}]//[^-._]}" ]] ; then 171 if [[ "${c[${i}]}" == "${w}" ]] ; then
159 found=$(($found + 1))
160 if [[ "$found" == "${1:-1}" ]] ; then
161 c[${i}]="${2}" 172 c[${i}]="${2}"
162 break 173 break
163 fi 174 fi
164 fi
165 done 175 done
176 else
177 for (( i = 0 ; i < ${#c[@]} ; i = $i + 1 )) ; do
178 if [[ -n "${c[${i}]//[^-._]}" ]] ; then
179 found=$(($found + 1))
180 if [[ "$found" == "${w}" ]] ; then
181 c[${i}]="${2}"
182 break
183 fi
184 fi
185 done
186 fi
166 c=${c[@]} 187 c=${c[@]}
167 echo ${c// } 188 echo ${c// }
168} 189}
169 190
170# Replace all version separators in $2 (defaults to $PV) with $1. 191# Replace all version separators in $2 (defaults to $PV) with $1.
174 c=( $(get_all_version_components "${2:-${PV}}" ) ) 195 c=( $(get_all_version_components "${2:-${PV}}" ) )
175 c="${c[@]//[-._]/$1}" 196 c="${c[@]//[-._]/$1}"
176 echo ${c// } 197 echo ${c// }
177} 198}
178 199
200# Delete the $1th separator in $2 (defaults to $PV if $2 is not supplied). If
201# there are fewer than $1 separators, don't change anything.
202# 1 1.2.3 -> 12.3
203# 2 1.2.3 -> 1.23
204# 1 1b-2.3 -> 1b2.3
205# Rather than being a number, $1 can be a separator character such as '-', '.'
206# or '_'. In this case, the first separator of this kind is deleted.
207delete_version_separator() {
208 replace_version_separator "${1}" "" "${2}"
209}
210
211# Delete all version separators in $1 (defaults to $PV).
212# 1b.2.3 -> 1b23
213delete_all_version_separators() {
214 replace_all_version_separators "" "${1}"
215}
216
217# Is $2 (defaults to $PVR) at least version $1? Intended for use in eclasses
218# only. May not be reliable, be sure to do very careful testing before actually
219# using this. Prod ciaranm if you find something it can't handle.
220version_is_at_least() {
221 local want_s="$1" have_s="${2:-${PVR}}" r
222 version_compare "${want_s}" "${have_s}"
223 r=$?
224 case $r in
225 1|2)
226 return 0
227 ;;
228 3)
229 return 1
230 ;;
231 *)
232 die "versionator compare bug [atleast, ${want_s}, ${have_s}, ${r}]"
233 ;;
234 esac
235}
236
237# Takes two parameters (a, b) which are versions. If a is an earlier version
238# than b, returns 1. If a is identical to b, return 2. If b is later than a,
239# return 3. You probably want version_is_at_least rather than this function.
240# May not be very reliable. Test carefully before using this.
241version_compare() {
242 local ver_a=${1} ver_b=${2} parts_a parts_b cur_idx_a=0 cur_idx_b=0
243 parts_a=( $(get_all_version_components "${ver_a}" ) )
244 parts_b=( $(get_all_version_components "${ver_b}" ) )
245
246 ### compare number parts.
247 local inf_loop=0
248 while true ; do
249 inf_loop=$(( ${inf_loop} + 1 ))
250 [[ ${inf_loop} -gt 20 ]] && \
251 die "versionator compare bug [numbers, ${ver_a}, ${ver_b}]"
252
253 # grab the current number components
254 local cur_tok_a=${parts_a[${cur_idx_a}]}
255 local cur_tok_b=${parts_b[${cur_idx_b}]}
256
257 # number?
258 if [[ -n ${cur_tok_a} ]] && [[ -z ${cur_tok_a//[[:digit:]]} ]] ; then
259 cur_idx_a=$(( ${cur_idx_a} + 1 ))
260 [[ ${parts_a[${cur_idx_a}]} == "." ]] \
261 && cur_idx_a=$(( ${cur_idx_a} + 1 ))
262 else
263 cur_tok_a=""
264 fi
265
266 if [[ -n ${cur_tok_b} ]] && [[ -z ${cur_tok_b//[[:digit:]]} ]] ; then
267 cur_idx_b=$(( ${cur_idx_b} + 1 ))
268 [[ ${parts_b[${cur_idx_b}]} == "." ]] \
269 && cur_idx_b=$(( ${cur_idx_b} + 1 ))
270 else
271 cur_tok_b=""
272 fi
273
274 # done with number components?
275 [[ -z ${cur_tok_a} ]] && [[ -z ${cur_tok_b} ]] && break
276
277 # to avoid going into octal mode, strip any leading zeros. otherwise
278 # bash will throw a hissy fit on versions like 6.3.068.
279 cur_tok_a=${cur_tok_a##+(0)}
280 cur_tok_b=${cur_tok_b##+(0)}
281
282 # if a component is blank, make it zero.
283 [[ -z ${cur_tok_a} ]] && cur_tok_a=0
284 [[ -z ${cur_tok_b} ]] && cur_tok_b=0
285
286 # compare
287 [[ ${cur_tok_a} -lt ${cur_tok_b} ]] && return 1
288 [[ ${cur_tok_a} -gt ${cur_tok_b} ]] && return 3
289 done
290
291 ### number parts equal. compare letter parts.
292 local letter_a=
293 letter_a=${parts_a[${cur_idx_a}]}
294 if [[ ${#letter_a} -eq 1 ]] && [[ -z ${letter_a/[a-z]} ]] ; then
295 cur_idx_a=$(( ${cur_idx_a} + 1 ))
296 else
297 letter_a="@"
298 fi
299
300 local letter_b=
301 letter_b=${parts_b[${cur_idx_b}]}
302 if [[ ${#letter_b} -eq 1 ]] && [[ -z ${letter_b/[a-z]} ]] ; then
303 cur_idx_b=$(( ${cur_idx_b} + 1 ))
304 else
305 letter_b="@"
306 fi
307
308 # compare
309 [[ ${letter_a} < ${letter_b} ]] && return 1
310 [[ ${letter_a} > ${letter_b} ]] && return 3
311
312 ### letter parts equal. compare suffixes in order.
313 local suffix rule part r_lt r_gt
314 for rule in "alpha=1" "beta=1" "pre=1" "rc=1" "p=3" "r=3" ; do
315 suffix=${rule%%=*}
316 r_lt=${rule##*=}
317 [[ ${r_lt} -eq 1 ]] && r_gt=3 || r_gt=1
318
319 local suffix_a=
320 for part in ${parts_a[@]} ; do
321 [[ ${part#${suffix}} != ${part} ]] && \
322 [[ -z ${part##${suffix}*([[:digit:]])} ]] && \
323 suffix_a=${part#${suffix}}0
324 done
325
326 local suffix_b=
327 for part in ${parts_b[@]} ; do
328 [[ ${part#${suffix}} != ${part} ]] && \
329 [[ -z ${part##${suffix}*([[:digit:]])} ]] && \
330 suffix_b=${part#${suffix}}0
331 done
332
333 [[ -z ${suffix_a} ]] && [[ -z ${suffix_b} ]] && continue
334
335 [[ -z ${suffix_a} ]] && return ${r_gt}
336 [[ -z ${suffix_b} ]] && return ${r_lt}
337
338 # avoid octal problems
339 suffix_a=${suffix_a##+(0)} ; suffix_a=${suffix_a:-0}
340 suffix_b=${suffix_b##+(0)} ; suffix_b=${suffix_b:-0}
341
342 [[ ${suffix_a} -lt ${suffix_b} ]] && return 1
343 [[ ${suffix_a} -gt ${suffix_b} ]] && return 3
344 done
345
346 ### no differences.
347 return 2
348}
349
350# Returns its parameters sorted, highest version last. We're using a quadratic
351# algorithm for simplicity, so don't call it with more than a few dozen items.
352# Uses version_compare, so be careful.
353version_sort() {
354 local items= left=0
355 items=( $@ )
356 while [[ ${left} -lt ${#items[@]} ]] ; do
357 local lowest_idx=${left}
358 local idx=$(( ${lowest_idx} + 1 ))
359 while [[ ${idx} -lt ${#items[@]} ]] ; do
360 version_compare "${items[${lowest_idx}]}" "${items[${idx}]}"
361 [[ $? -eq 3 ]] && lowest_idx=${idx}
362 idx=$(( ${idx} + 1 ))
363 done
364 local tmp=${items[${lowest_idx}]}
365 items[${lowest_idx}]=${items[${left}]}
366 items[${left}]=${tmp}
367 left=$(( ${left} + 1 ))
368 done
369 echo ${items[@]}
370}
371
372__versionator__test_version_compare() {
373 local lt=1 eq=2 gt=3 p q
374
375 __versionator__test_version_compare_t() {
376 version_compare "${1}" "${3}"
377 local r=$?
378 [[ ${r} -eq ${2} ]] || echo "FAIL: ${@} (got ${r} exp ${2})"
379 }
380
381 echo "
382 0 $lt 1
383 1 $lt 2
384 2 $gt 1
385 2 $eq 2
386 0 $eq 0
387 10 $lt 20
388 68 $eq 068
389 068 $gt 67
390 068 $lt 69
391
392 1.0 $lt 2.0
393 2.0 $eq 2.0
394 2.0 $gt 1.0
395
396 1.0 $gt 0.0
397 0.0 $eq 0.0
398 0.0 $lt 1.0
399
400 0.1 $lt 0.2
401 0.2 $eq 0.2
402 0.3 $gt 0.2
403
404 1.2 $lt 2.1
405 2.1 $gt 1.2
406
407 1.2.3 $lt 1.2.4
408 1.2.4 $gt 1.2.3
409
410 1.2.0 $eq 1.2
411 1.2.1 $gt 1.2
412 1.2 $lt 1.2.1
413
414 1.2b $eq 1.2b
415 1.2b $lt 1.2c
416 1.2b $gt 1.2a
417 1.2b $gt 1.2
418 1.2 $lt 1.2a
419
420 1.3 $gt 1.2a
421 1.3 $lt 1.3a
422
423 1.0_alpha7 $lt 1.0_beta7
424 1.0_beta $lt 1.0_pre
425 1.0_pre5 $lt 1.0_rc2
426 1.0_rc2 $lt 1.0
427
428 1.0_p1 $gt 1.0
429 1.0_p1-r1 $gt 1.0_p1
430
431 1.0_alpha6-r1 $gt 1.0_alpha6
432 1.0_beta6-r1 $gt 1.0_alpha6-r2
433
434 1.0_pre1 $lt 1.0-p1
435
436 1.0p $gt 1.0_p1
437 1.0r $gt 1.0-r1
438 1.6.15 $gt 1.6.10-r2
439 1.6.10-r2 $lt 1.6.15
440
441 " | while read a b c ; do
442 [[ -z "${a}${b}${c}" ]] && continue;
443 __versionator__test_version_compare_t "${a}" "${b}" "${c}"
444 done
445
446
447 for q in "alpha beta pre rc=${lt};${gt}" "p r=${gt};${lt}" ; do
448 for p in ${q%%=*} ; do
449 local c=${q##*=}
450 local alt=${c%%;*} agt=${c##*;}
451 __versionator__test_version_compare_t "1.0" $agt "1.0_${p}"
452 __versionator__test_version_compare_t "1.0" $agt "1.0_${p}1"
453 __versionator__test_version_compare_t "1.0" $agt "1.0_${p}068"
454
455 __versionator__test_version_compare_t "2.0_${p}" $alt "2.0"
456 __versionator__test_version_compare_t "2.0_${p}1" $alt "2.0"
457 __versionator__test_version_compare_t "2.0_${p}068" $alt "2.0"
458
459 __versionator__test_version_compare_t "1.0_${p}" $eq "1.0_${p}"
460 __versionator__test_version_compare_t "0.0_${p}" $lt "0.0_${p}1"
461 __versionator__test_version_compare_t "666_${p}3" $gt "666_${p}"
462
463 __versionator__test_version_compare_t "1_${p}7" $lt "1_${p}8"
464 __versionator__test_version_compare_t "1_${p}7" $eq "1_${p}7"
465 __versionator__test_version_compare_t "1_${p}7" $gt "1_${p}6"
466 __versionator__test_version_compare_t "1_${p}09" $eq "1_${p}9"
467 done
468 done
469
470 for p in "-r" "_p" ; do
471 __versionator__test_version_compare_t "7.2${p}1" $lt "7.2${p}2"
472 __versionator__test_version_compare_t "7.2${p}2" $gt "7.2${p}1"
473 __versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2"
474 __versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3"
475 done
476
477}
478

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.1.1

  ViewVC Help
Powered by ViewVC 1.1.20