Adding side stream changes to Maemian. Working to integrate full upstream libraries...
[maemian] / nokia-lintian / checks / patch-systems
diff --git a/nokia-lintian/checks/patch-systems b/nokia-lintian/checks/patch-systems
new file mode 100644 (file)
index 0000000..511a15d
--- /dev/null
@@ -0,0 +1,210 @@
+# patch-systems -- lintian check script -*- perl -*-
+#
+# Copyright (C) 2007 Marc Brockschmidt
+# Copyright (C) 2008 Raphael Hertzog
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, you can find it on the World Wide
+# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::patch_systems;
+use strict;
+use lib "$ENV{'LINTIAN_ROOT'}/checks/";
+use common_data;
+use Dep;
+use Tags;
+use Util;
+
+sub run {
+       my ($pkg, $type) = @_;
+
+       unless (-d "fields") {
+       fail("directory in lintian laboratory for $type package $pkg missing: fields");
+       }
+
+       #Some (cruft) checks are valid for every patch system, so we need to record that:
+       my $uses_patch_system = 0;
+
+       #Get build deps so we can decide which build system the maintainer
+       #meant to use:
+       my $build_deps = "";
+    if (open(IN, '<', "fields/build-depends")) {
+               local $/ = undef;
+        chomp($build_deps .= <IN>);
+               close(IN);
+    }
+       if (open(IN, '<', "fields/build-depends-indep")) {
+               local $/ = undef;
+               $build_deps .= ", " if $build_deps;
+               chomp($build_deps .= <IN>);
+               close(IN);
+       }
+       $build_deps = Dep::parse($build_deps);
+       # Get source package format
+       my $format = "";
+       if (open(IN, '<', "fields/format")) {
+               local $/ = undef;
+               chomp($format .= <IN>);
+               close(IN);
+       }
+       my $quilt_format = ($format =~ /3\.\d+ \(quilt\)/) ? 1 : 0;
+
+       #----- dpatch
+       if (Dep::implies($build_deps, Dep::parse("dpatch"))) {
+               $uses_patch_system++;
+               #check for a debian/patches file:
+               if (! -r "debfiles/patches/00list") {
+                       tag "dpatch-build-dep-but-no-patch-list", $pkg;
+               } else {
+                       my $list_uses_cpp = 0;
+                       if (open(OPTS, '<', "debfiles/patches/00options")) {
+                               while(<OPTS>) {
+                                       if (/DPATCH_OPTION_CPP=1/) {
+                                               $list_uses_cpp = 1;
+                                               last;
+                                       }
+                               }
+                               close(OPTS);
+                       }
+                       foreach my $listfile (glob("debfiles/patches/00list*")) {
+                               my @patches;
+                               if (open(IN, '<', "$listfile")) {
+                                       while(<IN>) {
+                                               chomp;
+                                               next if (/^\#/); #ignore comments or CPP directive
+                                               s%//.*%% if $list_uses_cpp; # remove C++ style comments
+                                               if ($list_uses_cpp && m%/\*%) {
+                                                       # remove C style comments
+                                                       $_ .= <IN> while($_ !~ m%\*/%);
+                                                       s%/\*[^*]*\*/%%g;
+                                               }
+                                               next if (/^\s*$/); #ignore blank lines
+                                               push @patches, split(' ', $_);
+                                       }
+                                       close(IN);
+                               }
+
+                               # Check each patch.
+                               foreach my $patch_file (@patches) {
+                                       $patch_file .= ".dpatch" if -e "debfiles/patches/$patch_file.dpatch"
+                                               and not -e "debfiles/patches/$patch_file";
+                                       if (! -r "debfiles/patches/$patch_file") {
+                                               tag "dpatch-index-references-non-existent-patch", $patch_file;
+                                               next;
+                                       }
+                                       if (open(PATCH_FILE, '<', "debfiles/patches/$patch_file")) {
+                                               my $has_comment = 0;
+                                               while (<PATCH_FILE>) {
+                                                       #stop if something looking like a patch starts:
+                                                       last if /^---/;
+                                                       #note comment if we find a proper one
+                                                       $has_comment = 1 if (/^\#+\s*DP:\s*(.*)$/ && $1 !~ /^no description\.?$/i)
+                                               }
+                                               close(PATCH_FILE);
+                                               unless ($has_comment) {
+                                                       tag "dpatch-missing-description", $patch_file;
+                                               }
+                                       }
+                                       check_patch($patch_file);
+                               }
+                       }
+               }
+       }
+
+       #----- quilt
+       if (Dep::implies($build_deps, Dep::parse("quilt")) or $quilt_format) {
+               $uses_patch_system++;
+               #check for a debian/patches file:
+               if (! -r "debfiles/patches/series") {
+                       tag "quilt-build-dep-but-no-series-file", $pkg unless $quilt_format;
+               } else {
+                       if (open(IN, '<', "debfiles/patches/series")) {
+                               my @patches;
+                               my @badopts;
+                               while(<IN>) {
+                                       chomp; s/^\s+//; s/\s+$//; # Strip leading/trailing spaces
+                                       s/(^|\s+)#.*$//; # Strip comment
+                                       next unless $_;
+                                       if (/^(\S+)\s+(\S.*)$/) {
+                                               $_ = $1;
+                                               if ($2 ne '-p1') {
+                                                       push @badopts, $_;
+                                               }
+                                       }
+                                       push @patches, $_;
+                               }
+                               close(IN);
+                               if (scalar(@badopts)) {
+                                       tag "quilt-patch-with-non-standard-options", @badopts;
+                               }
+
+                               # Check each patch.
+                               foreach my $patch_file (@patches) {
+                                       if (! -r "debfiles/patches/$patch_file") {
+                                               tag "quilt-series-references-non-existent-patch", $patch_file;
+                                               next;
+                                       }
+                                       check_patch($patch_file);
+                               }
+                       }
+               }
+       } else {
+               if (-r "debfiles/patches/series") {
+                       # 3.0 (quilt) sources don't need quilt as dpkg-source will do the work
+                       tag "quilt-series-but-no-build-dep" unless $quilt_format;
+               }
+       }
+
+
+       #----- general cruft checking:
+       if ($uses_patch_system) {
+               if ($uses_patch_system > 1) {
+                       tag "more-than-one-patch-system";
+               }
+
+               open(STAT, '<', "diffstat") or fail("cannot open diffstat file: $!");
+               while (<STAT>) {
+                       my ($file) = (m,^\s+(.*?)\s+\|,)
+                            or fail("syntax error in diffstat file: $_");
+
+                       if ($file !~ /^debian/) {
+                               tag "patch-system-but-direct-changes-in-diff", $file;
+                       }
+               }
+               close (STAT) or fail("error reading diffstat file: $!");
+       }
+}
+
+# Checks on patches common to all build systems
+sub check_patch($) {
+       my $patch_file = shift;
+       open(DIFFSTAT, "-|", "diffstat -p0 -l debfiles/patches/$patch_file")
+         or fail("can't fork diffstat");
+       while (<DIFFSTAT>) {
+               chomp;
+               if (m|^(\./)?debian/| or m|^(\./)?[^/]+/debian/|) {
+                       tag "patch-modifying-debian-files", $patch_file, $_;
+               }
+       }
+       close(DIFFSTAT) or fail("cannot close pipe to diffstat on $patch_file: $!");
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: t
+# cperl-indent-level: 8
+# End:
+# vim: syntax=perl sw=4 ts=4 noet shiftround