#!/usr/bin/perl use strict; use Data::Dumper; use RPM::VersionSort; use Memoize; # kadang2 ada lebih dari satu package yang memprovide sebuah capability, # blacklistlah package yang gak diperlukan disini... di antara package2 # yang memprovide capability itu biasanya cuma satu yang diperlukan our @blacklist = qw( mod_perl kernel-smp kdebindings mrtg sendmail exim ); # dbpath path ke database rpm... # /usr/lib/rpmdb/i386-redhat-linux/redhat adalah path database rpmdb-fedora # /var/lib/rpm adalah path dari database sistem our $dbpath = "/usr/lib/rpmdb/i386-redhat-linux/redhat"; our $queries = 0; our %alldeps; #memoize('rpm_qf'); memoize('rpm_whatprovides'); memoize('rpm_qR'); our %blacklist = map { $_ => 1 } @blacklist; foreach (@ARGV) { querydeps($_); } while(1) { my $alldone = 1; foreach (keys %alldeps) { my $status = $alldeps{$_}; if ($status == 0) { $alldone = 0; querydeps($_); } } if ($alldone == 1) { last; } } print "\n"; print "Saving output to rpmquerydeps.out\n"; open(LIST, "> rpmquerydeps.out"); foreach (sort keys %alldeps) { print LIST "$_\n"; } close LIST; sub querydeps { my $toquery = shift; print "resolving dependencies of $toquery\n"; my @alldeps = rpm_qR($toquery); foreach (@alldeps) { my $capability = $_; if (m#^/\S+$#) { # misalnya: /bin/sh my @deps = rpm_whatprovides($_); foreach (@deps) { if (! exists($alldeps{$_})) { print " adding $_, triggered by $capability\n"; $alldeps{$_} = 0; } } } elsif (m#^(\S+)\s+(\S+)\s+(\S+)$#) { # misalnya: foo >= 1.0 my $dep = $1; my $minver = $3; $minver =~ s/^.*://g; my @dep = rpm_whatprovides($dep); foreach (@dep) { my ($rel, $ver, @package) = reverse(split(/-/, $_)); if (rpmvercmp($minver, $ver) <= 0) { if (! exists($alldeps{$_})) { print " adding $_, triggered by $capability\n"; $alldeps{$_} = 0; } } } } elsif (m#^rpmlib#) { # misalnya: rpmlib(CompressedFileNames) blah next; } elsif (m#^\S+$#) { # lain-lainnya my @dep = rpm_whatprovides($_); foreach (@dep) { if (! exists($alldeps{$_})) { print " adding $_, triggered by $capability\n"; $alldeps{$_} = 0; } } } else { # catchall print " ERROR: dependency $_ is not counted!\n"; } } my @packagename = rpm_q($toquery); foreach(@packagename) { $alldeps{$_} = 1; } } #sub rpm_qf { # my $file = shift; # my @dep = `rpm --dbpath $dbpath -qf "$file"`; # if (scalar @dep > 1) { # print " WARNING: multiple packages own file $file: @dep\n"; # } # $queries++; # foreach (@dep) { # chomp; # s/^\s+//g; # s/\s+$//g; # } # return @dep; #} sub rpm_q { my $package = shift; my @resolved = `rpm --dbpath $dbpath -q "$package"`; $queries++; foreach (@resolved) { chomp; s/^\s+//g; s/\s+$//g; } return @resolved; } sub rpm_whatprovides { my $thing = shift; my @packages = `rpm --dbpath $dbpath -q --whatprovides "$thing"`; foreach (@packages) { chomp; s/^\s+//g; s/\s+$//g; } my %packages = map { $_ => 1 } @packages; @packages = keys %packages; my @newpackages; foreach (@packages) { my ($rel, $ver, @package) = reverse(split(/-/, $_)); my $package = join("-", reverse @package); if (exists $blacklist{$package}) { print " WARNING: package $package is blacklisted\n"; } else { push @newpackages, "$package-$ver-$rel"; } } if (scalar @newpackages > 1) { print " WARNING: multiple packages provides $thing: @newpackages\n"; } $queries++; return @newpackages; } sub rpm_qR { my $toquery = shift; my @alldeps = `rpm --dbpath $dbpath -qR $toquery`; $queries++; foreach (@alldeps) { chomp; s/^\s+//g; s/\s+$//g; } return @alldeps; }