Commit 26724018 authored by Frédéric Buclin's avatar Frédéric Buclin

Bug 938300: vers_cmp() incorrectly compares module versions

r=sgreen a=justdave
parent e21cee47
...@@ -17,11 +17,12 @@ use parent -norequire, qw(DBI::db); ...@@ -17,11 +17,12 @@ use parent -norequire, qw(DBI::db);
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Install::Requirements; use Bugzilla::Install::Requirements;
use Bugzilla::Install::Util qw(vers_cmp install_string); use Bugzilla::Install::Util qw(install_string);
use Bugzilla::Install::Localconfig; use Bugzilla::Install::Localconfig;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::DB::Schema; use Bugzilla::DB::Schema;
use Bugzilla::Version;
use List::Util qw(max); use List::Util qw(max);
use Storable qw(dclone); use Storable qw(dclone);
......
...@@ -17,7 +17,7 @@ use 5.10.1; ...@@ -17,7 +17,7 @@ use 5.10.1;
use strict; use strict;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Install::Util qw(vers_cmp install_string bin_loc use Bugzilla::Install::Util qw(install_string bin_loc
extension_requirement_packages); extension_requirement_packages);
use List::Util qw(max); use List::Util qw(max);
use Term::ANSIColor; use Term::ANSIColor;
...@@ -86,7 +86,6 @@ use constant APACHE_PATH => [qw( ...@@ -86,7 +86,6 @@ use constant APACHE_PATH => [qw(
# are 'blacklisted'--that is, even if the version is high enough, Bugzilla # are 'blacklisted'--that is, even if the version is high enough, Bugzilla
# will refuse to say that it's OK to run with that version. # will refuse to say that it's OK to run with that version.
sub REQUIRED_MODULES { sub REQUIRED_MODULES {
my $perl_ver = sprintf('%vd', $^V);
my @modules = ( my @modules = (
{ {
package => 'CGI.pm', package => 'CGI.pm',
...@@ -125,7 +124,7 @@ sub REQUIRED_MODULES { ...@@ -125,7 +124,7 @@ sub REQUIRED_MODULES {
{ {
package => 'DBI', package => 'DBI',
module => 'DBI', module => 'DBI',
version => (vers_cmp($perl_ver, '5.13.3') > -1) ? '1.614' : '1.54' version => ($^V >= v5.13.3) ? '1.614' : '1.54'
}, },
# 2.24 contains several useful text virtual methods. # 2.24 contains several useful text virtual methods.
{ {
...@@ -187,7 +186,6 @@ sub REQUIRED_MODULES { ...@@ -187,7 +186,6 @@ sub REQUIRED_MODULES {
}; };
sub OPTIONAL_MODULES { sub OPTIONAL_MODULES {
my $perl_ver = sprintf('%vd', $^V);
my @modules = ( my @modules = (
{ {
package => 'GD', package => 'GD',
...@@ -198,8 +196,9 @@ sub OPTIONAL_MODULES { ...@@ -198,8 +196,9 @@ sub OPTIONAL_MODULES {
{ {
package => 'Chart', package => 'Chart',
module => 'Chart::Lines', module => 'Chart::Lines',
# Versions below 2.1 cannot be detected accurately. # Versions below 2.4.1 cannot be compared accurately, see
version => '2.1', # https://rt.cpan.org/Public/Bug/Display.html?id=28218.
version => '2.4.1',
feature => [qw(new_charts old_charts)], feature => [qw(new_charts old_charts)],
}, },
{ {
...@@ -314,7 +313,7 @@ sub OPTIONAL_MODULES { ...@@ -314,7 +313,7 @@ sub OPTIONAL_MODULES {
# We need the 'utf8_mode' method of HTML::Parser, for HTML::Scrubber. # We need the 'utf8_mode' method of HTML::Parser, for HTML::Scrubber.
package => 'HTML-Parser', package => 'HTML-Parser',
module => 'HTML::Parser', module => 'HTML::Parser',
version => (vers_cmp($perl_ver, '5.13.3') > -1) ? '3.67' : '3.40', version => ($^V >= v5.13.3) ? '3.67' : '3.40',
feature => ['html_desc'], feature => ['html_desc'],
}, },
{ {
...@@ -668,8 +667,8 @@ sub check_graphviz { ...@@ -668,8 +667,8 @@ sub check_graphviz {
return $return; return $return;
} }
# This was originally clipped from the libnet Makefile.PL, adapted here to # This was originally clipped from the libnet Makefile.PL, adapted here for
# use the below vers_cmp routine for accurate version checking. # accurate version checking.
sub have_vers { sub have_vers {
my ($params, $output) = @_; my ($params, $output) = @_;
my $module = $params->{module}; my $module = $params->{module};
...@@ -694,15 +693,17 @@ sub have_vers { ...@@ -694,15 +693,17 @@ sub have_vers {
if ($@) { if ($@) {
no strict 'refs'; no strict 'refs';
$vnum = ${"${module}::VERSION"}; $vnum = ${"${module}::VERSION"};
}
$vnum ||= -1;
# Fix CPAN versions like 1.9304. # If we come here, then the version is not a valid one.
if ($module eq 'CPAN' and $vnum =~ /^(\d\.\d{2})\d{2}$/) { # We try to sanitize it.
$vnum = $1; if ($vnum =~ /^((\d+)(\.\d+)*)/) {
$vnum = $1;
}
} }
$vnum ||= -1;
my $vok = (vers_cmp($vnum,$wanted) > -1); # Must do a string comparison as $vnum may be of the form 5.10.1.
my $vok = ($vnum ne '-1' && version->new($vnum) >= version->new($wanted)) ? 1 : 0;
my $blacklisted; my $blacklisted;
if ($vok && $params->{blacklist}) { if ($vok && $params->{blacklist}) {
$blacklisted = grep($vnum =~ /$_/, @{$params->{blacklist}}); $blacklisted = grep($vnum =~ /$_/, @{$params->{blacklist}});
......
...@@ -38,7 +38,6 @@ our @EXPORT_OK = qw( ...@@ -38,7 +38,6 @@ our @EXPORT_OK = qw(
include_languages include_languages
success success
template_include_path template_include_path
vers_cmp
init_console init_console
); );
...@@ -476,49 +475,6 @@ sub template_include_path { ...@@ -476,49 +475,6 @@ sub template_include_path {
return \@include_path; return \@include_path;
} }
# This is taken straight from Sort::Versions 1.5, which is not included
# with perl by default.
sub vers_cmp {
my ($a, $b) = @_;
# Remove leading zeroes - Bug 344661
$a =~ s/^0*(\d.+)/$1/;
$b =~ s/^0*(\d.+)/$1/;
my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g);
my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g);
my ($A, $B);
while (@A and @B) {
$A = shift @A;
$B = shift @B;
if ($A eq '-' and $B eq '-') {
next;
} elsif ( $A eq '-' ) {
return -1;
} elsif ( $B eq '-') {
return 1;
} elsif ($A eq '.' and $B eq '.') {
next;
} elsif ( $A eq '.' ) {
return -1;
} elsif ( $B eq '.' ) {
return 1;
} elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) {
if ($A =~ /^0/ || $B =~ /^0/) {
return $A cmp $B if $A cmp $B;
} else {
return $A <=> $B if $A <=> $B;
}
} else {
$A = uc $A;
$B = uc $B;
return $A cmp $B if $A cmp $B;
}
}
@A <=> @B;
}
sub no_checksetup_from_cgi { sub no_checksetup_from_cgi {
print "Content-Type: text/html; charset=UTF-8\r\n\r\n"; print "Content-Type: text/html; charset=UTF-8\r\n\r\n";
print install_string('no_checksetup_from_cgi'); print install_string('no_checksetup_from_cgi');
...@@ -894,28 +850,6 @@ Used by L<Bugzilla::Template> to determine the languages' list which ...@@ -894,28 +850,6 @@ Used by L<Bugzilla::Template> to determine the languages' list which
are compiled with the browser's I<Accept-Language> and the languages are compiled with the browser's I<Accept-Language> and the languages
of installed templates. of installed templates.
=item C<vers_cmp>
=over
=item B<Description>
This is a comparison function, like you would use in C<sort>, except that
it compares two version numbers. So, for example, 2.10 would be greater
than 2.2.
It's based on versioncmp from L<Sort::Versions>, with some Bugzilla-specific
fixes.
=item B<Params>: C<$a> and C<$b> - The versions you want to compare.
=item B<Returns>
C<-1> if C<$a> is less than C<$b>, C<0> if they are equal, or C<1> if C<$a>
is greater than C<$b>.
=back
=back =back
=head1 B<Methods in need of POD> =head1 B<Methods in need of POD>
......
...@@ -10,9 +10,10 @@ package Bugzilla::Version; ...@@ -10,9 +10,10 @@ package Bugzilla::Version;
use 5.10.1; use 5.10.1;
use strict; use strict;
use parent qw(Bugzilla::Object); use parent qw(Bugzilla::Object Exporter);
@Bugzilla::Version::EXPORT = qw(vers_cmp);
use Bugzilla::Install::Util qw(vers_cmp);
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
...@@ -200,6 +201,53 @@ sub _check_product { ...@@ -200,6 +201,53 @@ sub _check_product {
return Bugzilla->user->check_can_admin_product($product->name); return Bugzilla->user->check_can_admin_product($product->name);
} }
###############################
##### Functions ####
###############################
# This is taken straight from Sort::Versions 1.5, which is not included
# with perl by default.
sub vers_cmp {
my ($a, $b) = @_;
# Remove leading zeroes - Bug 344661
$a =~ s/^0*(\d.+)/$1/;
$b =~ s/^0*(\d.+)/$1/;
my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g);
my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g);
my ($A, $B);
while (@A and @B) {
$A = shift @A;
$B = shift @B;
if ($A eq '-' and $B eq '-') {
next;
} elsif ( $A eq '-' ) {
return -1;
} elsif ( $B eq '-') {
return 1;
} elsif ($A eq '.' and $B eq '.') {
next;
} elsif ( $A eq '.' ) {
return -1;
} elsif ( $B eq '.' ) {
return 1;
} elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) {
if ($A =~ /^0/ || $B =~ /^0/) {
return $A cmp $B if $A cmp $B;
} else {
return $A <=> $B if $A <=> $B;
}
} else {
$A = uc $A;
$B = uc $B;
return $A cmp $B if $A cmp $B;
}
}
return @A <=> @B;
}
1; 1;
__END__ __END__
...@@ -243,11 +291,51 @@ below. ...@@ -243,11 +291,51 @@ below.
=item C<bug_count()> =item C<bug_count()>
Description: Returns the total of bugs that belong to the version. =over
=item B<Description>
Returns the total of bugs that belong to the version.
=item B<Params>
none
=item B<Returns>
Integer with the number of bugs.
=back
=back
=head1 FUNCTIONS
=over
=item C<vers_cmp($a, $b)>
=over
=item B<Description>
This is a comparison function, like you would use in C<sort>, except that
it compares two version numbers. So, for example, 2.10 would be greater
than 2.2.
It's based on versioncmp from L<Sort::Versions>, with some Bugzilla-specific
fixes.
Params: none. =item B<Params>
Returns: Integer with the number of bugs. C<$a> and C<$b> - The versions you want to compare.
=item B<Returns>
C<-1> if C<$a> is less than C<$b>, C<0> if they are equal, or C<1> if C<$a>
is greater than C<$b>.
=back
=back =back
......
...@@ -23,7 +23,7 @@ use Bugzilla::Install::CPAN; ...@@ -23,7 +23,7 @@ use Bugzilla::Install::CPAN;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Install::Requirements; use Bugzilla::Install::Requirements;
use Bugzilla::Install::Util qw(bin_loc init_console vers_cmp); use Bugzilla::Install::Util qw(bin_loc init_console);
use Data::Dumper; use Data::Dumper;
use Getopt::Long; use Getopt::Long;
......
...@@ -18,9 +18,9 @@ use Bugzilla::User; ...@@ -18,9 +18,9 @@ use Bugzilla::User;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Product; use Bugzilla::Product;
use Bugzilla::Version;
use Bugzilla::Keyword; use Bugzilla::Keyword;
use Bugzilla::Field; use Bugzilla::Field;
use Bugzilla::Install::Util qw(vers_cmp);
use Bugzilla::Token; use Bugzilla::Token;
############### ###############
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment