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

Contents of /eclass/versionator.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations) (download)
Fri Mar 25 00:51:48 2005 UTC (9 years, 9 months ago) by ciaranm
Branch: MAIN
Changes since 1.5: +13 -7 lines
handle x.y.00z version numbers properly

1 # Copyright 1999-2004 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header: /var/cvsroot/gentoo-x86/eclass/versionator.eclass,v 1.5 2005/01/04 13:03:54 ciaranm Exp $
4 #
5 # Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
6 #
7 # This eclass provides functions which simplify manipulating $PV and similar
8 # variables. Most functions default to working with $PV, although other
9 # values can be used.
10 #
11 # Simple Example 1: $PV is 1.2.3b, we want 1_2.3b:
12 # MY_PV=$(replace_version_separator 1 '_' )
13 #
14 # Simple Example 2: $PV is 1.4.5, we want 1:
15 # MY_MAJORV=$(get_major_version )
16 #
17 # Full list of user usable functions provided by this eclass (see the functions
18 # themselves for documentation):
19 # get_all_version_components ver_str
20 # get_version_components ver_str
21 # get_major_version ver_str
22 # get_version_component_range range ver_str
23 # get_after_major_version ver_str
24 # replace_version_separator index 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 # but it doesn't work in all cases, so only use it if you know what you're
36 # doing.
37
38 ECLASS=versionator
39 INHERITED="$INHERITED $ECLASS"
40
41 shopt -s extglob
42
43 # Split up a version string into its component parts. If no parameter is
44 # supplied, defaults to $PV.
45 # 0.8.3 -> 0 . 8 . 3
46 # 7c -> 7 c
47 # 3.0_p2 -> 3 . 0 _ p2
48 # 20040905 -> 20040905
49 # 3.0c-r1 -> 3 . 0 c - r1
50 get_all_version_components() {
51 local ver_str=${1:-${PV}} result result_idx=0
52 result=( )
53
54 # sneaky cache trick cache to avoid having to parse the same thing several
55 # times.
56 if [[ "${VERSIONATOR_CACHE_VER_STR}" == "${ver_str}" ]] ; then
57 echo ${VERSIONATOR_CACHE_RESULT}
58 return
59 fi
60 export VERSIONATOR_CACHE_VER_STR="${ver_str}"
61
62 while [[ -n "$ver_str" ]] ; do
63 case "${ver_str:0:1}" in
64 # number: parse whilst we have a number
65 [[:digit:]])
66 result[$result_idx]="${ver_str%%[^[:digit:]]*}"
67 ver_str="${ver_str##+([[:digit:]])}"
68 result_idx=$(($result_idx + 1))
69 ;;
70
71 # separator: single character
72 [-_.])
73 result[$result_idx]="${ver_str:0:1}"
74 ver_str="${ver_str:1}"
75 result_idx=$(($result_idx + 1))
76 ;;
77
78 # letter: grab the letters plus any following numbers
79 [[:alpha:]])
80 local not_match="${ver_str##+([[:alpha:]])*([[:digit:]])}"
81 result[$result_idx]=${ver_str:0:$((${#ver_str} - ${#not_match}))}
82 ver_str="${not_match}"
83 result_idx=$(($result_idx + 1))
84 ;;
85
86 # huh?
87 *)
88 result[$result_idx]="${ver_str:0:1}"
89 ver_str="${ver_str:1}"
90 result_idx=$(($result_idx + 1))
91 ;;
92 esac
93 done
94
95 export VERSIONATOR_CACHE_RESULT="${result[@]}"
96 echo ${result[@]}
97 }
98
99 # Get the important version components, excluding '.', '-' and '_'. Defaults to
100 # $PV if no parameter is supplied.
101 # 0.8.3 -> 0 8 3
102 # 7c -> 7 c
103 # 3.0_p2 -> 3 0 p2
104 # 20040905 -> 20040905
105 # 3.0c-r1 -> 3 0 c r1
106 get_version_components() {
107 local c="$(get_all_version_components "${1:-${PV}}")"
108 c=( ${c[@]//[-._]/ } )
109 echo ${c[@]}
110 }
111
112 # Get the major version of a value. Defaults to $PV if no parameter is supplied.
113 # 0.8.3 -> 0
114 # 7c -> 7
115 # 3.0_p2 -> 3
116 # 20040905 -> 20040905
117 # 3.0c-r1 -> 3
118 get_major_version() {
119 local c
120 c=( $(get_all_version_components "${1:-${PV}}" ) )
121 echo ${c[0]}
122 }
123
124 # Get a particular component or range of components from the version. If no
125 # version parameter is supplied, defaults to $PV.
126 # 1 1.2.3 -> 1
127 # 1-2 1.2.3 -> 1.2
128 # 2- 1.2.3 -> 2.3
129 get_version_component_range() {
130 local c v="${2:-${PV}}" range="${1}" range_start range_end i=-1 j=0
131 c=( $(get_all_version_components ${v} ) )
132 range_start="${range%-*}" ; range_start="${range_start:-1}"
133 range_end="${range#*-}" ; range_end="${range_end:-${#c[@]}}"
134
135 while (( j < ${range_start} )) ; do
136 i=$(($i + 1))
137 [[ $i -gt ${#c[@]} ]] && return
138 [[ -n "${c[${i}]//[-._]}" ]] && j=$(($j + 1))
139 done
140
141 while (( j <= ${range_end} )) ; do
142 echo -n ${c[$i]}
143 [[ $i -gt ${#c[@]} ]] && return
144 [[ -n "${c[${i}]//[-._]}" ]] && j=$(($j + 1))
145 i=$(($i + 1))
146 done
147 }
148
149 # Get everything after the major version and its separator (if present) of a
150 # value. Defaults to $PV if no parameter is supplied.
151 # 0.8.3 -> 8.3
152 # 7c -> c
153 # 3.0_p2 -> 0_p2
154 # 20040905 -> (empty string)
155 # 3.0c-r1 -> 0c-r1
156 get_after_major_version() {
157 echo $(get_version_component_range 2- "${1:-PV}" )
158 }
159
160 # Replace the $1th separator with $2 in $3 (defaults to $PV if $3 is not
161 # supplied). If there are fewer than $1 separators, don't change anything.
162 # 1 '_' 1.2.3 -> 1_2.3
163 # 2 '_' 1.2.3 -> 1.2_3
164 # 1 '_' 1b-2.3 -> 1b_2.3
165 # Rather than being a number, $1 can be a separator character such as '-', '.'
166 # or '_'. In this case, the first separator of this kind is selected.
167 replace_version_separator() {
168 local w i c found=0 v="${3:-${PV}}"
169 w=${1:-1}
170 c=( $(get_all_version_components ${v} ) )
171 if [[ "${w//[[:digit:]]/}" == "${w}" ]] ; then
172 # it's a character, not an index
173 for (( i = 0 ; i < ${#c[@]} ; i = $i + 1 )) ; do
174 if [[ "${c[${i}]}" == "${w}" ]] ; then
175 c[${i}]="${2}"
176 break
177 fi
178 done
179 else
180 for (( i = 0 ; i < ${#c[@]} ; i = $i + 1 )) ; do
181 if [[ -n "${c[${i}]//[^-._]}" ]] ; then
182 found=$(($found + 1))
183 if [[ "$found" == "${w}" ]] ; then
184 c[${i}]="${2}"
185 break
186 fi
187 fi
188 done
189 fi
190 c=${c[@]}
191 echo ${c// }
192 }
193
194 # Replace all version separators in $2 (defaults to $PV) with $1.
195 # '_' 1b.2.3 -> 1b_2_3
196 replace_all_version_separators() {
197 local c
198 c=( $(get_all_version_components "${2:-${PV}}" ) )
199 c="${c[@]//[-._]/$1}"
200 echo ${c// }
201 }
202
203 # Delete the $1th separator in $2 (defaults to $PV if $2 is not supplied). If
204 # there are fewer than $1 separators, don't change anything.
205 # 1 1.2.3 -> 12.3
206 # 2 1.2.3 -> 1.23
207 # 1 1b-2.3 -> 1b2.3
208 # Rather than being a number, $1 can be a separator character such as '-', '.'
209 # or '_'. In this case, the first separator of this kind is deleted.
210 delete_version_separator() {
211 replace_version_separator "${1}" "" "${2}"
212 }
213
214 # Delete all version separators in $1 (defaults to $PV).
215 # 1b.2.3 -> 1b23
216 delete_all_version_separators() {
217 replace_all_version_separators "" "${1}"
218 }
219
220 # 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
222 # reaaaallly well before using this. Prod ciaranm if you need it to support more
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.
226 version_is_at_least() {
227 local want_s="$1" have_s="${2:-${PVR}}" want_c have_c
228 want_c=( $(get_version_components "$want_s" ) )
229 have_c=( $(get_version_components "$have_s" ) )
230
231 # Stage 1: compare the version numbers part.
232 local done_w="" done_h="" i=0
233 while [[ -z "${done_w}" ]] || [[ -z "${done_h}" ]] ; do
234 local cur_w="${want_c[$i]}" cur_h="${have_c[$i]}"
235 local my_cur_w="${cur_w//#0}" my_cur_h="${cur_h//#0}"
236 [[ -z "${my_cur_w##[^[:digit:]]*}" ]] && done_w="yes"
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
245 local part
246 for part in "_alpha" "_beta" "_pre" "_rc" "_p" "-r" ; do
247 local part_w= part_h=
248
249 for (( i = 0 ; i < ${#want_c[@]} ; i = $i + 1 )) ; do
250 if [[ -z "${want_c[$i]##${part#[-._]}*}" ]] ; then
251 part_w="${want_c[$i]##${part#[-._]}}"
252 break
253 fi
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
273 # if present in neither want nor have, go to the next item
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
282 done
283
284 return 0
285 }
286
287 # Test function thing. To use, source versionator.eclass and then run it.
288 __versionator__test_version_is_at_least() {
289 version_is_at_least "1.2" "1.2" || echo "test 1 failed"
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
293 version_is_at_least "1.2_beta1" "1.2" || echo "test 4 failed"
294 version_is_at_least "1.2_alpha1" "1.2" || echo "test 5 failed"
295 version_is_at_least "1.2_alpha1" "1.2_beta1" || echo "test 6 failed"
296
297 version_is_at_least "1.2" "1.2_beta1" && echo "test 7 failed"
298 version_is_at_least "1.2" "1.2_alpha1" && echo "test 8 failed"
299 version_is_at_least "1.2_beta1" "1.2_alpha1" && echo "test 9 failed"
300
301 version_is_at_least "1.2_beta1" "1.2_beta1" || echo "test 10 failed"
302 version_is_at_least "1.2_beta2" "1.2_beta1" && echo "test 11 failed"
303 version_is_at_least "1.2_beta2" "1.2_beta3" || echo "test 12 failed"
304
305 version_is_at_least "1.2-r1" "1.2" && echo "test 13 failed"
306 version_is_at_least "1.2" "1.2-r1" || echo "test 14 failed"
307 version_is_at_least "1.2-r1" "1.3" || echo "test 15 failed"
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
311 version_is_at_least "1.2-r1" "1.2_beta2-r3" && echo "test 18 failed"
312 version_is_at_least "1.2-r1" "1.3_beta2-r3" || echo "test 19 failed"
313
314 version_is_at_least "1.002" "1.2" || echo "test 20 failed"
315 version_is_at_least "1.2" "1.002" || echo "test 21 failed"
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 }

  ViewVC Help
Powered by ViewVC 1.1.20