Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Oct 2000 07:00:15 +0900
From:      "Akinori MUSHA" <knu@idaemons.org>
To:        freebsd-ports@FreeBSD.org
Cc:        bmah@FreeBSD.org
Subject:   Re: Enhancement of pkg_version's version comparison routine
Message-ID:  <863dhj2rgw.wl@archon.local.idaemons.org>
In-Reply-To: <86vgvi49a0.wl@archon.local.idaemons.org>
References:  <86k8by6eis.wl@archon.local.idaemons.org> <vqcog1aohm7.fsf@silvia.hip.berkeley.edu> <86wvfy4etq.wl@archon.local.idaemons.org> <vqc1yy6o01x.fsf@silvia.hip.berkeley.edu> <86vgvi49a0.wl@archon.local.idaemons.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Is this patch forgotten?  pkg_version still does not conform to the
version comparison rules specified in the Handbook.

Aside from the introduction of `-t' option, at least CompareNumbers()
part should be taken in unless there is a better implementation, I
think.

At Wed, 27 Sep 2000 15:51:51 +0900,
I wrote:
> 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/27 06:48:31
> @@ -57,38 +57,83 @@
>  # 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;
> -	}
> -	# Check for numeric inequality.  We assume here that (for example)
> -	# 3.09 < 3.10.
> -	elsif ($p1 != $p2) {
> -	    return $p1 <=> $p2;
> +    # 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 =~ /^\D/) {		# $x1: non-number
> +	if ($x2 !~ /^\D/) {	#	        vs. $x2: number or null
> +	    return -1;		# -> $x2 wins
>  	}
> -	# 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;
> +
> +	if ($x1 ne $x2) {	#               vs. $x2: non-number
> +	    return $x1 cmp $x2;	# -> Compare in dictionary order
>  	}
> +    } elsif ($x2 =~ /^\D/) {	# $x1: number or null vs. $x2: non-number
> +	return 1;		# -> $x1 wins
>      }
>  
> +    # 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/) {		# $x1: number
> +	if ($x2 =~ /^\d/) {	#               vs. $x2: number
> +	    return $x1 <=> $x2; # -> Compare numerically
> +	}
> +				#               vs. $x2: non-number or null
> +	return 1;		# -> $x1 wins
> +    }
> +				# $x1: non-number or null
> +    if ($x2 =~ /^\d/) {		#               vs. $x2: number
> +	return -1;		# -> $x2 wins
> +    }
> +				#               vs. $x2: non-number or null
> +    return $x1 cmp $x2;		# -> Compare in dictionary order
>  }
>  
>  #
> @@ -197,6 +242,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 +252,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 +264,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 ? 0 : 1);
> +    }
> +
> +    if ($op =~ />/) {
> +	exit($cmp > 0 ? 0 : 1);
> +    }
> +
> +    if ($op =~ /!/) {
> +	exit($cmp != 0 ? 0 : 1);
> +    }
> +
> +    exit($cmp == 0 ? 0 : 1);
>  }
>  if ($opt_v) {
>      $VerboseFlag = 1;

-- 
                           /
                          /__  __
                         / )  )  ) )  /    and.or.jp / ruby-lang.org
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"


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?863dhj2rgw.wl>