Added lots more modules from lintian. Maemian appears to work.
[maemian] / checks / description
1 # description -- lintian check script -*- perl -*-
2
3 # Copyright (C) 1998 Christian Schwarz
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, you can find it on the World Wide
17 # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
18 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
20
21 package Maemian::description;
22 use strict;
23 use Spelling;
24 use Tags;
25 use Util;
26
27 sub run {
28
29 my $pkg = shift;
30 my $type = shift;
31 my $info = shift;
32
33 my $tabs = 0;
34 my $lines = 0;
35 my $template = 0;
36 my $unindented_list = 0;
37 my $synopsis;
38 my $description;
39
40 # description?
41 my $full_description = $info->field('description');
42 unless (defined $full_description) {
43     tag "package-has-no-description", "";
44     return 0;
45 }
46
47 $full_description =~ m/^([^\n]*)\n(.*)$/s;
48 ($synopsis, $description) = ($1, $2);
49 unless (defined $synopsis) {
50     $synopsis = $full_description;
51     $description = '';
52 }
53
54 if ($synopsis =~ m/^\s*$/) {
55     tag "description-synopsis-is-empty", "";
56 } else {
57     if ($synopsis =~ m/^\Q$pkg\E\b/i) {
58         tag "description-starts-with-package-name", "";
59     }
60     if ($synopsis =~ m/(?<!etc)\.\s*$/i) {
61         tag "description-synopsis-might-not-be-phrased-properly", "";
62     }
63     if ($synopsis =~ m/\t/) {
64         tag "description-contains-tabs", "" unless $tabs++;
65     }
66     if (length($synopsis) >= 80) {
67         tag "description-too-long", "";
68     }
69     if ($synopsis =~ m/^missing\s*$/i) {
70         tag "description-is-debmake-template", "" unless $template++;
71     } elsif ($synopsis =~ m/<insert up to 60 chars description>/) {
72         tag "description-is-dh_make-template", "" unless $template++;
73     }
74 }
75
76 my $flagged_homepage;
77 my $is_dummy;
78 foreach (split /\n/, $description) {
79     next if m/^ \.\s*$/o;
80
81     if ($lines == 0) {
82         my $firstline = lc $_;
83         my $lsyn = lc $synopsis;
84         if ($firstline =~ /^\Q$lsyn\E$/) {
85             tag "description-synopsis-is-duplicated", "";
86         } else {
87             $firstline =~ s/[^a-zA-Z0-9]+//g;
88             $lsyn =~ s/[^a-zA-Z0-9]+//g;
89             if ($firstline eq $lsyn) {
90                 tag "description-synopsis-is-duplicated", "";
91             }
92         }
93     }
94
95     $lines++;
96
97     if (m/^ \.\s*\S/o) {
98         tag "description-contains-invalid-control-statement", "";
99     } elsif (m/^ [\-\*]/o) {
100         # Print it only the second time.  Just one is not enough to be sure that
101         # it's a list, and after the second there's no need to repeat it.
102         tag "possible-unindented-list-in-extended-description", "" if $unindented_list++ == 2;
103     }
104
105     if (m/\t/o) {
106         tag "description-contains-tabs", "" unless $tabs++;
107     }
108
109     if (m,^\s*Homepage: <?https?://,i) {
110         tag "description-contains-homepage";
111         $flagged_homepage = 1;
112     }
113
114     if (m,This description was automagically extracted from the module by dh-make-perl,i) {
115         tag "description-contains-dh-make-perl-template";
116     }
117
118     my $wo_quotes = $_;
119     $wo_quotes =~ s,(\"|\')(.*?)(\1),,;
120     while ($wo_quotes =~ m,(?:\W|^)((\w+)(\s+(\2))+)(?:\W|\z),i) {
121         my $words = $1;
122         $wo_quotes =~ s/\Q$words//;
123         tag "description-contains-duplicated-word", "$words";
124     }
125
126     my $first_person = $_;
127     while ($first_person =~
128         m/(?:^|\s)(I|[Mm]y|[Oo]urs?|mine|myself|me|us|[Ww]e)(?:$|\s)/) {
129
130         my $word = $1;
131         $first_person =~ s/\Q$word//;
132         tag "using-first-person-in-description", "line $lines: $word";
133     }
134
135     if ($lines == 1) {
136         # checks for the first line of the extended description:
137         if (m/^ \s/o) {
138             tag "description-starts-with-leading-spaces", "";
139         }
140         if (m/^\s*missing\s*$/oi) {
141             tag "description-is-debmake-template", "" unless $template++;
142         } elsif (m/<insert long description, indented with spaces>/) {
143             tag "description-is-dh_make-template", "" unless $template++;
144         }
145     }
146
147     if (length($_) > 80) {
148         tag "extended-description-line-too-long", "";
149     }
150 }
151
152 if ($type ne 'udeb') {
153     if ($lines == 0) {
154         tag "extended-description-is-empty";
155     } elsif ($lines <= 2 and not $synopsis =~ /(dummy|transition)/i) {
156         tag "extended-description-is-probably-too-short";
157     }
158 }
159
160 # Check for a package homepage in the description and no Homepage field.  This
161 # is less accurate and more of a guess than looking for the old Homepage:
162 # convention in the body.
163 unless ($info->field('homepage') or $flagged_homepage) {
164     if ($description =~ /homepage|webpage|website|url|upstream|web\s+site
165                          |home\s+page|further\s+information|more\s+info
166                          |official\s+site|project\s+home/xi
167         and $description =~ m,\b(https?://[a-z0-9][^>\s]+),i) {
168         tag 'description-possibly-contains-homepage', $1;
169     } elsif ($description =~ m,\b(https?://[a-z0-9][^>\s]+)>?\.?\s*\z,i) {
170         tag 'description-possibly-contains-homepage', $1;
171     }
172 }
173
174 if ($description) {
175     spelling_check('spelling-error-in-description', $description);
176     spelling_check_picky('spelling-error-in-description', $description);
177 }
178
179 }
180
181 1;
182
183 # Local Variables:
184 # indent-tabs-mode: t
185 # cperl-indent-level: 4
186 # End:
187 # vim: syntax=perl sw=4 ts=8