I was looking to clean up packages I had installed on my system a bit
because there is a lot of them installed that I don't use at all. I was a
bit suprised there wasn't a tool around that would give me a dependancy
graph or reference count for packages. So, I wrote this woefully
inefficient nasty little perl script. Dont bother commenting on it's
efficiency, how it could have been better or how I could have written it
in one line, I'm not really interested :-) . It does the following
o Reference counts packages
o Prints out packages with only one reference to ./debian_package.single
o Produces a graph of package dependances with a reference count < 2 to
./debian_package.graph
o Generates a postscript file of graph with dot
It was ./debian_package.single I was interested in but when DEPTHRESHOLD
is set to something really high, it produces a mildly amusing, albeit
worthless (461 edges point to libc) graph. Thought the script might be
of use to someone so here it is
#!/usr/bin/perl
use strict;
# Global variables
my $DEB_INSTALLED="/var/lib/dpkg/status";
my $GRAPH="./debian_package.graph";
my $SINGLECOUNT="./debian_package.single";
my $DEPTHRESHOLD=2;
# Input variables
my $line;
my $package;
my $dependlist;
my $depend;
my $dummy;
my $count=0;
my $status;
my %depcount;
# Open files
open (INPUT , $DEB_INSTALLED) || die ("Failed to open input file");
open (OUTPUT, ">$GRAPH") || die("Failed to open output file");
open (SINGLE, ">$SINGLECOUNT") || die("Failed to open output file");
# Print headers
print OUTPUT "digraph debian {\n";
print OUTPUT "node [ fontname=Helvetica,fontsize=8 ];\n";
# Read installed file and do a package reference count
print "Generating reference count\n";
$line=<INPUT>;
while (!eof(INPUT) )
{
# Read to package
while ($line !~ /^Package:/ && !eof(INPUT)) { $line = <INPUT>; }
# Get package name
chomp($line);
($dummy, $package) = split(/ /, $line);
# Read status
$line = <INPUT>;
($dummy, $status) = split(/ /, $line);
if ($status eq "install")
{
# Read forward to depends
while ($line !~ /Depends:/ && !eof(INPUT)) { $line = <INPUT>; chomp($line); }
if (!eof(INPUT))
{
$dependlist = $line;
$dependlist =~ s/Depends: //;
# Reference count
foreach $depend (split(/,/, $dependlist))
{
# Remove version
$depend =~ s/\(.*\)//;
$depcount{"$depend"}++;
}
}
}
}
# Read installed file and print out depends
print "Generating graph\n";
seek INPUT, 0, 0;
$line=<INPUT>;
while (!eof(INPUT) )
{
# Read to package
while ($line !~ /^Package:/ && !eof(INPUT)) { $line = <INPUT>; }
# Read status
$line = <INPUT>;
($dummy, $status) = split(/ /, $line);
if ($status eq "install")
{
# Get package name
chomp($line);
($dummy, $package) = split(/ /, $line);
# Print out if only single reference
if ($depcount{$package} == 0) { print SINGLE "$package\n"; }
# Read forward to depends
while ($line !~ /Depends:/ && !eof(INPUT)) { $line = <INPUT>; chomp($line); }
if (!eof(INPUT))
{
$dependlist = $line;
$dependlist =~ s/Depends: //;
# Print out depends list
foreach $depend (split(/,/, $dependlist))
{
# Remove version
$depend =~ s/\(.*\)//;
# Output dependancy
if ($depcount{"$depend"} < $DEPTHRESHOLD)
{
print OUTPUT "\"$package\" -> \"$depend (" . $depcount{"$depend"} . ")\";\n";
}
}
}
}
}
# Close graph
print OUTPUT "}\n";
# Generate graph
print "Generating graph postscript....\n";
system("dot -Tps $GRAPH -o dependancies.ps");
# Close files
close INPUT;
close OUTPUT;
close SINGLE;
--
Mel Gorman
MSc Student, University of Limerick
http://www.csn.ul.ie/~mel
Maintained by the ILUG website team. The aim of Linux.ie is to
support and help commercial and private users of Linux in Ireland. You can
display ILUG news in your own webpages, read backend
information to find out how. Networking services kindly provided by HEAnet, server kindly donated by
Dell. Linux is a trademark of Linus Torvalds,
used with permission. No penguins were harmed in the production or maintenance
of this highly praised website. Looking for the
Indian Linux Users' Group? Try here. If you've read all this and aren't a lawyer: you should be!