From d430038ae5dca974834e874e4fecddc8850db38f Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Sat, 10 Mar 2001 00:48:57 +0000 Subject: [PATCH] add dpkg-checkbuilddeps --- scripts/dpkg-checkbuilddeps.1 | 25 ++++ scripts/dpkg-checkbuilddeps.pl | 203 +++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 scripts/dpkg-checkbuilddeps.1 create mode 100755 scripts/dpkg-checkbuilddeps.pl diff --git a/scripts/dpkg-checkbuilddeps.1 b/scripts/dpkg-checkbuilddeps.1 new file mode 100644 index 00000000..e52505d5 --- /dev/null +++ b/scripts/dpkg-checkbuilddeps.1 @@ -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 + +.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 index 00000000..1a63a93b --- /dev/null +++ b/scripts/dpkg-checkbuilddeps.pl @@ -0,0 +1,203 @@ +#!/usr/bin/perl -w +# GPL copyright 2001 by Joey Hess + +use strict; +use Getopt::Long; + +sub usage { + print STDERR < \$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 () { + 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 () { + 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; +} -- 2.39.5