From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from lists.gentoo.org ([140.105.134.102] helo=robin.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1IcTV2-0005Uq-UE for garchives@archives.gentoo.org; Mon, 01 Oct 2007 22:12:25 +0000 Received: from robin.gentoo.org (localhost [127.0.0.1]) by robin.gentoo.org (8.14.1/8.14.0) with SMTP id l91M2drb007185; Mon, 1 Oct 2007 22:02:39 GMT Received: from mail.marples.name (rsm.demon.co.uk [80.177.111.50]) by robin.gentoo.org (8.14.1/8.14.0) with ESMTP id l91Lxgin000926 for ; Mon, 1 Oct 2007 21:59:42 GMT Received: from uberlaptop.marples.name (uberlaptop.marples.name [10.73.1.31]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.marples.name (Postfix) with ESMTP id C9DDD190038 for ; Mon, 1 Oct 2007 22:59:41 +0100 (BST) From: Roy Marples To: gentoo-dev@lists.gentoo.org Subject: [gentoo-dev] RFC: sh versionator.eclass Date: Mon, 1 Oct 2007 22:59:40 +0100 User-Agent: KMail/1.9.7 Organization: Gentoo Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@gentoo.org Reply-to: gentoo-dev@lists.gentoo.org MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_M3WAHPiZJbJMwQB" Message-Id: <200710012259.40589.uberlord@gentoo.org> X-Archives-Salt: c54079d8-f5df-4be5-8fd7-f9eac0a95f89 X-Archives-Hash: db104222dfea3163a1c956d10f151cc5 --Boundary-00=_M3WAHPiZJbJMwQB Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline I would like to propse a new versionator.eclass for consideration (attached). This version, I believe, is more readable and maintainable then the one currently in portage. It also uses a lot less code and has the bonus of being pure sh. It has not been tested in any ebuilds, but it does pass the self test from portage as it stands. No doubt the nit pickers can invent new tests where this one fails and the current one does not - I shall address this when they do. Comments are welcome. Thanks Roy --Boundary-00=_M3WAHPiZJbJMwQB Content-Type: text/plain; charset="us-ascii"; name="versionator.eclass" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="versionator.eclass" # Copyright 2007 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # sh version of versionator.eclass # get_last_version_component_index implementation is not implemented because # 1) The name encourages the use of bash arrarys # 2) User could do $(($(get_version_component_count) - 1)) to achieve the # same result _get_all_version_components() { local dosep=$1 ver=${2:-${PV}} x= last= this= while [ -n "${ver}" ]; do x=$(printf "%c" "${ver}") case "${x}" in [0-9]) this="digit";; -|.|_) this="sep";; *) this="alpha";; esac if ${dosep} || [ "${this}" != "sep" ]; then [ -n "${last}" -a "${this}" != "${last}" ] && printf " " printf "%c" "${x}" fi last=${this} ver=${ver#${x}} done } # Split up a version string into its component parts. If no parameter is # supplied, defaults to $PV. # 0.8.3 -> 0 . 8 . 3 # 7c -> 7 c # 3.0_p2 -> 3 . 0 _ p2 # 20040905 -> 20040905 # 3.0c-r1 -> 3 . 0 c - r1 get_all_version_components() { _get_all_version_components true "$@" } # Get the important version components, excluding '.', '-' and '_'. Defaults to # $PV if no parameter is supplied. # 0.8.3 -> 0 8 3 # 7c -> 7 c # 3.0_p2 -> 3 0 p2 # 20040905 -> 20040905 # 3.0c-r1 -> 3 0 c r1 get_version_components() { _get_all_version_components false "$@" } # Get the major version of a value. Defaults to $PV if no parameter is supplied. # 0.8.3 -> 0 # 7c -> 7 # 3.0_p2 -> 3 # 20040905 -> 20040905 # 3.0c-r1 -> 3 get_major_version() { set -- $(get_version_components "$@") printf "%s" "$1" } # Get everything after the major version and its separator (if present) of a # value. Defaults to $PV if no parameter is supplied. # 0.8.3 -> 8.3 # 7c -> c # 3.0_p2 -> 0_p2 # 20040905 -> (empty string) # 3.0c-r1 -> 0c-r1 get_after_major_version() { printf "%s" "${@#$(get_major_version "$@")}" } _replace_version_separator_n() { local n=$1 sep=$2 i=0 set -- $(get_all_version_components "$3") while [ -n "$1" ]; do case "$1" in -|.|_) i=$((${i} + 1)) if [ "${i}" = "${n}" ]; then printf "%s" "${sep}" else printf "%s" "$1" fi ;; *) printf "%s" "$1" ;; esac shift done } _replace_version_separator_a() { local n=$1 sep=$2 i=0 set -- $(get_all_version_components "$3") while [ -n "$1" ]; do if [ "${n}" = "$1" ]; then printf "%s" "${sep}" n= else printf "%s" "$1" fi shift done } # Replace the $1th separator with $2 in $3 (defaults to $PV if $3 is not # supplied). If there are fewer than $1 separators, don't change anything. # 1 '_' 1.2.3 -> 1_2.3 # 2 '_' 1.2.3 -> 1.2_3 # 1 '_' 1b-2.3 -> 1b_2.3 # Rather than being a number, $1 can be a separator character such as '-', '.' # or '_'. In this case, the first separator of this kind is selected. replace_version_separator() { case "$1" in [0-9]*) _replace_version_separator_n "$@";; *) _replace_version_separator_a "$@";; esac } # Replace all version separators in $2 (defaults to $PV) with $1. # '_' 1b.2.3 -> 1b_2_3 replace_all_version_separators() { local sep=$1 set -- $(get_all_version_components "$2") while [ -n "$1" ]; do case "$1" in -|.|_) printf "%s" "${sep}";; *) printf "%s" "$1";; esac shift done } # Delete the $1th separator in $2 (defaults to $PV if $2 is not supplied). If # there are fewer than $1 separators, don't change anything. # 1 1.2.3 -> 12.3 # 2 1.2.3 -> 1.23 # 1 1b-2.3 -> 1b2.3 # Rather than being a number, $1 can be a separator character such as '-', '.' # or '_'. In this case, the first separator of this kind is deleted. delete_version_separator() { replace_version_separator "$1" "" "$2" } # Delete all version separators in $1 (defaults to $PV). # 1b.2.3 -> 1b23 delete_all_version_separators() { replace_all_version_separators "" "$@" } # How many version components are there in $1 (defaults to $PV)? # 1.0.1 -> 3 # 3.0c-r1 -> 4 get_version_component_count() { set -- $(get_version_components "$@") printf "%s" "$#" } # Get a particular component or range of components from the version. If no # version parameter is supplied, defaults to $PV. # 1 1.2.3 -> 1 # 1-2 1.2.3 -> 1.2 # 2- 1.2.3 -> 2.3 get_version_component_range() { [ -z "$1" ] && return 1 local range=$(get_all_version_components "$1") shift local vers=$(get_all_version_components "$@") set -- ${range} local one=$1 two=$2 three=$3 set -- ${vers} local i=1 while [ ${i} -lt ${one} ]; do shift; shift i=$((${i} + 1)) done printf "%s" "$1" [ "${two}" != "-" ] && return shift [ -z "${three}" ] && three=$(get_version_component_count "${vers}") while [ ${i} -lt ${three} ]; do printf "%s" "$1$2" shift; shift i=$((${i} + 1)) done } _version_getn() { local v=$1 case "$1" in 0*) v=${1##*0}; v=${v:-0};; -|.|_) v=0;; esac printf "%s" "${v}" } _version_is_prefix() { case "$1" in alpha|beta|pre|rc) return 0;; esac return 1 } # Takes two parameters (a, b) which are versions. If a is an earlier version # than b, returns 1. If a is identical to b, return 2. If b is later than a, # return 3. You probably want version_is_at_least rather than this function. # May not be very reliable. Test carefully before using this. version_compare() { # Don't beat around the bush [ "$1" = "$2" ] && return 2 local ver1=$(get_all_version_components "$1") ver11= ver11n= local ver2=$(get_all_version_components "$2") ver21= ver21n= while [ -n "${ver1}" -o -n "${ver2}" ]; do # Grab the components and trim leading 0's set -- ${ver1} ver11=$(_version_getn "$@") shift ver1="$@" set -- ${ver2} ver21=$(_version_getn "$@") shift ver2="$@" if _version_is_prefix "${ver11}"; then _version_is_prefix "${ver21}" || return 1 else _version_is_prefix "${ver21}" && return 3 fi [ -z "${ver11}" ] && ver11=0 [ -z "${ver21}" ] && ver21=0 [ "${ver11}" = "${ver21}" ] && continue case "${ver11}" in [0-9]*) ver11n=true;; *) ver11n=false;; esac case "${ver21}" in [0-9]*) ver21n=true;; *) ver21n=false;; esac if ${ver11n} && ${ver21n}; then # Both are numbers [ "${ver11}" -lt "${ver21}" ] && return 1 [ "${ver11}" -gt "${ver21}" ] && return 3 fi # Either is not a number, so lexical comparison [ "${ver11}" "<" "${ver21}" ] && return 1 [ "${ver11}" ">" "${ver21}" ] && return 3 done # All equal then return 2 } # Is $2 (defaults to $PVR) at least version $1? Intended for use in eclasses # only. May not be reliable, be sure to do very careful testing before actually # using this. Prod ciaranm if you find something it can't handle. version_is_at_least() { version_compare "$1" "${2:-${PVR}}" case $? in 1|2) return 0;; 3) return 1;; *) die "versionator compare bug";; esac } # Returns its parameters sorted, highest version last. version_sort() { local sorted= left="$@" item= while [ -n "${left}" ]; do set -- ${left} item=$1 shift left="$@" set -- ${sorted} sorted= local inserted=false while [ -n "$1" ]; do version_compare "${item}" "$1" if [ "$?" = "1" ]; then sorted="${sorted}${sorted:+ }${item} $*" continue 2 fi sorted="${sorted}${sorted:+ }$1" shift done sorted="${sorted}${sorted:+ }${item}" done printf "%s" "${sorted}" } __versionator__test_version_compare() { local lt=1 eq=2 gt=3 p= q= __versionator__test_version_compare_t() { version_compare "$1" "$3" local r=$? [ "${r}" != "$2" ] && echo "FAIL: ${@} (got ${r} exp $2)" } echo " 0 $lt 1 1 $lt 2 2 $gt 1 2 $eq 2 0 $eq 0 10 $lt 20 68 $eq 068 068 $gt 67 068 $lt 69 1.0 $lt 2.0 2.0 $eq 2.0 2.0 $gt 1.0 1.0 $gt 0.0 0.0 $eq 0.0 0.0 $lt 1.0 0.1 $lt 0.2 0.2 $eq 0.2 0.3 $gt 0.2 1.2 $lt 2.1 2.1 $gt 1.2 1.2.3 $lt 1.2.4 1.2.4 $gt 1.2.3 1.2.0 $eq 1.2 1.2.1 $gt 1.2 1.2 $lt 1.2.1 1.2b $eq 1.2b 1.2b $lt 1.2c 1.2b $gt 1.2a 1.2b $gt 1.2 1.2 $lt 1.2a 1.3 $gt 1.2a 1.3 $lt 1.3a 1.0_alpha7 $lt 1.0_beta7 1.0_beta $lt 1.0_pre 1.0_pre5 $lt 1.0_rc2 1.0_rc2 $lt 1.0 1.0_p1 $gt 1.0 1.0_p1-r1 $gt 1.0_p1 1.0_alpha6-r1 $gt 1.0_alpha6 1.0_beta6-r1 $gt 1.0_alpha6-r2 1.0_pre1 $lt 1.0-p1 1.0p $gt 1.0_p1 1.0r $gt 1.0-r1 1.6.15 $gt 1.6.10-r2 1.6.10-r2 $lt 1.6.15 " | while read a b c ; do [ -z "${a}${b}${c}" ] && continue; __versionator__test_version_compare_t "${a}" "${b}" "${c}" done for q in "alpha beta pre rc=${lt};${gt}" "p r=${gt};${lt}" ; do for p in ${q%%=*} ; do local c=${q##*=} local alt=${c%%;*} agt=${c##*;} __versionator__test_version_compare_t "1.0" $agt "1.0_${p}" __versionator__test_version_compare_t "1.0" $agt "1.0_${p}1" __versionator__test_version_compare_t "1.0" $agt "1.0_${p}068" __versionator__test_version_compare_t "2.0_${p}" $alt "2.0" __versionator__test_version_compare_t "2.0_${p}1" $alt "2.0" __versionator__test_version_compare_t "2.0_${p}068" $alt "2.0" __versionator__test_version_compare_t "1.0_${p}" $eq "1.0_${p}" __versionator__test_version_compare_t "0.0_${p}" $lt "0.0_${p}1" __versionator__test_version_compare_t "666_${p}3" $gt "666_${p}" __versionator__test_version_compare_t "1_${p}7" $lt "1_${p}8" __versionator__test_version_compare_t "1_${p}7" $eq "1_${p}7" __versionator__test_version_compare_t "1_${p}7" $gt "1_${p}6" __versionator__test_version_compare_t "1_${p}09" $eq "1_${p}9" done done for p in "-r" "_p" ; do __versionator__test_version_compare_t "7.2${p}1" $lt "7.2${p}2" __versionator__test_version_compare_t "7.2${p}2" $gt "7.2${p}1" __versionator__test_version_compare_t "7.2${p}3" $gt "7.2${p}2" __versionator__test_version_compare_t "7.2${p}2" $lt "7.2${p}3" done } --Boundary-00=_M3WAHPiZJbJMwQB-- -- gentoo-dev@gentoo.org mailing list