Subject: [PATCH] Added script that updates most of the debhelper data, implemented missing-build-dependency-for-dh_-command, and recognise -dh_command and not just dh_command

From: Raphael Geissert <[email-masked]>
Date: Fri, 12 Sep 2008 23:56:18 -0500

Signed-off-by: Raphael Geissert <[email-masked]>
---
 checks/debhelper                     |   18 ++++-
 checks/debhelper.desc                |    8 ++
 data/debhelper/dh_commands           |   96 +++++++++++++++++++++++++++
 data/debhelper/dh_packages           |   29 ++++++++
 data/debhelper/maint_commands        |   21 +++++-
 data/debhelper/misc-Depends_commands |    8 --
 data/debhelper/miscDepends_commands  |   12 ++++
 private/refresh-debhelper-data       |  121 ++++++++++++++++++++++++++++++++++
 testset/dh-test/debian/rules         |    1 +
 testset/tags.dh-test                 |    1 +
 10 files changed, 299 insertions(+), 16 deletions(-)
 create mode 100644 data/debhelper/dh_commands
 create mode 100644 data/debhelper/dh_packages
 delete mode 100644 data/debhelper/misc-Depends_commands
 create mode 100644 data/debhelper/miscDepends_commands
 create mode 100755 private/refresh-debhelper-data

diff --git a/checks/debhelper b/checks/debhelper
index 12d35fc..5c747bc 100644
--- a/checks/debhelper
+++ b/checks/debhelper
@@ -42,6 +42,7 @@ my $usescdbs = '';
 my $seendhpython = '';
 my $usescdbspython = '';
 my $needmiscdepends = 0;
+my %missingbdeps;
 
 # If there is no debian/compat file present but cdbs is being used, cdbs will
 # create one automatically.  Currently it always uses compatibility level 5.
@@ -51,8 +52,8 @@ my $needmiscdepends = 0;
 my $cdbscompat = 5;
 
 my $maint_commands = Lintian::Data->new ('debhelper/maint_commands');
-
-my $miscDeps_commands = Lintian::Data->new ('debhelper/misc-Depends_commands');
+my $miscDeps_commands = Lintian::Data->new ('debhelper/miscDepends_commands');
+my $dh_commands_depends = Lintian::Data->new ('debhelper/dh_commands', '=');
 
 # The version at which debhelper commands were introduced.  Packages that use
 # one of these commands must have a dependency on that version of debhelper or
@@ -67,7 +68,7 @@ open(RULES, '<', "debfiles/rules") or fail("cannot read debian/rules: $!");
 my $dhcompatvalue;
 my @versioncheck;
 while (<RULES>) {
-    if (m/^\s+(dh_\w+)/) {
+    if (m/^\s+-?(dh_\w+)/) {
         my $dhcommand = $1;
     	if ($dhcommand =~ /dh_testversion(?:\s+(.+))?/) {
 	    $needversiondepends = $1 if ($1);
@@ -83,9 +84,13 @@ while (<RULES>) {
 	if ($maint_commands->known($dhcommand) and not m/\s+\-n\s+/) {
 	    $needtomodifyscripts = 1;
 	}
-	if ($miscDeps_commands->known($dh_command)) {
+	if ($miscDeps_commands->known($dhcommand)) {
 	    $needmiscdepends = 1;
 	}
+	if ($dh_commands_depends->known($dhcommand)) {
+	    my $dep = $dh_commands_depends->value($dhcommand);
+	    $missingbdeps{$dep} = $dhcommand;
+	}
         if ($versions{$dhcommand}) {
             push (@versioncheck, $dhcommand);
         }
@@ -206,6 +211,11 @@ while (defined(my $file=readdir(DEBIAN))) {
         if ($needbuilddepends && ! Dep::implies($bdepends, Dep::parse('debhelper'))) {
 	    tag "package-uses-debhelper-but-lacks-build-depends", "";
 	}
+	for my $dep (keys %missingbdeps) {
+	    my $command = $missingbdeps{$dep};
+	    tag 'missing-build-dependency-for-dh_-command', "$command=$dep"
+		    unless (Dep::implies($bdepends, Dep::parse($dep)));
+	}
     } elsif ($file =~ m/^ex\.|\.ex$/i) {
         tag "dh-make-template-in-source", "debian/$file";
     } elsif ($file =~ m/(.+\.|^)(docs|dirs|manpages)$/) {
diff --git a/checks/debhelper.desc b/checks/debhelper.desc
index b232392..ab197ec 100644
--- a/checks/debhelper.desc
+++ b/checks/debhelper.desc
@@ -126,6 +126,14 @@ Info: The source package uses debhelper but it does not have ${misc:Depends} on
  dependencies are set correctly in case the result of a call to any of the dh_
  commands cause the package to depend on another package.
 
+Tag: missing-build-dependency-for-dh_-command
+Type: error
+Severity: important
+Certainty: possible
+Info: The source package appears to be using a dh_ command but doesn't build
+ depend on the package that actually provides it.  If it uses it, it must
+ build depend on it.
+
 Tag: debhelper-script-needs-versioned-build-depends
 Type: warning
 Severity: normal
diff --git a/data/debhelper/dh_commands b/data/debhelper/dh_commands
new file mode 100644
index 0000000..e1ab66e
--- /dev/null
+++ b/data/debhelper/dh_commands
@@ -0,0 +1,96 @@
+dh_auto_build=debhelper
+dh_auto_clean=debhelper
+dh_auto_configure=debhelper
+dh_auto_install=debhelper
+dh_auto_test=debhelper
+dh_bash-completion=bash-completion
+dh_builddeb=debhelper
+dh_buildinfo=dh-buildinfo
+dh_clean=debhelper
+dh_clideps=cli-common-dev
+dh_clifixperms=cli-common-dev
+dh_cligacpolicy=cli-common-dev
+dh_clistrip=cli-common-dev
+dh_compress=debhelper
+dh_consoledata=dh-consoledata
+dh_desktop=debhelper
+dh_fixperms=debhelper
+dh_gconf=debhelper
+dh_gencontrol=debhelper
+dh_gnustep=gnustep-make
+dh_gstscancodecs=gstreamer-tools
+dh_gtkmodules=libgtk2.0-dev
+dh_haskell_build=haskell-devscripts
+dh_haskell_buildinst=haskell-devscripts
+dh_haskell_configure=haskell-devscripts
+dh_haskell_depends=haskell-devscripts
+dh_haskell=haskell-devscripts
+dh_haskell_install=haskell-devscripts
+dh_haskell_prep=haskell-devscripts
+dh_icons=debhelper
+dh_installcatalogs=debhelper
+dh_installchangelogs=debhelper
+dh_installcligac=cli-common-dev
+dh_installcron=debhelper
+dh_installdebconf=debhelper
+dh_installdeb=debhelper
+dh_install=debhelper
+dh_installdefoma=defoma
+dh_installdirs=debhelper
+dh_installdocs=debhelper
+dh_installemacsen=debhelper
+dh_installexamples=debhelper
+dh_installifupdown=debhelper
+dh_installinfo=debhelper
+dh_installinit=debhelper
+dh_installkpatches=dh-kpatches
+dh_installlisting=desktop-profiles
+dh_installlogcheck=debhelper
+dh_installlogrotate=debhelper
+dh_installman=debhelper
+dh_installmanpages=debhelper
+dh_installmenu=debhelper
+dh_installmime=debhelper
+dh_installmodules=debhelper
+dh_installpam=debhelper
+dh_installppp=debhelper
+dh_installtex=tex-common
+dh_installudev=debhelper
+dh_installwm=debhelper
+dh_installxfonts=debhelper
+dh_installxmlcatalogs=xml-core
+dh_installxsp=mono-xsp-base
+dh_installyorick=yorick-dev
+dh_installzopeinstance=zope-debhelper
+dh_installzope=zope-debhelper
+dh_javadoc=gjdoc
+dh_link=debhelper
+dh_lintian=debhelper
+dh_lisp=dh-lisp
+dh_listpackages=debhelper
+dh_makeclilibs=cli-common-dev
+dh_make=dh-make
+dh_makeshlibs=debhelper
+dh_md5sums=debhelper
+dh_metainit=dh-metainit
+dh_movefiles=debhelper
+dh_nativejava=java-gcj-compat-dev
+dh_ocaml=ocaml-nox
+dh_pangomodules=libpango1.0-dev
+dh_perl=debhelper
+dh_pidgin=pidgin-dev
+dh_prep=debhelper
+dh_pycentral=python-central
+dh_pysupport=python-support
+dh_python=debhelper
+dh_rdoc=ruby-pkg-tools
+dh_scrollkeeper=debhelper
+dh_shlibdeps=debhelper
+dh_strip=debhelper
+dh_suidregister=debhelper
+dh_testdir=debhelper
+dh_testroot=debhelper
+dh_testversion=debhelper
+dh_undocumented=debhelper
+dh_upx=upx-ucl
+dh_usrlocal=debhelper
diff --git a/data/debhelper/dh_packages b/data/debhelper/dh_packages
new file mode 100644
index 0000000..93c186c
--- /dev/null
+++ b/data/debhelper/dh_packages
@@ -0,0 +1,29 @@
+bash-completion
+cli-common-dev
+debhelper
+defoma
+desktop-profiles
+dh-buildinfo
+dh-consoledata
+dh-kpatches
+dh-lisp
+dh-make
+dh-metainit
+gjdoc
+gnustep-make
+gstreamer-tools
+haskell-devscripts
+java-gcj-compat-dev
+libgtk2.0-dev
+libpango1.0-dev
+mono-xsp-base
+ocaml-nox
+pidgin-dev
+python-central
+python-support
+ruby-pkg-tools
+tex-common
+upx-ucl
+xml-core
+yorick-dev
+zope-debhelper
diff --git a/data/debhelper/maint_commands b/data/debhelper/maint_commands
index 3127102..832c799 100644
--- a/data/debhelper/maint_commands
+++ b/data/debhelper/maint_commands
@@ -1,23 +1,36 @@
-# This list of debhelper commands that like to modify maintainer scripts was
-# generated by using the following commands:
-# grep -l autoscript $(dpkg -L debhelper | egrep '^/usr/bin/dh_.+$') \
-# | sed s,/usr/bin/,,g | sort
+dh_cligacpolicy
+dh_consoledata
 dh_desktop
 dh_gconf
+dh_haskell_prep
 dh_icons
 dh_installcatalogs
+dh_installcligac
 dh_installdebconf
+dh_installdefoma
 dh_installdocs
 dh_installemacsen
 dh_installinfo
 dh_installinit
+dh_installlisting
 dh_installmenu
 dh_installmime
 dh_installmodules
+dh_installtex
 dh_installudev
 dh_installwm
 dh_installxfonts
+dh_installxmlcatalogs
+dh_installxsp
+dh_installzope
+dh_installzopeinstance
+dh_lisp
 dh_makeshlibs
+dh_metainit
+dh_nativejava
+dh_ocaml
+dh_pycentral
+dh_pysupport
 dh_python
 dh_scrollkeeper
 dh_suidregister
diff --git a/data/debhelper/misc-Depends_commands b/data/debhelper/misc-Depends_commands
deleted file mode 100644
index 9a1f26d..0000000
--- a/data/debhelper/misc-Depends_commands
+++ /dev/null
@@ -1,8 +0,0 @@
-# This list of debhelper commands that may make use of ${misc:Depends} was
-# generated by using the following commands:
-# grep -l misc:Depends $(dpkg -L debhelper | egrep '^/usr/bin/dh_.+$') \
-# | sed s,/usr/bin/,,g | sort
-dh_gconf
-dh_installcatalogs
-dh_installdebconf
-dh_installxfonts
diff --git a/data/debhelper/miscDepends_commands b/data/debhelper/miscDepends_commands
new file mode 100644
index 0000000..0afb23c
--- /dev/null
+++ b/data/debhelper/miscDepends_commands
@@ -0,0 +1,12 @@
+dh_gconf
+dh_gtkmodules
+dh_installcatalogs
+dh_installdebconf
+dh_installlisting
+dh_installtex
+dh_installxfonts
+dh_installxmlcatalogs
+dh_lisp
+dh_nativejava
+dh_pangomodules
+dh_pidgin
diff --git a/private/refresh-debhelper-data b/private/refresh-debhelper-data
new file mode 100755
index 0000000..a1d1913
--- /dev/null
+++ b/private/refresh-debhelper-data
@@ -0,0 +1,121 @@
+#!/bin/sh
+
+set -e
+
+if [ -z "$1" ]; then
+    printf "Usage: %s path/to/lintian/data [Contents-arch.(gz|bz2|)]\n" \
+	"$(basename "$0")"
+    cat <<INFO
+
+If the Contents file is specified, the list of dh_ commands found there will
+be compared with the list at lintian/data/debhelper/dh_commands and will
+indicate if the list is up to date with an exit status of zero.
+
+If the Contents file is not specified, the script will download the following
+files from a mirror (which should be specified via the DEB_MIRROR env var, 
+which defaults to http://i386-geomirror.debian.net/debian and is used directly
+without any kind of parsing so one can play with it):
+* Contents-i386.gz, main/binary-i386/Packages.gz
+* Binary packages found at Contents shipping dh_ commands
+Any special parameter can be passed to wget via WGET_ARGS, if needed.
+
+Other options:
+Other variables such as GREP_OPTIONS can be used to enable things like --mmap.
+INFO
+    exit
+fi
+
+readonly lintian_data="$(readlink -f "$1")"
+readonly contents="$(readlink -f "$2")"
+readonly dh_regex='^usr/bin/dh_.'
+readonly dh_perl_regex='^usr/bin/(dh_[^\s]+)\s+\w+/([^,]+).*'
+offline=0
+
+[ -d "$lintian_data" ] || {
+    printf "%s is not a directory, aborting" "$lintiandata" >&2
+    exit 1
+}
+
+[ ! -z "$contents" -a ! -f "$contents" ] && {
+    printf "%s is not a file, aborting" "$contents" >&2
+    exit 1
+}
+
+[ -z "$contents" ] || offline=1
+
+readonly workdir="$(mktemp -d)"
+
+cleanup () {
+        [ ! -d "$workdir" ] || rm -rf "$workdir"
+}; trap cleanup EXIT
+
+if [ $offline -eq 1 ]; then
+    known_commands="$lintian_data/debhelper/dh_commands"
+    [ -f "$known_commands" ] || exit 1
+    new_commands="$workdir/new"
+
+    case "$contents" in
+	*.gz)
+	    command="zgrep"
+	;;
+	*.bz2)
+	    command="bzgrep"
+	;;
+	*)
+	    command="grep"
+	;;
+    esac
+    which "$command" 2>&1 1>/dev/null || exit 2
+
+    $command -E "$dh_regex" "$contents" \
+	| perl -p -w -E 's#'"$dh_perl_regex"'#$1=$2#g;' \
+	| sort > "$new_commands"
+    cmp -s "$known_commands" "$new_commands"
+    exit
+else
+    mirror="${DEB_MIRROR:=http://i386-geomirror.debian.net/debian}"
+    WGET_ARGS="${WGET_ARGS:=-nv}"
+    wget() {
+	/usr/bin/wget $WGET_ARGS "$mirror"/"$1"
+    }
+    cd "$workdir"
+    wget dists/sid/Contents-i386.gz
+    zgrep -E "$dh_regex" Contents-i386.gz > dh_entries
+    cat dh_entries \
+	| perl -p -w -E 's#'"$dh_perl_regex"'#$1=$2#g;' \
+	| sort > dh_commands
+    cat dh_entries \
+	| perl -p -w -E 's#'"$dh_perl_regex"'#$2#g;' \
+	| sort -u > dh_packages
+
+    for f in commands packages; do
+	rf="$lintian_data/debhelper/dh_$f"
+	[ ! -f "$rf" ] ||
+	    mv "$rf" "${rf}.old"
+	cp -a "dh_$f" "$rf"
+    done
+
+    wget dists/sid/main/binary-i386/Packages.gz
+    gunzip Packages.gz
+    for package in $(cat dh_packages); do
+	fn="$(grep-dctrl -n -P "$package" -sFilename Packages)"
+	wget "$fn"
+	file="$(basename "$fn")"
+	dpkg-deb -x "$file" "$(mktemp -d -p .)"
+	rm -rf "$file"
+	find */ | grep -Ev '^[^/]+/usr/bin/dh_.+$' \
+	    | xargs rm >/dev/null 2>&1 || true
+    done
+
+    grep -lr autoscript */ \
+	| sed 's,.*/usr/bin/,,g' | sort -u > maint_commands
+    grep -lr misc:Depends */ \
+	| sed 's,.*/usr/bin/,,g' | sort -u > miscDepends_commands
+
+    for f in maint miscDepends; do
+	rf="$lintian_data/debhelper/${f}_commands"
+	[ ! -f "$rf" ] ||
+	    mv "$rf" "${rf}.old"
+	cp -a "${f}_commands" "$rf"
+    done
+fi
diff --git a/testset/dh-test/debian/rules b/testset/dh-test/debian/rules
index dbe5113..a6354b2 100755
--- a/testset/dh-test/debian/rules
+++ b/testset/dh-test/debian/rules
@@ -82,6 +82,7 @@ binary-arch: build install
 #	dh_installcron
 #	dh_installinfo
 	dh_installman
+	-dh_gnustep
 #	dh_dhelp
 	dh_suidregister
 	dh_link
diff --git a/testset/tags.dh-test b/testset/tags.dh-test
index 21c38b3..8ddada5 100644
--- a/testset/tags.dh-test
+++ b/testset/tags.dh-test
@@ -1,4 +1,5 @@
 E: dh-test source: brace-expansion-in-debhelper-config-file debian/docs
+E: dh-test source: missing-build-dependency-for-dh_-command dh_gnustep=gnustep-make
 E: dh-test: description-is-dh_make-template
 E: dh-test: helper-templates-in-copyright
 E: dh-test: section-is-dh_make-template