Skip to content

Commit 2ba36cd

Browse files
committed
Add vercmp function
The existing vercmp_numbers function only handles, as the name says, numbers. I noticed that "sort" has had a version sort for a long time [1] and, rather than re-implement it badly, use this as a version of vercmp that works a bit more naturally. This is intended to be used in an "if" statement as in prog_ver=$(prog_ver --version | grep ...) if vercmp $prog_ver "<" 2.0; then ... fi A test-case is added to test the basic features and some edge-cases. [1] http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=4c9fae4e97d95a9f89d1399a8aeb03051f0fec96 Change-Id: Ie55283acdc40a095b80b2631a55310072883ad0d
1 parent bcad037 commit 2ba36cd

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

functions

+46
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,58 @@ function vercmp_numbers {
527527
typeset v1=$1 v2=$2 sep
528528
typeset -a ver1 ver2
529529

530+
deprecated "vercmp_numbers is deprecated for more generic vercmp"
531+
530532
IFS=. read -ra ver1 <<< "$v1"
531533
IFS=. read -ra ver2 <<< "$v2"
532534

533535
_vercmp_r "${#ver1[@]}" "${ver1[@]}" "${ver2[@]}"
534536
}
535537

538+
# vercmp ver1 op ver2
539+
# Compare VER1 to VER2
540+
# - op is one of < <= == >= >
541+
# - returns true if satisified
542+
# e.g.
543+
# if vercmp 1.0 "<" 2.0; then
544+
# ...
545+
# fi
546+
function vercmp {
547+
local v1=$1
548+
local op=$2
549+
local v2=$3
550+
local result
551+
552+
# sort the two numbers with sort's "-V" argument. Based on if v2
553+
# swapped places with v1, we can determine ordering.
554+
result=$(echo -e "$v1\n$v2" | sort -V | head -1)
555+
556+
case $op in
557+
"==")
558+
[ "$v1" = "$v2" ]
559+
return
560+
;;
561+
">")
562+
[ "$v1" != "$v2" ] && [ "$result" = "$v2" ]
563+
return
564+
;;
565+
"<")
566+
[ "$v1" != "$v2" ] && [ "$result" = "$v1" ]
567+
return
568+
;;
569+
">=")
570+
[ "$result" = "$v2" ]
571+
return
572+
;;
573+
"<=")
574+
[ "$result" = "$v1" ]
575+
return
576+
;;
577+
*)
578+
die $LINENO "unrecognised op: $op"
579+
;;
580+
esac
581+
}
536582

537583
# This function sets log formatting options for colorizing log
538584
# output to stdout. It is meant to be called by lib modules.

tests/test_vercmp.sh

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env bash
2+
3+
# Tests for DevStack vercmp functionality
4+
5+
TOP=$(cd $(dirname "$0")/.. && pwd)
6+
7+
# Import common functions
8+
source $TOP/functions
9+
source $TOP/tests/unittest.sh
10+
11+
assert_true "numeric gt" vercmp 2.0 ">" 1.0
12+
assert_true "numeric gte" vercmp 2.0 ">=" 1.0
13+
assert_true "numeric gt" vercmp 1.0.1 ">" 1.0
14+
assert_true "numeric gte" vercmp 1.0.1 ">=" 1.0
15+
assert_true "alpha gt" vercmp 1.0.1b ">" 1.0.1a
16+
assert_true "alpha gte" vercmp 1.0.1b ">=" 1.0.1a
17+
assert_true "alpha gt" vercmp b ">" a
18+
assert_true "alpha gte" vercmp b ">=" a
19+
assert_true "alpha gt" vercmp 2.0-rc3 ">" 2.0-rc1
20+
assert_true "alpha gte" vercmp 2.0-rc3 ">=" 2.0-rc1
21+
22+
assert_false "numeric gt fail" vercmp 1.0 ">" 1.0
23+
assert_true "numeric gte" vercmp 1.0 ">=" 1.0
24+
assert_false "numeric gt fail" vercmp 0.9 ">" 1.0
25+
assert_false "numeric gte fail" vercmp 0.9 ">=" 1.0
26+
assert_false "numeric gt fail" vercmp 0.9.9 ">" 1.0
27+
assert_false "numeric gte fail" vercmp 0.9.9 ">=" 1.0
28+
assert_false "numeric gt fail" vercmp 0.9a.9 ">" 1.0.1
29+
assert_false "numeric gte fail" vercmp 0.9a.9 ">=" 1.0.1
30+
31+
assert_false "numeric lt" vercmp 1.0 "<" 1.0
32+
assert_true "numeric lte" vercmp 1.0 "<=" 1.0
33+
assert_true "numeric lt" vercmp 1.0 "<" 1.0.1
34+
assert_true "numeric lte" vercmp 1.0 "<=" 1.0.1
35+
assert_true "alpha lt" vercmp 1.0.1a "<" 1.0.1b
36+
assert_true "alpha lte" vercmp 1.0.1a "<=" 1.0.1b
37+
assert_true "alpha lt" vercmp a "<" b
38+
assert_true "alpha lte" vercmp a "<=" b
39+
assert_true "alpha lt" vercmp 2.0-rc1 "<" 2.0-rc3
40+
assert_true "alpha lte" vercmp 2.0-rc1 "<=" 2.0-rc3
41+
42+
assert_true "eq" vercmp 1.0 "==" 1.0
43+
assert_true "eq" vercmp 1.0.1 "==" 1.0.1
44+
assert_false "eq fail" vercmp 1.0.1 "==" 1.0.2
45+
assert_false "eq fail" vercmp 2.0-rc1 "==" 2.0-rc2
46+
47+
report_results

tests/unittest.sh

+45
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,51 @@ function assert_empty {
9292
fi
9393
}
9494

95+
# assert the arguments evaluate to true
96+
# assert_true "message" arg1 arg2
97+
function assert_true {
98+
local lineno
99+
lineno=`caller 0 | awk '{print $1}'`
100+
local function
101+
function=`caller 0 | awk '{print $2}'`
102+
local msg=$1
103+
shift
104+
105+
$@
106+
if [ $? -eq 0 ]; then
107+
PASS=$((PASS+1))
108+
echo "PASS: $function:L$lineno - $msg"
109+
else
110+
FAILED_FUNCS+="$function:L$lineno\n"
111+
echo "ERROR: test failed in $function:L$lineno!"
112+
echo " $msg"
113+
ERROR=$((ERROR+1))
114+
fi
115+
}
116+
117+
# assert the arguments evaluate to false
118+
# assert_false "message" arg1 arg2
119+
function assert_false {
120+
local lineno
121+
lineno=`caller 0 | awk '{print $1}'`
122+
local function
123+
function=`caller 0 | awk '{print $2}'`
124+
local msg=$1
125+
shift
126+
127+
$@
128+
if [ $? -eq 0 ]; then
129+
FAILED_FUNCS+="$function:L$lineno\n"
130+
echo "ERROR: test failed in $function:L$lineno!"
131+
echo " $msg"
132+
ERROR=$((ERROR+1))
133+
else
134+
PASS=$((PASS+1))
135+
echo "PASS: $function:L$lineno - $msg"
136+
fi
137+
}
138+
139+
95140
# Print a summary of passing and failing tests and exit
96141
# (with an error if we have failed tests)
97142
# usage: report_results

0 commit comments

Comments
 (0)