#3655 - add two new subroutines for comparing rpm versions

This commit is contained in:
nott 2013-09-05 13:05:39 -04:00
parent 3b82ab0817
commit 0fac74810f

View File

@ -29,8 +29,8 @@ if ( -f "/etc/debian_version" ) {
else {
$sha1support = eval {
require Digest::SHA1;
1;
require Digest::SHA1;
1;
};
}
use IPC::Open3;
@ -51,6 +51,158 @@ This program module file, is a set of utilities used by xCAT buildkit command
#-------------------------------------------------------------
#--------------------------------------------------------------------------
=head3 get_latest_version
Find the latest version in a list of rpms with the same basename
Arguments:
- the repo location
- a list of rpms with the same basename
Returns:
- name of rpm
- undef
Example:
my $new_d = xCAT::BuildKitUtils->get_latest_version($repodir, \@rpmlist);
Comments:
=cut
#--------------------------------------------------------------------------
sub get_latest_version
{
my ($class, $repodir, $rpms) = @_;
my @rpmlist = @$rpms;
my %localversions_hash = ();
my %file_name_hash = ();
my $i = 0;
foreach my $rpm (@rpmlist)
{
# include path
my $fullrpmpath = "$repodir/$rpm*";
# get the basename, version, and release for this rpm
my $rcmd = "rpm -qp --queryformat '%{N} %{V} %{R}\n' $repodir/$rpm*";
my $out = `$rcmd`;
my ($rpkg, $VERSION, $RELEASE) = split(' ', $out);
chomp $VERSION;
chomp $RELEASE;
$localversions_hash{$i}{'VERSION'} = $VERSION;
$localversions_hash{$i}{'RELEASE'} = $RELEASE;
$file_name_hash{$VERSION}{$RELEASE} = $rpm;
$i++;
}
if ($i == 0)
{
print "error\n";
return undef;
}
my $versionout = "";
my $releaseout = "";
$i = 0;
foreach my $k (keys %localversions_hash)
{
if ($i == 0)
{
$versionout = $localversions_hash{$k}{'VERSION'};
$releaseout = $localversions_hash{$k}{'RELEASE'};
}
# if this is a newer version/release then set them
if ( xCAT::BuildKitUtils->testVersion($localversions_hash{$k}{'VERSION'}, ">", $versionout, $localversions_hash{$k}{'RELEASE'}, $releaseout) ) {
$versionout = $localversions_hash{$k}{'VERSION'};
$releaseout = $localversions_hash{$k}{'RELEASE'};
}
$i++;
}
return ($file_name_hash{$versionout}{$releaseout});
}
#------------------------------------------------------------------------------
=head3 testVersion
Compare version1 and version2 according to the operator and
return True or False.
Arguments:
$version1
$operator
$version2
$release1
$release2
Returns:
True or False
Example:
Comments:
The return value is generated with the Require query of the
rpm command.
=cut
#-----------------------------------------------------------------------------
sub testVersion
{
my ($class, $version1, $operator, $version2, $release1, $release2) = @_;
my @a1 = split(/\./, $version1);
my @a2 = split(/\./, $version2);
my $len = (scalar(@a1) > scalar(@a2) ? scalar(@a1) : scalar(@a2));
$#a1 = $len - 1; # make the arrays the same length before appending release
$#a2 = $len - 1;
push @a1, split(/\./, $release1);
push @a2, split(/\./, $release2);
$len = (scalar(@a1) > scalar(@a2) ? scalar(@a1) : scalar(@a2));
my $num1 = '';
my $num2 = '';
for (my $i = 0 ; $i < $len ; $i++)
{
# remove any non-numbers on the end
my ($d1) = $a1[$i] =~ /^(\d*)/;
my ($d2) = $a2[$i] =~ /^(\d*)/;
my $diff = length($d1) - length($d2);
if ($diff > 0) # pad d2
{
$num1 .= $d1;
$num2 .= ('0' x $diff) . $d2;
}
elsif ($diff < 0) # pad d1
{
$num1 .= ('0' x abs($diff)) . $d1;
$num2 .= $d2;
}
else # they are the same length
{
$num1 .= $d1;
$num2 .= $d2;
}
}
# Remove the leading 0s or perl will interpret the numbers as octal
$num1 =~ s/^0+//;
$num2 =~ s/^0+//;
# be sure that $num1 is not a "".
if (length($num1) == 0) { $num1 = 0; }
if (length($num2) == 0) { $num2 = 0; }
if ($operator eq '=') { $operator = '=='; }
my $bool = eval "$num1 $operator $num2";
return $bool;
}
#-------------------------------------------------------------------------------
@ -112,95 +264,6 @@ sub get_OS_VRMF
return (length($version) ? $version : undef);
}
#----------------------------------------------------------------------------
=head3 testversion
Compare version1 and version2 according to the operator and
return True or False.
Arguments:
$version1
$operator
$version2
$release1
$release2
Returns:
True or False
Example:
if (BuildKitUtils->testversion ( $ins_ver,
"<",
$req_ver,
$ins_rel,
$req_rel)){ blah; }
Comments:
=cut
#-------------------------------------------------------------------------------
sub testversion
{
my ($class, $version1, $operator, $version2, $release1, $release2) = @_;
my @a1 = split(/\./, $version1);
my @a2 = split(/\./, $version2);
my $len = (scalar(@a1) > scalar(@a2) ? scalar(@a1) : scalar(@a2));
$#a1 = $len - 1; # make the arrays the same length before appending release
$#a2 = $len - 1;
push @a1, split(/\./, $release1);
push @a2, split(/\./, $release2);
$len = (scalar(@a1) > scalar(@a2) ? scalar(@a1) : scalar(@a2));
my $num1 = '';
my $num2 = '';
for (my $i = 0 ; $i < $len ; $i++)
{
my ($d1) = $a1[$i] =~ /^(\d*)/; # remove any non-numbers on the end
my ($d2) = $a2[$i] =~ /^(\d*)/;
my $diff = length($d1) - length($d2);
if ($diff > 0) # pad d2
{
$num1 .= $d1;
$num2 .= ('0' x $diff) . $d2;
}
elsif ($diff < 0) # pad d1
{
$num1 .= ('0' x abs($diff)) . $d1;
$num2 .= $d2;
}
else # they are the same length
{
$num1 .= $d1;
$num2 .= $d2;
}
}
# Remove the leading 0s or perl will interpret the numbers as octal
$num1 =~ s/^0+//;
$num2 =~ s/^0+//;
#SLES Changes ??
# if $num1="", the "eval '$num1 $operator $num2'" will fail.
# So MUST BE be sure that $num1 is not a "".
if (length($num1) == 0) { $num1 = 0; }
if (length($num2) == 0) { $num2 = 0; }
#End of SLES Changes
if ($operator eq '=') { $operator = '=='; }
my $bool = eval "$num1 $operator $num2";
if (length($@))
{
# error msg ?
}
return $bool;
}
#-------------------------------------------------------------------------------
=head3 isLinux