Wichert Akkerman лет назад: 25
Родитель
Сommit
d430038ae5
2 измененных файлов с 228 добавлено и 0 удалено
  1. 25 0
      scripts/dpkg-checkbuilddeps.1
  2. 203 0
      scripts/dpkg-checkbuilddeps.pl

+ 25 - 0
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
+<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.

+ 203 - 0
scripts/dpkg-checkbuilddeps.pl

@@ -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;
+}