summaryrefslogtreecommitdiff
path: root/bin/apt-why
blob: fcf24867bc33c6435a8f0338b705173300a7fe5a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env perl
## Copyright © 2008-2009 by Daniel Friesel <derf@derf.homelinux.org>
## License: WTFPL <http://sam.zoy.org/wtfpl>
use strict;
use warnings;
use 5.010;
use AptPkg::Cache;
use Getopt::Long;

my $cache     = AptPkg::Cache->new;
my $max_depth = 5;
my $all       = 0;
my $tabsign   = "\t";
my @deptypes  = qw/Depends Recommends Suggests/;
my @known;

sub revdeps {
	my $name    = shift;
	my $package = $cache->{$name};
	my @return;
	my $rdeps = $package->{RevDependsList};

	foreach my $dependency ( @{$rdeps} ) {
		if (
			not $dependency->{ParentPkg}{Name} ~~ @known
			and (  $all
				or $cache->{ $dependency->{ParentPkg}{Name} }->{CurrentState} eq
				'Installed' )
			and "$dependency->{DepType}" ~~ @deptypes
		)
		{
			push( @return, $dependency->{ParentPkg}{Name} );
		}
	}

	push( @known, @return );
	return (@return);
}

sub recurse {
	my $name  = shift;
	my $depth = (shift) + 1;

	printf( "%s%s\n", $tabsign x ( $depth - 1 ), $name );

	if ( $depth >= $max_depth ) {
		return;
	}

	foreach ( revdeps($name) ) {
		recurse( $_, $depth );
	}

	return;
}

GetOptions(
	'all!'       => \$all,
	'deptype=s'  => sub { @deptypes = split( /,/, $_[1] ) },
	'depth=i'    => \$max_depth,
	'tabwidth=i' => sub { $tabsign = q{ } x $_[1] },
	'h|?|help'   =>
		sub { exec( 'perldoc', '-F', $0 ) or die("See perldoc -F $0\n") },
);

my $packagename = shift
	or die("Usage: $0 [options] <package>; see $0 --help\n");

if ( not defined $cache->{$packagename} ) {
	die("No such package: $packagename\n");
}

if ( $cache->{$packagename}->{Flags} =~ /Essential/ ) {
	print "Essential: Yes\n";
}

recurse( $packagename, 0 );

__END__

=head1 NAME

apt-why - filtered reverse dependency displayer using AptPkg::Cache

=head1 SYNOPSIS

B<apt-why> [ I<options> ] I<package>

=head1 DESCRIPTION

B<apt-why> recursively displays I<package>'s reverse dependencies, thus
showing which installed packages require I<package> on the system.

=head1 OPTIONS

=over

=item B<--all>

Consider all packages, not just installed ones

=item B<--depth>=I<integer> (default: 5)

Specify the maximum recursion depth

=item B<--deptype>=I<types>

Only show reverse dependencies which mach the specified I<types> (comma separated list).
Right now, possible types are Depends, Suggests, Recommends.

=item B<--tabwidth>=I<i>

Indent each recursion level with I<i> spaces (by default: one tab)

=back

=head1 EXIT STATUS

Zero on success, non-zero on error (i.e. no such package).

=head1 CONFIGURATION

None.

=head1 DEPENDENCIES

This program requires the perl module B<AptPkg::Cache>. On Debian, it is
available via the package B<libapt-pkg-perl>.

=head1 BUGS AND LIMITATIONS

There may be problems with virtual packages and "Provides: " stuff.

=head1 AUTHOR

Daniel Friesel E<lt>derf@derf.homelinux.orgE<gt>

=head1 LICENSE

  0. You just DO WHAT THE FUCK YOU WANT TO.