]> err.no Git - dpkg/commitdiff
add dpkg-checkbuilddeps
authorWichert Akkerman <wakkerma@debian.org>
Sat, 10 Mar 2001 00:48:57 +0000 (00:48 +0000)
committerWichert Akkerman <wakkerma@debian.org>
Sat, 10 Mar 2001 00:48:57 +0000 (00:48 +0000)
scripts/dpkg-checkbuilddeps.1 [new file with mode: 0644]
scripts/dpkg-checkbuilddeps.pl [new file with mode: 0755]

diff --git a/scripts/dpkg-checkbuilddeps.1 b/scripts/dpkg-checkbuilddeps.1
new file mode 100644 (file)
index 0000000..e52505d
--- /dev/null
@@ -0,0 +1,25 @@
+.TH DPKG-CHECKBUILDDEPS 1 "February 2001" "Debian project" "dpkg utililties"
+.SH NAME
+dpkg-checkbuilddeps -- check build dependancies and conflicts
+.SH SYNOPSIS
+\fBdpkg-checkbuilddeps\fR -B [\fIcontrol-file\fR]
+.SH DESCRIPTION
+This program checks the installed packages in the system against the build
+dependancies and build conflicts listed in the control file. If any are
+not met, it displays them and exits with a nonzero return code.
+.P
+By default, \fBdebian/control\fR is read, but an alternate control filename
+may be specified on the command line.
+.SH OPTIONS
+.TP
+.I -B
+Ignore Build-Depends-Indep lines. Use when no arch-indep packages will be
+built.
+.SH AUTHOR
+Copyright 2001 Joey Hess
+.UR mailto:joeyh@debian.org
+<joeyh@debian.org>
+.UE
+.sp
+This is free software; see the GNU General Public Licence version 2 or
+later for copying conditions.  There is NO warranty.
diff --git a/scripts/dpkg-checkbuilddeps.pl b/scripts/dpkg-checkbuilddeps.pl
new file mode 100755 (executable)
index 0000000..1a63a93
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/perl -w
+# GPL copyright 2001 by Joey Hess <joeyh@debian.org>
+
+use strict;
+use Getopt::Long;
+
+sub usage {
+       print STDERR <<EOF;
+Usage: dpkg-checkbuild [-B] [control-file]
+       -B              binary-only, ignore -Indep
+       control-file    control file to process [Default: debian/control]
+EOF
+}
+
+my ($me)=$0=~m:.*/(.+):;
+
+my $binary_only=0;
+my $want_help=0;
+if (! GetOptions('-B' => \$binary_only,
+                '-h' => \$want_help)) {
+       usage();
+       exit(2);
+}
+if ($want_help) {
+       usage();
+       exit(0);
+}
+
+my $control=shift || "debian/control";
+
+open (CONTROL, $control) || die "$control: $!\n";
+my @status=parse_status();
+my (@unmet, @conflicts);
+while (<CONTROL>) {
+       chomp;
+       last if $_ eq ''; # end of first stanza
+
+       if (/^Build-Depends:\s+(.*)/i) {
+               push @unmet, build_depends($1, @status);
+       }
+       elsif (/^Build-Conflicts:\s+(.*)/i) {
+               push @conflicts, build_conflicts($1, @status);
+       }
+       elsif (! $binary_only && /^Build-Depends-Indep:\s+(.*)/i) {
+               push @unmet, build_depends($1, @status);
+       }
+       elsif (! $binary_only && /^Build-Conflicts-Indep:\s+(.*)/i) {
+               push @conflicts, build_conflicts($1, @status);
+       }
+}
+close CONTROL;
+
+if (@unmet) {
+       print STDERR "$me: Unmet build dependancies: ";
+       print STDERR join(", ", @unmet), "\n";
+}
+if (@conflicts) {
+       print STDERR "$me: Build conflicts: ";
+       print STDERR join(", ", @conflicts), "\n";
+}
+exit 1 if @unmet || @conflicts;
+
+# This part could be replaced. Silly little status file parser.
+# thanks to Matt Zimmerman. Returns two hash references that
+# are exactly what the other functions need...
+sub parse_status {
+       my $status=shift || "/var/lib/dpkg/status";
+       
+       my %providers;
+       my %version;
+       local $/ = '';
+       open(STATUS, "<$status") || die "$status: $!\n";
+       while (<STATUS>) {
+               next unless /^Status: .*ok installed$/m;
+       
+               my ($package) = /^Package: (.*)$/m;
+               push @{$providers{$package}}, $package;
+               ($version{$package}) = /^Version: (.*)$/m;
+       
+               if (/^Provides: (.*)$/m) {
+                       foreach (split(/,\s+/, $1)) {
+                               push @{$providers{$_}}, $package;
+                       }
+               }
+       }
+       close STATUS;
+
+       return \%version, \%providers;
+}
+
+# This function checks the build dependancies passed in as the first
+# parameter. If they are satisfied, returns false. If they are unsatisfied,
+# an list of the unsatisfied depends is returned.
+#
+# Additional parameters that must be passed:
+# * A reference to a hash of all "ok installed" the packages on the system,
+#   with the hash key being the package name, and the value being the 
+#   installed version.
+# * A reference to a hash, where the keys are package names, and the
+#   value is a true value iff some package installed on the system provides
+#   that package (all installed packages provide themselves)
+#
+# Optionally, the architecture the package is to be built for can be passed
+# in as the 4th parameter. If not set, dpkg will be queried for the build
+# architecture.
+sub build_depends {
+       return check_line(1, @_);
+}
+
+# This function is exactly like unmet_build_depends, except it
+# checks for build conflicts, and returns a list of the packages
+# that are installed and are conflicted with.
+sub build_conflicts {
+       return check_line(0, @_);
+}
+
+# This function does all the work. The first parameter is 1 to check build
+# deps, and 0 to check build conflicts.
+sub check_line {
+       my $build_depends=shift;
+       my $line=shift;
+       my %version=%{shift()};
+       my %providers=%{shift()};
+       my $build_arch=shift || `dpkg --print-architecture`;
+       chomp $build_arch;
+
+       my @unmet=();
+       foreach my $dep (split(/,\s+/, $line)) {
+               my $ok=0;
+               my @possibles=();
+ALTERNATE:     foreach my $alternate (split(/\s*\|\s*/, $dep)) {
+                       my ($package, $rest)=split(/\s+/, $alternate, 2);
+       
+                       # Check arch specifications.
+                       if (defined $rest && $rest=~m/\[(.*?)\]/) {
+                               my $arches=lc($1);
+                               my $seen_arch='';
+                               foreach my $arch (split(' ', $arches)) {
+                                       if ($arch eq $build_arch) {
+                                               $seen_arch=1;
+                                               next;
+                                       }
+                                       elsif ($arch eq "!$build_arch") {
+                                               next ALTERNATE;
+                                       }
+                                       elsif ($arch =~ /!/) {
+                                               # This is equivilant to
+                                               # having seen the current arch,
+                                               # unless the current arch
+                                               # is also listed..
+                                               $seen_arch=1;
+                                       }
+                               }
+                               if (! $seen_arch) {
+                                       next;
+                               }
+                       }
+                       
+                       # This is a possibile way to meet the dependancy.
+                       # Remove the arch stuff from $alternate.
+                       $alternate=~s/\s+\[.*?\]//;
+                       push @possibles, $alternate;
+       
+                       # Check version.
+                       if (defined $rest && $rest=~m/\((..)\s+(.*?)\)/) {
+                               my $relation=$1;
+                               my $version=$2;
+                               
+                               if (! exists $version{$package}) {
+                                       # Not installed at all, so fail.
+                                       next;
+                               }
+                               else {
+                                       # Compare installed and needed
+                                       # version number.
+                                       system("dpkg", "--compare-versions",
+                                               $version{$package}, $relation,
+                                                $version);
+                                       if (($? >> 8) != 0) {
+                                               next; # fail
+                                       }
+                               }
+                       }
+                       elsif (! defined $providers{$package}) {
+                               # It's not a versioned dependancy, and
+                               # nothing provides it, so fail.
+                               next;
+                       }
+       
+                       # If we get to here, the dependancy was met.
+                       $ok=1;
+               }
+       
+               if (@possibles && (($build_depends && ! $ok) ||
+                                  (! $build_depends && $ok))) {
+                       # TODO: this could return a more complex
+                       # data structure instead to save re-parsing.
+                       push @unmet, join (" | ", @possibles);
+               }
+       }
+
+       return @unmet;
+}