From owner-freebsd-ports Tue Sep 26 14:16:51 2000 Delivered-To: freebsd-ports@freebsd.org Received: from ms.tokyo.jcom.ne.jp (ms.tokyo.jcom.ne.jp [210.234.123.18]) by hub.freebsd.org (Postfix) with ESMTP id 5671337B422; Tue, 26 Sep 2000 14:16:14 -0700 (PDT) Received: from daemon.local.idaemons.org (203-165-77-17.sugnm1.kt.home.ne.jp [203.165.77.17]) by ms.tokyo.jcom.ne.jp (8.9.3/3.7W 04/27/00) with ESMTP id GAA01445; Wed, 27 Sep 2000 06:16:10 +0900 (JST) Received: by daemon.local.idaemons.org (8.11.0/3.7W) id e8QLFdI68068; Wed, 27 Sep 2000 06:15:40 +0900 (JST) Date: Wed, 27 Sep 2000 06:15:39 +0900 Message-ID: <86k8by6eis.wl@archon.local.idaemons.org> From: "Akinori -Aki- MUSHA" To: freebsd-ports@FreeBSD.org Cc: bmah@FreeBSD.org Subject: Enhancement of pkg_version's version comparison routine User-Agent: Wanderlust/1.1.2 (Raspberry Beret) EMIKO/1.13.12 (Euglena sociabilis) FLIM/1.13.2 (Kasanui) APEL/10.2 MULE XEmacs/21.1 (patch 12) (Channel Islands) (i386--freebsd) Organization: Associated I. Daemons X-PGP-Public-Key: finger knu@FreeBSD.org X-PGP-Fingerprint: 081D 099C 1705 861D 4B70 B04A 920B EFC7 9FD9 E1EE X-PGP-Comment: I changed my key on 2000-08-10 MIME-Version: 1.0 (generated by EMIKO 1.13.12 - "Euglena sociabilis") Content-Type: text/plain; charset=US-ASCII Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org Hi Bruce and Ports, I made a patch that fixes pkg_version's version comparison routine. In short, it makes pkg_version recognize alpha ("a"), beta ("b"), pre ("p"), and patchlevels as the handbook says. With this fix, comparisons will result as the following: Winer Loser Comment 1.6.0 1.6.0.p3 Pre is before the release (*) 1.0.b 1.0.a3 Beta is after alpha's 1.0a 1.0 A letter "a" means alpha only when it appears after an period. 5.0a 5.0.b Ditto. 3.2.ab1 3.2.p1 "ab" is unknown, but at least it should be after alpha's, beta's and pre's. (*) 2.3pl10 2.3pl9 Patchlevel 10 is after 9, of course (*) where (*) indicates previously it wasn't handled correctly. To perform comparison from scripts, I also implemented `-t' option so you can use it like this: #!/bin/sh version=$(cd /var/db/pkg; echo foobar-* | sed -e 's/.*-//' -e 's/[_,].*//') if pkg_version -t "${version} < 1.5.b5"; then echo "You need foobar version 1.5 beta5 or later installed." exit 1 fi exit 0 Yes, this feature can be used from such as REQ scripts when you need to compare package versions. (until we get more sophisticated pkg_* tools/framework :) Bruce, would you review and approve this change? -- / /__ __ / ) ) ) ) / Akinori -Aki- MUSHA aka / (_ / ( (__( @ idaemons.org / FreeBSD.org "We're only at home when we're on the run, on the wing, on the fly" Index: pkg_version.1 =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/version/pkg_version.1,v retrieving revision 1.8 diff -u -r1.8 pkg_version.1 --- pkg_version.1 2000/09/15 04:16:20 1.8 +++ pkg_version.1 2000/09/26 20:23:39 @@ -35,6 +35,8 @@ .Op Fl cdhv .Op Fl l Ar limchar .Op Ar index +.Nm pkg_version +.Op Fl t Ar expression .Sh DESCRIPTION The .Nm @@ -93,6 +95,44 @@ to the shell, it is best to quote .Ar limchar with single quotes. +.It Fl t +Test an expression and exit. It returns either 0 (true) or 1 (false). +.It Ar expression +Specify the expression to test, in one of the following forms: +.Bl -tag -width Ar +.It Ar \&v\&1 Cm \&= Ar \&v\&2 +True if the versions +.Ar \&v\&1 +and +.Ar \&v\&2 +are identical. +.It Ar \&v\&1 Cm \&!= Ar \&v\&2 +True if the versions +.Ar \&v\&1 +and +.Ar \&v\&2 +are not identical. +.It Ar \&v\&1 Cm \&< Ar \&v\&2 +True if the version +.Ar \&v\&1 +is less than the version +.Ar \&v\&2 . +.It Ar \&v\&1 Cm \&> Ar \&v\&2 +True if the version +.Ar \&v\&1 +is greater than the version +.Ar \&v\&2 . +.It Ar \&v\&1 Cm \&<= Ar \&v\&2 +True if the version +.Ar \&v\&1 +is less than or equal to the version +.Ar \&v\&2 . +.It Ar \&v\&1 Cm \&>= Ar \&v\&2 +True if the version +.Ar \&v\&1 +is greater than or equal to the version +.Ar \&v\&2 . +.El .It Fl v Enable verbose output. Verbose output includes some English-text interpretations of the version number comparisons, as well as the @@ -144,18 +184,20 @@ suggestions, and then cut-and-paste (or retype) the commands you want to run. .Pp .Dl % pkg_version -c > do_update +.Pp +The following command tests if a version is less than another. +.Pp +.Dl % pkg_version -t '1.6.0.p3 < 1.6.0' && echo 'true!' .Sh AUTHOR .An Bruce A. Mah Aq bmah@FreeBSD.org .Sh CONTRIBUTORS .An Nik Clayton Aq nik@FreeBSD.org , .An Dominic Mitchell Aq dom@palmerharvey.co.uk , -.An Mark Ovens Aq marko@FreeBSD.org +.An Mark Ovens Aq marko@FreeBSD.org , +.An Akinori MUSHA Aq knu@FreeBSD.org .Sh BUGS There should be a better way of dealing with packages that can have more than one installed version. -.Pp -Patch levels aren't handled -very well (i.e. version numbers of the form 1.2p3 or 1.2pl3). .Pp Updates to packages that don't change the version number (e.g. small delta bugfixes in the Index: pkg_version.pl =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/version/pkg_version.pl,v retrieving revision 1.10 diff -u -r1.10 pkg_version.pl --- pkg_version.pl 2000/09/15 04:16:20 1.10 +++ pkg_version.pl 2000/09/26 19:55:09 @@ -57,38 +57,87 @@ # This function returns -1, 0, or 1, in the same manner as <=> or cmp. # sub CompareNumbers { - local($v1, $v2); - $v1 = $_[0]; - $v2 = $_[1]; + my($v1, $v2) = @_; # Short-cut in case of equality if ($v1 eq $v2) { return 0; } - # Loop over different components (the parts separated by dots). - # If any component differs, we have the basis for an inequality. - while (1) { - ($p1, $v1) = split(/\./, $v1, 2); - ($p2, $v2) = split(/\./, $v2, 2); - - # If we\'re out of components, they\'re equal (this probably won\'t - # happen, since the short-cut case above should get this). - if (($p1 eq "") && ($p2 eq "")) { - return 0; + # Split into subnumbers + my @s1 = split(/\./, $v1); + my @s2 = split(/\./, $v2); + + # Subnumbers + my($s1, $s2); + + # Seek for the difference + do { + last unless @s1 || @s2; + + $s1 = shift @s1; + $s2 = shift @s2; + } while ($s1 eq $s2); + + # Short-cut in case of equality + if ($s1 eq $s2) { + return 0; + } + + # Split into sub-subnumbers + my @x1 = split(/(\D+)/, $s1); + my @x2 = split(/(\D+)/, $s2); + + shift @x1 if ($s1 =~ /^\D/); + shift @x2 if ($s2 =~ /^\D/); + + # Sub-subnumbers + my $x1 = shift @x1; + my $x2 = shift @x2; + + # Check for alpha, beta, or pre + if ($x1 =~ /^[abp]$/) { + if ($x2 !~ /^[abp]$/) { + return -1; # A non-abp (including null) wins over an abp } - # Check for numeric inequality. We assume here that (for example) - # 3.09 < 3.10. - elsif ($p1 != $p2) { - return $p1 <=> $p2; + + if ($x1 ne $x2) { + return $x1 cmp $x2; # Accidentally, 'a' < 'b' < 'p' :) } - # Check for string inequality, given numeric equality. This - # handles version numbers of the form 3.4j < 3.4k. - elsif ($p1 ne $p2) { - return $p1 cmp $p2; + } elsif ($x2 =~ /^[abp]$/) { + return 1; # A non-abp (including null) wins over an abp + } + + # Seek for the difference + while ($x1 eq $x2) { + last unless @x1 || @x2; + + $x1 = shift @x1; + $x2 = shift @x2; + } + + # Short-cut in case of equality + if ($x1 eq $x2) { + return 0; + } + + if ($x1 =~ /^\d/) { + if ($x2 =~ /^\d/) { + # Both numbers: compare numerically + return $x1 <=> $x2; } + + # A number wins over non-numbers + return 1; } + if ($x2 =~ /^\d/) { + # A number wins over non-numbers + return -1; + } + + # Both non-numbers: compare as strings + return $x1 cmp $x2; } # @@ -197,6 +246,7 @@ -d debug Debugging output (debug controls level of output) -h Help (this message) -l limchar Limit output +-t expr Test expression -v Verbose output index URL or filename of index file (Default is $IndexFile) @@ -206,7 +256,7 @@ # # Parse command-line arguments, deal with them # -if (!getopts('cdhl:v') || ($opt_h)) { +if (!getopts('cdhl:t:v') || ($opt_h)) { &PrintHelp(); exit; } @@ -218,6 +268,34 @@ } if ($opt_l) { $LimitFlag = $opt_l; +} +if ($opt_t) { + my $expr = $opt_t; + + $expr =~ s/\s+//g; + + my($v1, $op, $v2) = split(/([<>]=?|=|!=|)/, $expr, 2); + + if ($v2 eq '') { + print "Invalid expression: $expr\n"; + exit -1; + } + + my $cmp = CompareVersions($v1, $v2); + + if ($op =~ //) { + exit($cmp > 0); + } + + if ($op =~ /!/) { + exit($cmp != 0); + } + + exit($cmp == 0); } if ($opt_v) { $VerboseFlag = 1; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message