2 # Copyright (C) Patrick Schoenfeld
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 build-rdeps - find packages that depend on a specific package to build (reverse build depends)
24 B<build-rdeps> I<package>
28 B<build-rdeps> searches for all packages that build-depend on the specified package.
34 =item B<-u> B<--update>
36 Run apt-get update before searching for build-depends.
40 Use sudo when running apt-get update. Has no effect if -u is omitted.
42 =item B<--distribution>
44 Select another distribution, which is searched for build-depends.
48 Ignore contrib and non-free
50 =item B<--exclude-component>
52 Ignore the given component (e.g. main, contrib, non-free).
56 Restrict the search to only the specified origin (such as "Debian").
58 =item B<-m> B<--print-maintainer>
60 Print the value of the maintainer field for each package.
62 =item B<-d> B<--debug>
68 Show the usage information.
72 Show the version information.
78 The tool requires apt Sources files to be around for the checked components.
79 In the default case this means that in /var/lib/apt/lists files need to be
80 around for main, contrib and non-free.
82 In practice this means one needs to add one deb-src line for each component,
85 deb-src http://<mirror>/debian <dist> main contrib non-free
87 and run apt-get update afterwards or use the update option of this tool.
98 my $progname = basename($0);
100 my $dctrl = "/usr/bin/grep-dctrl";
101 my $sources_path = "/var/lib/apt/lists/";
102 my $release_pattern = '(.*_dists_(sid|unstable))_Release$';
110 my $opt_distribution;
111 my $opt_origin = 'Debian';
112 my @opt_exclude_components;
115 die "$progname: Fatal error. grep-dctrl is not available.\nPlease install the 'dctrl-tools' package.\n";
120 This is $progname $version, from the Debian devscripts package, v. ###VERSION###
121 This code is copyright by Patrick Schoenfeld, all rights reserved.
122 It comes with ABSOLUTELY NO WARRANTY. You are free to redistribute this code
123 under the terms of the GNU General Public License, version 2 or later.
130 usage: $progname packagename
134 Searches for all packages that build-depend on the specified package.
137 -u, --update Run apt-get update before searching for build-depends.
138 (needs root privileges)
139 -s, --sudo Use sudo when running apt-get update
140 (has no effect when -u is ommitted)
141 -d, --debug Enable the debug mode
142 -m, --print-maintainer Print the maintainer information (experimental)
143 --distribution distribution Select a distribution to search for build-depends
145 --origin origin Select an origin to search for build-depends
147 --only-main Ignore contrib and non-free
148 --exclude-component COMPONENT Ignore the specified component (can be given multiple times)
154 # Sub to test if a given section shall be included in the result
155 sub test_for_valid_component {
156 my $filebase = shift;
158 if ($opt_mainonly and $filebase =~ /(contrib|non-free)/) {
161 foreach my $component (@opt_exclude_components) {
162 if ($filebase =~ /$component/) {
167 if (! -e "$sources_path/$filebase") {
168 print STDERR "Warning: Ignoring missing sources file $filebase. (Missing component in sources.list?)\n";
172 print STDERR "DEBUG: Component ($_) may not be excluded.\n" if ($opt_debug);
176 # Scan Release files and add appropriate Sources files
178 my ($file, $base) = @_;
179 open(RELEASE, '<', "$sources_path/$file");
181 if (/^Origin:\s*(.+)\s*$/) {
183 # skip undesired (non-specified or already seen) origins
184 if (($opt_origin && $origin !~ /^\s*\Q$opt_origin\E\s*$/)
185 || $seen_origins{$origin}) {
188 $seen_origins{$origin} = 1;
190 elsif (/^(?:MD5|SHA)\w+:/) {
191 # from a list of checksums, grab names of Sources files
194 if (/([^ ]+\/Sources)$/) {
195 addsources($base, $1);
204 # Add a *_Sources file if test_for_valid_component likes it
206 my ($base, $filename) = @_;
207 # main/source/Sources
208 $filename =~ s/\//_/g;
209 # -> ftp.debian.org_..._main_source_Sources
210 $filename = "${base}_${filename}";
211 if (test_for_valid_component($filename) == 0) {
212 push(@source_files, $filename);
213 print STDERR "DEBUG: Added source file: $_\n" if ($opt_debug);
217 sub findreversebuilddeps {
218 my ($package, $source_file) = @_;
220 my $depending_package;
222 my $maintainer_info='';
224 open(PACKAGES, "$dctrl -F Build-Depends,Build-Depends-Indep $package -s Package,Build-Depends,Build-Depends-Indep,Maintainer $source_file|");
228 print STDERR "$_\n" if ($opt_debug);
229 if (/Package: (.*)$/) {
230 $depending_package = $1;
231 $packages{$depending_package}->{'Build-Depends'} = 0;
233 elsif (/Maintainer: (.*)$/) {
234 if ($depending_package) {
235 $packages{$depending_package}->{'Maintainer'} = $1;
238 elsif (/Build-Depends: (.*)$/ or /Build-Depends-Indep: (.*)$/) {
239 if ($depending_package) {
240 print STDERR "$1\n" if ($opt_debug);
241 if ($1 =~ /^(.*\s)?\Q$package\E([\s,]|$)/) {
242 $packages{$depending_package}->{'Build-Depends'} = 1;
249 while($depending_package = each(%packages)) {
250 if ($packages{$depending_package}->{'Build-Depends'} != 1) {
251 print STDERR "Ignoring package $depending_package because its not really build depending on $package.\n" if ($opt_debug);
254 if ($opt_maintainer) {
255 $maintainer_info = "($packages{$depending_package}->{'Maintainer'})";
259 print "$depending_package $maintainer_info \n";
264 print "No reverse build-depends found for $package.\n\n"
267 print "\nFound a total of $count reverse build-depend(s) for $package.\n\n";
271 if ($#ARGV < 0) { usage; exit(0); }
274 Getopt::Long::Configure('bundling');
276 "u|update" => \$opt_update,
277 "s|sudo" => \$opt_sudo,
278 "m|print-maintainer" => \$opt_maintainer,
279 "distribution=s" => \$opt_distribution,
280 "only-main" => \$opt_mainonly,
281 "exclude-component=s" => \@opt_exclude_components,
282 "origin=s" => \$opt_origin,
283 "d|debug" => \$opt_debug,
284 "h|help" => sub { usage; },
285 "v|version" => sub { version; }
291 die "$progname: missing argument. expecting packagename\n";
294 print STDERR "DEBUG: Package => $package\n" if ($opt_debug);
297 print STDERR "DEBUG: Updating apt-cache before search\n" if ($opt_debug);
300 print STDERR "DEBUG: Using sudo to become root\n" if ($opt_debug);
303 push(@cmd, 'apt-get', 'update');
307 if ($opt_distribution) {
308 print STDERR "DEBUG: Setting distribution to $opt_distribution\n" if ($opt_debug);
309 $release_pattern = '(.*_dists_' . $opt_distribution . ')_Release$';
313 find(sub { readrelease($_, $1) if /$release_pattern/ }, $sources_path);
315 if (!@source_files) {
316 die "$progname: unable to find sources files.\nDid you forget to run apt-get update (or add --update to this command)?";
319 foreach my $source_file (@source_files) {
320 if ($source_file =~ /main/) {
321 print "Reverse Build-depends in main:\n";
322 print "------------------------------\n\n";
323 findreversebuilddeps($package, "$sources_path/$source_file");
326 if ($source_file =~ /contrib/) {
327 print "Reverse Build-depends in contrib:\n";
328 print "---------------------------------\n\n";
329 findreversebuilddeps($package, "$sources_path/$source_file");
332 if ($source_file =~ /non-free/) {
333 print "Reverse Build-depends in non-free:\n";
334 print "----------------------------------\n\n";
335 findreversebuilddeps($package, "$sources_path/$source_file");
341 This code is copyright by Patrick Schoenfeld
342 <schoenfeld@debian.org>, all rights reserved.
343 This program comes with ABSOLUTELEY NO WARRANTY.
344 You are free to redistribute this code under the terms of the
345 GNU General Public License, version 2 or later.
349 Patrick Schoenfeld <schoenfeld@debian.org>