public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] RFC: sh versionator.eclass
@ 2007-10-01 21:59 Roy Marples
  2007-10-01 22:30 ` Roy Marples
  2007-10-02  7:29 ` [gentoo-dev] " Fabian Groffen
  0 siblings, 2 replies; 85+ messages in thread
From: Roy Marples @ 2007-10-01 21:59 UTC (permalink / raw
  To: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 510 bytes --]

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

[-- Attachment #2: versionator.eclass --]
[-- Type: text/plain, Size: 10429 bytes --]

# 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
}


^ permalink raw reply	[flat|nested] 85+ messages in thread

end of thread, other threads:[~2007-10-11  6:59 UTC | newest]

Thread overview: 85+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-01 21:59 [gentoo-dev] RFC: sh versionator.eclass Roy Marples
2007-10-01 22:30 ` Roy Marples
2007-10-01 22:41   ` Fernando J. Pereda
2007-10-01 22:48     ` Roy Marples
2007-10-02  0:22       ` Mike Frysinger
2007-10-02  6:26         ` Roy Marples
2007-10-02  8:56           ` [gentoo-dev] " Duncan
2007-10-02  9:28           ` [gentoo-dev] " Mike Frysinger
2007-10-02  6:35   ` Natanael Copa
2007-10-02  6:46     ` Roy Marples
2007-10-02  9:50       ` [gentoo-dev] " Steve Long
2007-10-02  7:29 ` [gentoo-dev] " Fabian Groffen
2007-10-02  8:48   ` Roy Marples
2007-10-02  9:22     ` Fabian Groffen
2007-10-02  9:37       ` Roy Marples
2007-10-02  9:49         ` Fabian Groffen
2007-10-02 10:09           ` Roy Marples
2007-10-02 10:28             ` Mike Frysinger
2007-10-02 10:49               ` Roy Marples
2007-10-02 11:00                 ` Mike Frysinger
2007-10-02 10:41             ` Fabian Groffen
2007-10-02 11:00               ` Roy Marples
2007-10-02 11:10                 ` Fabian Groffen
2007-10-02 10:10         ` Mike Frysinger
2007-10-02 10:31           ` Roy Marples
2007-10-02 10:49             ` Mike Frysinger
2007-10-02 11:38               ` Roy Marples
2007-10-02 11:50                 ` Luca Barbato
2007-10-02 12:38                   ` Mike Frysinger
2007-10-02 13:16                     ` Luca Barbato
2007-10-02 13:26                       ` Mike Frysinger
2007-10-02 14:01                         ` Natanael Copa
2007-10-02 12:35                 ` Mike Frysinger
2007-10-02 12:39                 ` Alec Warner
2007-10-02 14:03                   ` Natanael Copa
2007-10-02 15:36                     ` Richard Freeman
2007-10-02 23:02           ` Joe Peterson
2007-10-02 23:11             ` Roy Marples
2007-10-03  0:55               ` [gentoo-dev] " Steve Long
2007-10-03  8:40                 ` Roy Marples
2007-10-03 18:06                   ` Fabian Groffen
2007-10-07  5:03             ` [gentoo-dev] " Mike Frysinger
2007-10-07 16:19               ` Joe Peterson
2007-10-07 22:15                 ` Fabian Groffen
2007-10-07 22:37                   ` Joe Peterson
2007-10-08  6:31                     ` Fabian Groffen
2007-10-08  1:51                   ` Mike Frysinger
2007-10-08  3:26                     ` Joe Peterson
2007-10-08  8:50                       ` [gentoo-dev] GNU userland and binary package (WAS: RFC: sh versionator.eclass) Natanael Copa
2007-10-08 13:52                         ` Alec Warner
2007-10-08 15:02                           ` Natanael Copa
2007-10-08 19:25                             ` [gentoo-dev] " Steve Long
2007-10-09  9:00                               ` Natanael Copa
2007-10-09 16:28                                 ` [gentoo-dev] " Steve Long
2007-10-11  3:03                             ` [gentoo-dev] " Alec Warner
2007-10-11  6:46                               ` Roy Marples
2007-10-02  9:39     ` [gentoo-dev] RFC: sh versionator.eclass Mike Frysinger
2007-10-02 10:24       ` Roy Marples
2007-10-02 10:57         ` Mike Frysinger
2007-10-02 11:28           ` Roy Marples
2007-10-02 12:29             ` Mike Frysinger
2007-10-02 12:58             ` [gentoo-dev] " Duncan
2007-10-02 13:10               ` Alec Warner
2007-10-02 13:17               ` Mike Frysinger
2007-10-03 12:40           ` [gentoo-dev] " Roy Marples
2007-10-07  5:06             ` Mike Frysinger
2007-10-07 17:38               ` Roy Marples
2007-10-08  1:44                 ` Mike Frysinger
2007-10-02 12:36       ` [gentoo-dev] " Steve Long
2007-10-02 14:18         ` Roy Marples
2007-10-02 14:25           ` Roy Marples
2007-10-02 16:30             ` George Shapovalov
2007-10-02 16:52               ` Roy Marples
2007-10-02 18:37                 ` [gentoo-dev] " Steve Long
2007-10-02 19:44                   ` Roy Marples
2007-10-02 22:18                     ` [gentoo-dev] " Steve Long
2007-10-02 22:47                       ` Roy Marples
2007-10-03  1:29                       ` [gentoo-dev] " Ryan Hill
2007-10-03  6:44                         ` Roy Marples
2007-10-07  5:09               ` Mike Frysinger
2007-10-07 17:31                 ` Roy Marples
2007-10-08  1:42                   ` Mike Frysinger
2007-10-02 18:46           ` Alex Tarkovsky
2007-10-03 12:34             ` Yuri Gagarin
2007-10-02  9:10   ` [gentoo-dev] " Natanael Copa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox