#!/usr/bin/perl -w
# $Id: pkg_tree,v 1.2 2001/12/12 11:38:47 mavetju Exp $
#
# PKG-TREE
#
# Generates a ascii-art-graphical tree of packages and their dependancies.
# For example for itk-3.2_1:
#
# [~] edwin@k7>pkg_tree itk
# itk-3.2_1
# |\__ freetype2-2.0.4
# |\__ tcl-8.3.3_3 (unknown)
# |\__ itcl-3.2
# | \__ tcl-8.3.3_3 (unknown)
# |\__ imake-4.1.0 (unknown)
# |\__ tk-8.3.3
# | |\__ tcl-8.3.3_3 (unknown)
# | |\__ imake-4.1.0 (unknown)
# | |\__ freetype2-2.0.4
# | \__ XFree86-libraries-4.1.0 (unknown)
# \__ XFree86-libraries-4.1.0 (unknown)
#
# Unknown means that the package is no longer in /var/db/pkg, most likely
# updated by a newer version. In case of tcl-8.3.3_3, this is tcl-8.3.3_4.
#
# PKG-TREE is (c) Edwin Groothuis, edwin@mavetju.org
# For license issues, see the file LICENSE.
# For more information, see the website: http://www.mavetju.org
#
use strict;
use Getopt::Std;
use vars qw/ $opt_b $opt_q $opt_t $opt_v /;
$opt_v=0;
$opt_t=0;
$opt_b=0;
$opt_q=0;
getopts("bqtv");
my $PKGDIR="/var/db/pkg";
opendir DIR,$PKGDIR or die "Couldn't open $PKGDIR";
my @dirs=readdir DIR;
closedir DIR;
@dirs=grep !/^\./,@dirs;
@dirs=grep !/^pkgdb.db$/,@dirs;
@dirs=sort @dirs;
my @args=@ARGV;
my $hasargs=$#ARGV>=0;
my %required; # this key is required by other packages
my %requires; # this key requires other packages
#
# Read from every package the +REQUIRED_BY file. This file contains
# info about the packages which require this package.
#
my $pkg;
foreach $pkg (@dirs) {
$required{$pkg}[0]=0;
if (open FILE,$PKGDIR."/".$pkg."/+REQUIRED_BY") {
my @lines=();
my $line;
my $count=0;
@lines=<FILE>;
chomp @lines;
foreach $line (@lines) {
$required{$pkg}[++$count]=$line;
}
$required{$pkg}[0]=$count;
close FILE;
}
}
#
# Read from every packege the +CONTENTS. The lines starting with @pkgdep
# tell which packages they are depending on.
#
foreach $pkg (@dirs) {
$requires{$pkg}[0]=0;
if (open FILE,$PKGDIR."/".$pkg."/+CONTENTS") {
my @lines=();
my $line;
my $count=0;
my @w;
@lines=<FILE>;
chomp @lines;
@lines=grep /^\@pkgdep/,@lines;
foreach $line (@lines) {
@w=split(" ",$line);
$requires{$pkg}[++$count]=$w[1];
}
$requires{$pkg}[0]=$count;
close FILE;
}
}
#
# Print the dependancies (recursive) of the packages
#
sub print_deps {
my $prefixwith=shift;
my $prefixwithout=shift;
my $shift=shift;
my $pkg=shift;
my $i=0;
while (++$i<=$requires{$pkg}[0]) {
if ($i!=$requires{$pkg}[0]) {
print $prefixwith;
} else {
print $prefixwithout;
}
print "\\__ ";
print "$requires{$pkg}[$i]";
if (defined $requires{$requires{$pkg}[$i]}[0]) {
print "\n";
if ($opt_v==1) {
if ($i!=$requires{$pkg}[0]) {
print_deps("$prefixwith |","$prefixwith ",
$shift+1,$requires{$pkg}[$i]);
} else {
print_deps("$prefixwithout |","$prefixwithout ",
$shift+1,$requires{$pkg}[$i]);
}
}
} else {
print " (unknown)\n";
}
}
}
#
# Print all packages or, if there is a command line argument, the ones which
# matches one of the arguments.
#
foreach $pkg (@dirs) {
if ($hasargs) {
my $found=0;
my $arg;
foreach $arg (@args) {
$found=1 if ($pkg=~/$arg/);
}
next if (!$found);
}
next if ($opt_t && $required{$pkg}[0]!=0);
next if ($opt_b && $requires{$pkg}[0]!=0);
print "$pkg\n";
if (!$opt_q && $requires{$pkg}[0]!=0) {
print_deps("|"," ",1,$pkg);
}
}
syntax highlighted by Code2HTML, v. 0.9.1