gen_rpmlists
#!/usr/bin/perl -w
#
# make lists of "newest" RPMs in directory trees;
#
use strict;
use File::Find;
my @distlist = qw(valhalla psyche shrike); # maintained distributions
my $dist; # each distribution
my $base_url = "http://tautology.unh.edu/linux"; # where RPMs are found on web
my $base_dir = "/usr/local/misc"; # where distribution directories are
my $list_dir = "$base_dir/cislinux"; # where generated lists are
my %url_of; # URL for a given name/arch
my %version_of; # newest version seen for a given name/arch
my %release_of; # newest release seen for a given name/arch
my $key; # iterator
my @distdirs; # directories for a given distribution
my $dir; # each directory processed
my $name; # name of package
my $arch; # architecture of package
foreach $dist (@distlist) {
undef %url_of;
undef %version_of;
undef %release_of;
print "Doing $dist...\n";
@distdirs = glob("$base_dir/${dist}*");
foreach $dir (@distdirs) {
print "Scanning $dir...\n";
find( { wanted => \&wanted, follow => 0 }, $dir );
}
open( F, ">$list_dir/${dist}_rpms" )
|| die "Opening output file for $dist failed: $!\n";
foreach $key ( keys %url_of ) {
( $name, $arch ) = split ( /,/, $key );
print F
"$url_of{$key} $name $version_of{$key} $release_of{$key} $arch\n";
}
close(F);
}
sub wanted {
my $url; # URL for the file
my $poop; # rpm -qp output for file
my ( $name, $version, $release, $arch ); # split-up output
my $result; # comparison result
if (/^.*\.rpm\z/s) {
( $url = $File::Find::name ) =~ s^$base_dir^$base_url^;
chomp( $poop =
`/bin/rpm -qp --queryformat '%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n' $_`
);
( $name, $version, $release, $arch ) = split ( / /, $poop );
if ( $url_of{"$name,$arch"} ) { # already seen a URL for this...
$result = rpmvercmp( $version, $version_of{"$name,$arch"} );
if (
$result > 0
|| ( $result == 0
&& rpmvercmp( $release, $release_of{"$name,$arch"} ) > 0 )
)
{
$url_of{"$name,$arch"} = $url;
$version_of{"$name,$arch"} = $version;
$release_of{"$name,$arch"} = $release;
}
}
else {
$url_of{"$name,$arch"} = $url;
$version_of{"$name,$arch"} = $version;
$release_of{"$name,$arch"} = $release;
}
}
}
sub rpmverparse {
my ($ver) = @_;
my @verparts = ();
while ( $ver ne "" ) {
if ( $ver =~ /^([A-Za-z]+)/ ) { # leading letters
push ( @verparts, $1 );
$ver =~ s/^[A-Za-z]+//;
}
elsif ( $ver =~ /^(\d+)/ ) { # leading digits
push ( @verparts, $1 );
$ver =~ s/^\d+//;
}
else { # remove non-letter, non-digit
$ver =~ s/^.//;
}
}
return @verparts;
}
sub rpmvercmp {
my ( $a, $b ) = @_;
my @aparts;
my @bparts; # array of version "tokens"
my $apart;
my $bpart;
my $result;
if ( $a eq $b ) {
return 0;
}
@aparts = rpmverparse($a);
@bparts = rpmverparse($b);
while ( @aparts && @bparts ) {
$apart = shift (@aparts);
$bpart = shift (@bparts);
if ( $apart =~ /^\d+$/ && $bpart =~ /^\d+$/ ) { # numeric
if ( $result = ( $apart <=> $bpart ) ) {
return $result;
}
}
elsif ( $apart =~ /^[A-Za-z]+/ && $bpart =~ /^[A-Za-z]+/ ) { # alpha
if ( $result = ( $apart cmp $bpart ) ) {
return $result;
}
}
else { # "arbitrary" in original code
return -1;
}
}
if (@aparts) { # left over stuff in a, assume it's newer
return 1;
}
elsif (@bparts) { # leftover in b, assume it's newer
return -1;
}
else { # "should never happen"
return 0;
}
}