| @@ -1,1001 +1,1001 @@ | | | @@ -1,1001 +1,1001 @@ |
1 | #! @PERL@ | | 1 | #! @PERL@ |
2 | # $NetBSD: pkglint.pl,v 1.862 2014/01/13 01:54:52 cheusov Exp $ | | 2 | # $NetBSD: pkglint.pl,v 1.863 2014/03/02 08:39:01 obache Exp $ |
3 | # | | 3 | # |
4 | | | 4 | |
5 | # pkglint - static analyzer and checker for pkgsrc packages | | 5 | # pkglint - static analyzer and checker for pkgsrc packages |
6 | # | | 6 | # |
7 | # Written by: | | 7 | # Written by: |
8 | # Roland Illig <rillig@NetBSD.org> | | 8 | # Roland Illig <rillig@NetBSD.org> |
9 | # | | 9 | # |
10 | # Based on work by: | | 10 | # Based on work by: |
11 | # Hubert Feyrer <hubertf@NetBSD.org> | | 11 | # Hubert Feyrer <hubertf@NetBSD.org> |
12 | # Thorsten Frueauf <frueauf@NetBSD.org> | | 12 | # Thorsten Frueauf <frueauf@NetBSD.org> |
13 | # Thomas Klausner <wiz@NetBSD.org> | | 13 | # Thomas Klausner <wiz@NetBSD.org> |
14 | # and others. | | 14 | # and others. |
15 | # | | 15 | # |
16 | # Based on FreeBSD's portlint by: | | 16 | # Based on FreeBSD's portlint by: |
17 | # Jun-ichiro itojun Hagino <itojun@itojun.org> | | 17 | # Jun-ichiro itojun Hagino <itojun@itojun.org> |
18 | # Yoshishige Arai <ryo2@on.rim.or.jp> | | 18 | # Yoshishige Arai <ryo2@on.rim.or.jp> |
19 | # | | 19 | # |
20 | # FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp | | 20 | # FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp |
21 | # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. | | 21 | # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. |
22 | # All rights reserved. | | 22 | # All rights reserved. |
23 | # Freely redistributable. Absolutely no warranty. | | 23 | # Freely redistributable. Absolutely no warranty. |
24 | | | 24 | |
25 | # To get an overview of the code, run: | | 25 | # To get an overview of the code, run: |
26 | # sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl | | 26 | # sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl |
27 | | | 27 | |
28 | #========================================================================== | | 28 | #========================================================================== |
29 | # Note: The @EXPORT clauses in the packages must be in a BEGIN block, | | 29 | # Note: The @EXPORT clauses in the packages must be in a BEGIN block, |
30 | # because otherwise the names starting with an uppercase letter are not | | 30 | # because otherwise the names starting with an uppercase letter are not |
31 | # recognized as subroutines but as file handles. | | 31 | # recognized as subroutines but as file handles. |
32 | #========================================================================== | | 32 | #========================================================================== |
33 | | | 33 | |
34 | use strict; | | 34 | use strict; |
35 | use warnings; | | 35 | use warnings; |
36 | | | 36 | |
37 | use PkgLint::Util; | | 37 | use PkgLint::Util; |
38 | use PkgLint::Logging; | | 38 | use PkgLint::Logging; |
39 | use PkgLint::SimpleMatch; | | 39 | use PkgLint::SimpleMatch; |
40 | use PkgLint::Line; | | 40 | use PkgLint::Line; |
41 | use PkgLint::FileUtil; | | 41 | use PkgLint::FileUtil; |
42 | use PkgLint::Type; | | 42 | use PkgLint::Type; |
43 | use PkgLint::VarUseContext; | | 43 | use PkgLint::VarUseContext; |
44 | use PkgLint::SubstContext; | | 44 | use PkgLint::SubstContext; |
45 | use PkgLint::CVS_Entry; | | 45 | use PkgLint::CVS_Entry; |
46 | use PkgLint::Change; | | 46 | use PkgLint::Change; |
47 | | | 47 | |
48 | package pkglint; | | 48 | package pkglint; |
49 | #========================================================================== | | 49 | #========================================================================== |
50 | # This package contains the application-specific code of pkglint. | | 50 | # This package contains the application-specific code of pkglint. |
51 | # Most subroutines in this package follow a strict naming convention: | | 51 | # Most subroutines in this package follow a strict naming convention: |
52 | # | | 52 | # |
53 | # The get_*() functions provide easy access to important non-trivial data | | 53 | # The get_*() functions provide easy access to important non-trivial data |
54 | # structures that are loaded from external files and are therefore cached. | | 54 | # structures that are loaded from external files and are therefore cached. |
55 | # | | 55 | # |
56 | # The is_*() functions return a boolean value and have no side effects. | | 56 | # The is_*() functions return a boolean value and have no side effects. |
57 | # | | 57 | # |
58 | # The checkline_*() procedures check a single line for compliance with some | | 58 | # The checkline_*() procedures check a single line for compliance with some |
59 | # rules. | | 59 | # rules. |
60 | # | | 60 | # |
61 | # The checklines_*() procedures check an array of lines for compliance. | | 61 | # The checklines_*() procedures check an array of lines for compliance. |
62 | # Usually they make use of several checkline_*() procedures. | | 62 | # Usually they make use of several checkline_*() procedures. |
63 | # | | 63 | # |
64 | # The checkfile_*() procedures load a file and check the lines of that | | 64 | # The checkfile_*() procedures load a file and check the lines of that |
65 | # file. Usually they make use of several checklines_*() and checkline_*() | | 65 | # file. Usually they make use of several checklines_*() and checkline_*() |
66 | # procedures. | | 66 | # procedures. |
67 | # | | 67 | # |
68 | # The checkdir_*() procedures check the files of a directory and call | | 68 | # The checkdir_*() procedures check the files of a directory and call |
69 | # checkfile_*() on them. | | 69 | # checkfile_*() on them. |
70 | # | | 70 | # |
71 | # Note: I have tried to order the subroutines so that there are no | | 71 | # Note: I have tried to order the subroutines so that there are no |
72 | # back-references, that is, if you start reading the code from the top to | | 72 | # back-references, that is, if you start reading the code from the top to |
73 | # the bottom you should not find a call to a subroutine you haven't yet | | 73 | # the bottom you should not find a call to a subroutine you haven't yet |
74 | # seen. | | 74 | # seen. |
75 | #========================================================================== | | 75 | #========================================================================== |
76 | use strict; | | 76 | use strict; |
77 | use warnings; | | 77 | use warnings; |
78 | | | 78 | |
79 | use Data::Dumper; | | 79 | use Data::Dumper; |
80 | use Digest::SHA1; | | 80 | use Digest::SHA1; |
81 | use Getopt::Long qw(:config no_ignore_case bundling require_order); | | 81 | use Getopt::Long qw(:config no_ignore_case bundling require_order); |
82 | use Fcntl qw(:mode); | | 82 | use Fcntl qw(:mode); |
83 | use File::Basename; | | 83 | use File::Basename; |
84 | use File::stat; | | 84 | use File::stat; |
85 | use Cwd; | | 85 | use Cwd; |
86 | use pkgsrc::Dewey; | | 86 | use pkgsrc::Dewey; |
87 | | | 87 | |
88 | BEGIN { | | 88 | BEGIN { |
89 | import PkgLint::Util qw( | | 89 | import PkgLint::Util qw( |
90 | array_to_hash assert | | 90 | array_to_hash assert |
91 | false true dont_know doesnt_matter | | 91 | false true dont_know doesnt_matter |
92 | normalize_pathname | | 92 | normalize_pathname |
93 | ); | | 93 | ); |
94 | import PkgLint::Logging qw( | | 94 | import PkgLint::Logging qw( |
95 | NO_FILE NO_LINE_NUMBER NO_LINES | | 95 | NO_FILE NO_LINE_NUMBER NO_LINES |
96 | log_fatal log_error log_warning log_note log_debug | | 96 | log_fatal log_error log_warning log_note log_debug |
97 | explain_error explain_warning explain_info | | 97 | explain_error explain_warning explain_info |
98 | ); | | 98 | ); |
99 | import PkgLint::FileUtil qw( | | 99 | import PkgLint::FileUtil qw( |
100 | load_file load_lines | | 100 | load_file load_lines |
101 | save_autofix_changes | | 101 | save_autofix_changes |
102 | ); | | 102 | ); |
103 | import PkgLint::Type qw( | | 103 | import PkgLint::Type qw( |
104 | LK_NONE LK_INTERNAL LK_EXTERNAL | | 104 | LK_NONE LK_INTERNAL LK_EXTERNAL |
105 | GUESSED NOT_GUESSED | | 105 | GUESSED NOT_GUESSED |
106 | ); | | 106 | ); |
107 | import PkgLint::VarUseContext qw( | | 107 | import PkgLint::VarUseContext qw( |
108 | VUC_TIME_UNKNOWN VUC_TIME_LOAD VUC_TIME_RUN | | 108 | VUC_TIME_UNKNOWN VUC_TIME_LOAD VUC_TIME_RUN |
109 | VUC_TYPE_UNKNOWN | | 109 | VUC_TYPE_UNKNOWN |
110 | VUC_SHELLWORD_UNKNOWN VUC_SHELLWORD_PLAIN VUC_SHELLWORD_DQUOT | | 110 | VUC_SHELLWORD_UNKNOWN VUC_SHELLWORD_PLAIN VUC_SHELLWORD_DQUOT |
111 | VUC_SHELLWORD_SQUOT VUC_SHELLWORD_BACKT VUC_SHELLWORD_FOR | | 111 | VUC_SHELLWORD_SQUOT VUC_SHELLWORD_BACKT VUC_SHELLWORD_FOR |
112 | VUC_EXTENT_UNKNOWN VUC_EXTENT_FULL VUC_EXTENT_WORD | | 112 | VUC_EXTENT_UNKNOWN VUC_EXTENT_FULL VUC_EXTENT_WORD |
113 | VUC_EXTENT_WORD_PART | | 113 | VUC_EXTENT_WORD_PART |
114 | ); | | 114 | ); |
115 | } | | 115 | } |
116 | | | 116 | |
117 | # | | 117 | # |
118 | # Buildtime configuration | | 118 | # Buildtime configuration |
119 | # | | 119 | # |
120 | | | 120 | |
121 | use constant conf_distver => '@DISTVER@'; | | 121 | use constant conf_distver => '@DISTVER@'; |
122 | use constant conf_make => '@MAKE@'; | | 122 | use constant conf_make => '@MAKE@'; |
123 | use constant conf_datadir => '@DATADIR@'; | | 123 | use constant conf_datadir => '@DATADIR@'; |
124 | | | 124 | |
125 | # | | 125 | # |
126 | # Global variables that can be modified via command line options. | | 126 | # Global variables that can be modified via command line options. |
127 | # | | 127 | # |
128 | | | 128 | |
129 | # The pkgsrc directory, relative to the current working directory of | | 129 | # The pkgsrc directory, relative to the current working directory of |
130 | # pkglint. | | 130 | # pkglint. |
131 | my $cwd_pkgsrcdir = undef; | | 131 | my $cwd_pkgsrcdir = undef; |
132 | | | 132 | |
133 | # The pkgsrc directory, relative to the directory that is currently | | 133 | # The pkgsrc directory, relative to the directory that is currently |
134 | # checked. | | 134 | # checked. |
135 | my $cur_pkgsrcdir = undef; | | 135 | my $cur_pkgsrcdir = undef; |
136 | | | 136 | |
137 | # | | 137 | # |
138 | # Command Line Options | | 138 | # Command Line Options |
139 | # | | 139 | # |
140 | | | 140 | |
141 | my $opt_check_ALTERNATIVES = true; | | 141 | my $opt_check_ALTERNATIVES = true; |
142 | my $opt_check_bl3 = true; | | 142 | my $opt_check_bl3 = true; |
143 | my $opt_check_DESCR = true; | | 143 | my $opt_check_DESCR = true; |
144 | my $opt_check_distinfo = true; | | 144 | my $opt_check_distinfo = true; |
145 | my $opt_check_extra = false; | | 145 | my $opt_check_extra = false; |
146 | my $opt_check_global = false; | | 146 | my $opt_check_global = false; |
147 | my $opt_check_INSTALL = true; | | 147 | my $opt_check_INSTALL = true; |
148 | my $opt_check_Makefile = true; | | 148 | my $opt_check_Makefile = true; |
149 | my $opt_check_MESSAGE = true; | | 149 | my $opt_check_MESSAGE = true; |
150 | my $opt_check_mk = true; | | 150 | my $opt_check_mk = true; |
151 | my $opt_check_patches = true; | | 151 | my $opt_check_patches = true; |
152 | my $opt_check_PLIST = true; | | 152 | my $opt_check_PLIST = true; |
153 | my (%checks) = ( | | 153 | my (%checks) = ( |
154 | "ALTERNATIVES" => [\$opt_check_ALTERNATIVES, "check ALTERNATIVES files"], | | 154 | "ALTERNATIVES" => [\$opt_check_ALTERNATIVES, "check ALTERNATIVES files"], |
155 | "bl3" => [\$opt_check_bl3, "check buildlink3 files"], | | 155 | "bl3" => [\$opt_check_bl3, "check buildlink3 files"], |
156 | "DESCR" => [\$opt_check_DESCR, "check DESCR file"], | | 156 | "DESCR" => [\$opt_check_DESCR, "check DESCR file"], |
157 | "distinfo" => [\$opt_check_distinfo, "check distinfo file"], | | 157 | "distinfo" => [\$opt_check_distinfo, "check distinfo file"], |
158 | "extra" => [\$opt_check_extra, "check various additional files"], | | 158 | "extra" => [\$opt_check_extra, "check various additional files"], |
159 | "global" => [\$opt_check_global, "inter-package checks"], | | 159 | "global" => [\$opt_check_global, "inter-package checks"], |
160 | "INSTALL" => [\$opt_check_INSTALL, "check INSTALL and DEINSTALL scripts"], | | 160 | "INSTALL" => [\$opt_check_INSTALL, "check INSTALL and DEINSTALL scripts"], |
161 | "Makefile" => [\$opt_check_Makefile, "check Makefiles"], | | 161 | "Makefile" => [\$opt_check_Makefile, "check Makefiles"], |
162 | "MESSAGE" => [\$opt_check_MESSAGE, "check MESSAGE files"], | | 162 | "MESSAGE" => [\$opt_check_MESSAGE, "check MESSAGE files"], |
163 | "mk" => [\$opt_check_mk, "check other .mk files"], | | 163 | "mk" => [\$opt_check_mk, "check other .mk files"], |
164 | "patches" => [\$opt_check_patches, "check patches"], | | 164 | "patches" => [\$opt_check_patches, "check patches"], |
165 | "PLIST" => [\$opt_check_PLIST, "check PLIST files"], | | 165 | "PLIST" => [\$opt_check_PLIST, "check PLIST files"], |
166 | ); | | 166 | ); |
167 | | | 167 | |
168 | my $opt_debug_include = false; | | 168 | my $opt_debug_include = false; |
169 | my $opt_debug_misc = false; | | 169 | my $opt_debug_misc = false; |
170 | my $opt_debug_patches = false; | | 170 | my $opt_debug_patches = false; |
171 | my $opt_debug_quoting = false; | | 171 | my $opt_debug_quoting = false; |
172 | my $opt_debug_shell = false; | | 172 | my $opt_debug_shell = false; |
173 | my $opt_debug_tools = false; | | 173 | my $opt_debug_tools = false; |
174 | my $opt_debug_trace = false; | | 174 | my $opt_debug_trace = false; |
175 | my $opt_debug_unchecked = false; | | 175 | my $opt_debug_unchecked = false; |
176 | my $opt_debug_unused = false; | | 176 | my $opt_debug_unused = false; |
177 | my $opt_debug_vartypes = false; | | 177 | my $opt_debug_vartypes = false; |
178 | my $opt_debug_varuse = false; | | 178 | my $opt_debug_varuse = false; |
179 | my (%debug) = ( | | 179 | my (%debug) = ( |
180 | "include" => [\$opt_debug_include, "included files"], | | 180 | "include" => [\$opt_debug_include, "included files"], |
181 | "misc" => [\$opt_debug_misc, "all things that didn't fit elsewhere"], | | 181 | "misc" => [\$opt_debug_misc, "all things that didn't fit elsewhere"], |
182 | "patches" => [\$opt_debug_patches, "the states of the patch parser"], | | 182 | "patches" => [\$opt_debug_patches, "the states of the patch parser"], |
183 | "quoting" => [\$opt_debug_quoting, "additional information about quoting"], | | 183 | "quoting" => [\$opt_debug_quoting, "additional information about quoting"], |
184 | "shell" => [\$opt_debug_shell, "the parsers for shell words and shell commands"], | | 184 | "shell" => [\$opt_debug_shell, "the parsers for shell words and shell commands"], |
185 | "tools" => [\$opt_debug_tools, "the tools framework"], | | 185 | "tools" => [\$opt_debug_tools, "the tools framework"], |
186 | "trace" => [\$opt_debug_trace, "follow subroutine calls"], | | 186 | "trace" => [\$opt_debug_trace, "follow subroutine calls"], |
187 | "unchecked" => [\$opt_debug_unchecked, "show the current limitations of pkglint"], | | 187 | "unchecked" => [\$opt_debug_unchecked, "show the current limitations of pkglint"], |
188 | "unused" => [\$opt_debug_unused, "unused variables"], | | 188 | "unused" => [\$opt_debug_unused, "unused variables"], |
189 | "vartypes" => [\$opt_debug_vartypes, "additional type information"], | | 189 | "vartypes" => [\$opt_debug_vartypes, "additional type information"], |
190 | "varuse" => [\$opt_debug_varuse, "contexts where variables are used"], | | 190 | "varuse" => [\$opt_debug_varuse, "contexts where variables are used"], |
191 | ); | | 191 | ); |
192 | | | 192 | |
193 | my $opt_warn_absname = true; | | 193 | my $opt_warn_absname = true; |
194 | my $opt_warn_directcmd = true; | | 194 | my $opt_warn_directcmd = true; |
195 | our $opt_warn_extra = false; # used by PkgLint::SubstContext | | 195 | our $opt_warn_extra = false; # used by PkgLint::SubstContext |
196 | my $opt_warn_order = true; | | 196 | my $opt_warn_order = true; |
197 | my $opt_warn_perm = false; | | 197 | my $opt_warn_perm = false; |
198 | my $opt_warn_plist_depr = false; | | 198 | my $opt_warn_plist_depr = false; |
199 | my $opt_warn_plist_sort = false; | | 199 | my $opt_warn_plist_sort = false; |
200 | my $opt_warn_quoting = false; | | 200 | my $opt_warn_quoting = false; |
201 | my $opt_warn_space = false; | | 201 | my $opt_warn_space = false; |
202 | my $opt_warn_style = false; | | 202 | my $opt_warn_style = false; |
203 | my $opt_warn_types = true; | | 203 | my $opt_warn_types = true; |
204 | my $opt_warn_varorder = false; | | 204 | my $opt_warn_varorder = false; |
205 | my (%warnings) = ( | | 205 | my (%warnings) = ( |
206 | "absname" => [\$opt_warn_absname, "warn about use of absolute file names"], | | 206 | "absname" => [\$opt_warn_absname, "warn about use of absolute file names"], |
207 | "directcmd" => [\$opt_warn_directcmd, "warn about use of direct command names instead of Make variables"], | | 207 | "directcmd" => [\$opt_warn_directcmd, "warn about use of direct command names instead of Make variables"], |
208 | "extra" => [\$opt_warn_extra, "enable some extra warnings"], | | 208 | "extra" => [\$opt_warn_extra, "enable some extra warnings"], |
209 | "order" => [\$opt_warn_order, "warn if Makefile entries are unordered"], | | 209 | "order" => [\$opt_warn_order, "warn if Makefile entries are unordered"], |
210 | "perm" => [\$opt_warn_perm, "warn about unforeseen variable definition and use"], | | 210 | "perm" => [\$opt_warn_perm, "warn about unforeseen variable definition and use"], |
211 | "plist-depr" => [\$opt_warn_plist_depr, "warn about deprecated paths in PLISTs"], | | 211 | "plist-depr" => [\$opt_warn_plist_depr, "warn about deprecated paths in PLISTs"], |
212 | "plist-sort" => [\$opt_warn_plist_sort, "warn about unsorted entries in PLISTs"], | | 212 | "plist-sort" => [\$opt_warn_plist_sort, "warn about unsorted entries in PLISTs"], |
213 | "quoting" => [\$opt_warn_quoting, "warn about quoting issues"], | | 213 | "quoting" => [\$opt_warn_quoting, "warn about quoting issues"], |
214 | "space" => [\$opt_warn_space, "warn about inconsistent use of white-space"], | | 214 | "space" => [\$opt_warn_space, "warn about inconsistent use of white-space"], |
215 | "style" => [\$opt_warn_style, "warn about stylistic issues"], | | 215 | "style" => [\$opt_warn_style, "warn about stylistic issues"], |
216 | "types" => [\$opt_warn_types, "do some simple type checking in Makefiles"], | | 216 | "types" => [\$opt_warn_types, "do some simple type checking in Makefiles"], |
217 | "varorder" => [\$opt_warn_varorder, "warn about the ordering of variables"], | | 217 | "varorder" => [\$opt_warn_varorder, "warn about the ordering of variables"], |
218 | ); | | 218 | ); |
219 | | | 219 | |
220 | my $opt_autofix = false; | | 220 | my $opt_autofix = false; |
221 | my $opt_dumpmakefile = false; | | 221 | my $opt_dumpmakefile = false; |
222 | my $opt_import = false; | | 222 | my $opt_import = false; |
223 | my $opt_quiet = false; | | 223 | my $opt_quiet = false; |
224 | my $opt_recursive = false; | | 224 | my $opt_recursive = false; |
225 | my $opt_rcsidstring = "NetBSD"; | | 225 | my $opt_rcsidstring = "NetBSD"; |
226 | my (@options) = ( | | 226 | my (@options) = ( |
227 | # [ usage-opt, usage-message, getopt-opt, getopt-action ] | | 227 | # [ usage-opt, usage-message, getopt-opt, getopt-action ] |
228 | [ "-C{check,...}", "Enable or disable specific checks", | | 228 | [ "-C{check,...}", "Enable or disable specific checks", |
229 | "check|C=s", | | 229 | "check|C=s", |
230 | sub { | | 230 | sub { |
231 | my ($opt, $val) = @_; | | 231 | my ($opt, $val) = @_; |
232 | parse_multioption($val, \%checks); | | 232 | parse_multioption($val, \%checks); |
233 | } ], | | 233 | } ], |
234 | [ "-D{debug,...}", "Enable or disable debugging categories", | | 234 | [ "-D{debug,...}", "Enable or disable debugging categories", |
235 | "debugging|D=s", | | 235 | "debugging|D=s", |
236 | sub ($$) { | | 236 | sub ($$) { |
237 | my ($opt, $val) = @_; | | 237 | my ($opt, $val) = @_; |
238 | parse_multioption($val, \%debug); | | 238 | parse_multioption($val, \%debug); |
239 | } ], | | 239 | } ], |
240 | [ "-F|--autofix", "Try to automatically fix some errors (experimental)", | | 240 | [ "-F|--autofix", "Try to automatically fix some errors (experimental)", |
241 | "autofix|F", \$opt_autofix ], | | 241 | "autofix|F", \$opt_autofix ], |
242 | [ "-I|--dumpmakefile", "Dump the Makefile after parsing", | | 242 | [ "-I|--dumpmakefile", "Dump the Makefile after parsing", |
243 | "dumpmakefile|I", \$opt_dumpmakefile ], | | 243 | "dumpmakefile|I", \$opt_dumpmakefile ], |
244 | [ "-R|--rcsidstring", "Set the allowed RCS Id strings", | | 244 | [ "-R|--rcsidstring", "Set the allowed RCS Id strings", |
245 | "rcsidstring|R=s", \$opt_rcsidstring ], | | 245 | "rcsidstring|R=s", \$opt_rcsidstring ], |
246 | [ "-V|--version", "print the version number of pkglint", | | 246 | [ "-V|--version", "print the version number of pkglint", |
247 | "version|V", | | 247 | "version|V", |
248 | sub { | | 248 | sub { |
249 | print(conf_distver . "\n"); | | 249 | print(conf_distver . "\n"); |
250 | exit(0); | | 250 | exit(0); |
251 | } ], | | 251 | } ], |
252 | [ "-W{warn,...}", "enable or disable specific warnings", | | 252 | [ "-W{warn,...}", "enable or disable specific warnings", |
253 | "warning|W=s", | | 253 | "warning|W=s", |
254 | sub { | | 254 | sub { |
255 | my ($opt, $val) = @_; | | 255 | my ($opt, $val) = @_; |
256 | parse_multioption($val, \%warnings); | | 256 | parse_multioption($val, \%warnings); |
257 | } ], | | 257 | } ], |
258 | [ "-e|--explain", "Explain the diagnostics or give further help", | | 258 | [ "-e|--explain", "Explain the diagnostics or give further help", |
259 | "explain|e", sub { | | 259 | "explain|e", sub { |
260 | PkgLint::Logging::set_explain(); | | 260 | PkgLint::Logging::set_explain(); |
261 | } ], | | 261 | } ], |
262 | [ "-g|--gcc-output-format", "Mimic the gcc output format", | | 262 | [ "-g|--gcc-output-format", "Mimic the gcc output format", |
263 | "gcc-output-format|g", | | 263 | "gcc-output-format|g", |
264 | sub { | | 264 | sub { |
265 | PkgLint::Logging::set_gcc_output_format(); | | 265 | PkgLint::Logging::set_gcc_output_format(); |
266 | } ], | | 266 | } ], |
267 | [ "-h|--help", "print a detailed help message", | | 267 | [ "-h|--help", "print a detailed help message", |
268 | "help|h", | | 268 | "help|h", |
269 | sub { | | 269 | sub { |
270 | help(*STDOUT, 0, 1); | | 270 | help(*STDOUT, 0, 1); |
271 | } ], | | 271 | } ], |
272 | [ "-i|--import", "Prepare the import of a wip package", | | 272 | [ "-i|--import", "Prepare the import of a wip package", |
273 | "import|i", \$opt_import ], | | 273 | "import|i", \$opt_import ], |
274 | # Note: This is intentionally undocumented. | | 274 | # Note: This is intentionally undocumented. |
275 | [ "--pkgsrcdir", "Set the root directory of pkgsrc explicitly.", | | 275 | [ "--pkgsrcdir", "Set the root directory of pkgsrc explicitly.", |
276 | "pkgsrcdir=s", \$cwd_pkgsrcdir ], | | 276 | "pkgsrcdir=s", \$cwd_pkgsrcdir ], |
277 | [ "-q|--quiet", "Don't print a summary line when finishing", | | 277 | [ "-q|--quiet", "Don't print a summary line when finishing", |
278 | "quiet|q", \$opt_quiet ], | | 278 | "quiet|q", \$opt_quiet ], |
279 | [ "-r|--recursive", "Recursive---check subdirectories, too", | | 279 | [ "-r|--recursive", "Recursive---check subdirectories, too", |
280 | "recursive|r", \$opt_recursive ], | | 280 | "recursive|r", \$opt_recursive ], |
281 | [ "-s|--source", "Show the source lines together with diagnostics", | | 281 | [ "-s|--source", "Show the source lines together with diagnostics", |
282 | "source|s", | | 282 | "source|s", |
283 | sub { | | 283 | sub { |
284 | PkgLint::Logging::set_show_source_flag(); | | 284 | PkgLint::Logging::set_show_source_flag(); |
285 | } ], | | 285 | } ], |
286 | ); | | 286 | ); |
287 | | | 287 | |
288 | our $program = $0; | | 288 | our $program = $0; |
289 | | | 289 | |
290 | # | | 290 | # |
291 | # Commonly used regular expressions. | | 291 | # Commonly used regular expressions. |
292 | # | | 292 | # |
293 | | | 293 | |
294 | use constant regex_dependency_lge => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d])+)[<>]=?(\d[^-*?\[\]]*)$"; | | 294 | use constant regex_dependency_lge => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d])+)[<>]=?(\d[^-*?\[\]]*)$"; |
295 | use constant regex_dependency_wildcard | | 295 | use constant regex_dependency_wildcard |
296 | => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d\[])+)-(?:\[0-9\]\*|\d[^-]*)$"; | | 296 | => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d\[])+)-(?:\[0-9\]\*|\d[^-]*)$"; |
297 | use constant regex_gnu_configure_volatile_vars | | 297 | use constant regex_gnu_configure_volatile_vars |
298 | => qr"^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$"; | | 298 | => qr"^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$"; |
299 | use constant regex_mk_comment => qr"^ *\s*#(.*)$"; | | 299 | use constant regex_mk_comment => qr"^ *\s*#(.*)$"; |
300 | use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$"; | | 300 | use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$"; |
301 | use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$"; | | 301 | use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$"; |
302 | use constant regex_mk_include => qr"^\.\s*(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$"; | | 302 | use constant regex_mk_include => qr"^\.\s*(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$"; |
303 | use constant regex_mk_sysinclude=> qr"^\.\s*s?include\s+<([^>]+)>\s*(?:#.*)?$"; | | 303 | use constant regex_mk_sysinclude=> qr"^\.\s*s?include\s+<([^>]+)>\s*(?:#.*)?$"; |
304 | use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect | | 304 | use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect |
305 | use constant regex_pkgname => qr"^([\w\-.+]+)-(\d(?:\w|\.\d)*)$"; | | 305 | use constant regex_pkgname => qr"^([\w\-.+]+)-(\d(?:\w|\.\d)*)$"; |
306 | use constant regex_mk_shellcmd => qr"^\t(.*)$"; | | 306 | use constant regex_mk_shellcmd => qr"^\t(.*)$"; |
307 | use constant regex_rcs_conflict => qr"^(<<<<<<<|=======|>>>>>>>)"; | | 307 | use constant regex_rcs_conflict => qr"^(<<<<<<<|=======|>>>>>>>)"; |
308 | use constant regex_unresolved => qr"\$\{"; | | 308 | use constant regex_unresolved => qr"\$\{"; |
309 | use constant regex_validchars => qr"[\011\040-\176]"; | | 309 | use constant regex_validchars => qr"[\011\040-\176]"; |
310 | # Note: the following regular expression looks more complicated than | | 310 | # Note: the following regular expression looks more complicated than |
311 | # necessary to avoid a stack overflow in the Perl interpreter. | | 311 | # necessary to avoid a stack overflow in the Perl interpreter. |
312 | # The leading white-space may only consist of \040 characters, otherwise | | 312 | # The leading white-space may only consist of \040 characters, otherwise |
313 | # the order of regex_varassign and regex_mk_shellcmd becomes important. | | 313 | # the order of regex_varassign and regex_mk_shellcmd becomes important. |
314 | use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$"; | | 314 | use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$"; |
315 | use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)="; | | 315 | use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)="; |
316 | | | 316 | |
317 | # The following "constants" are often used in contexts where | | 317 | # The following "constants" are often used in contexts where |
318 | # interpolation comes handy, so they are variables. Nevertheless they | | 318 | # interpolation comes handy, so they are variables. Nevertheless they |
319 | # are not modified. | | 319 | # are not modified. |
320 | | | 320 | |
321 | # This regular expression cannot parse all kinds of shell programs, but | | 321 | # This regular expression cannot parse all kinds of shell programs, but |
322 | # it will catch almost all shell programs that are portable enough to be | | 322 | # it will catch almost all shell programs that are portable enough to be |
323 | # used in pkgsrc. | | 323 | # used in pkgsrc. |
324 | my $regex_shellword = qr"\s*( | | 324 | my $regex_shellword = qr"\s*( |
325 | \#.* # shell comment | | 325 | \#.* # shell comment |
326 | | | | 326 | | |
327 | (?: '[^']*' # single quoted string | | 327 | (?: '[^']*' # single quoted string |
328 | | \"(?:\\.|[^\"\\])*\" # double quoted string | | 328 | | \"(?:\\.|[^\"\\])*\" # double quoted string |
329 | | \`[^\`]*\` # backticks string | | 329 | | \`[^\`]*\` # backticks string |
330 | | \\\$\$ # an escaped dollar sign | | 330 | | \\\$\$ # an escaped dollar sign |
331 | | \\[^\$] # other escaped characters | | 331 | | \\[^\$] # other escaped characters |
332 | | \$[\w_] # one-character make(1) variable | | 332 | | \$[\w_] # one-character make(1) variable |
333 | | \$\{[^{}]+\} # make(1) variable | | 333 | | \$\{[^{}]+\} # make(1) variable |
334 | | \$\([^()]+\) # make(1) variable, $(...) | | 334 | | \$\([^()]+\) # make(1) variable, $(...) |
335 | | \$[/\@<^] # special make(1) variables | | 335 | | \$[/\@<^] # special make(1) variables |
336 | | \$\$[0-9A-Z_a-z]+ # shell variable | | 336 | | \$\$[0-9A-Z_a-z]+ # shell variable |
337 | | \$\$[\#?@] # special shell variables | | 337 | | \$\$[\#?@] # special shell variables |
338 | | \$\$\$\$ # the special pid shell variable | | 338 | | \$\$\$\$ # the special pid shell variable |
339 | | \$\$\{[0-9A-Z_a-z]+\} # shell variable in braces | | 339 | | \$\$\{[0-9A-Z_a-z]+\} # shell variable in braces |
340 | | \$\$\( # POSIX-style backticks replacement | | 340 | | \$\$\( # POSIX-style backticks replacement |
341 | | [^\(\)'\"\\\s;&\|<>\`\$] # non-special character | | 341 | | [^\(\)'\"\\\s;&\|<>\`\$] # non-special character |
342 | | \$\{[^\s\"'`]+ # HACK: nested make(1) variables | | 342 | | \$\{[^\s\"'`]+ # HACK: nested make(1) variables |
343 | )+ | ;;? | &&? | \|\|? | \( | \) | >& | <<? | >>? | \#.*)"sx; | | 343 | )+ | ;;? | &&? | \|\|? | \( | \) | >& | <<? | >>? | \#.*)"sx; |
344 | my $regex_varname = qr"(?:[-*+.0-9A-Z_a-z{}\[]+|\$\{[\w_]+\})+"; | | 344 | my $regex_varname = qr"(?:[-*+.0-9A-Z_a-z{}\[]+|\$\{[\w_]+\})+"; |
345 | my $regex_pkgbase = qr"(?:[+.0-9A-Z_a-z]|-[A-Z_a-z])+"; | | 345 | my $regex_pkgbase = qr"(?:[+.0-9A-Z_a-z]|-[A-Z_a-z])+"; |
346 | my $regex_pkgversion = qr"\d(?:\w|\.\d)*"; | | 346 | my $regex_pkgversion = qr"\d(?:\w|\.\d)*"; |
347 | | | 347 | |
348 | # | | 348 | # |
349 | # Commonly used explanations for diagnostics. | | 349 | # Commonly used explanations for diagnostics. |
350 | # | | 350 | # |
351 | | | 351 | |
352 | use constant expl_relative_dirs => ( | | 352 | use constant expl_relative_dirs => ( |
353 | "Directories in the form \"../../category/package\" make it easier to", | | 353 | "Directories in the form \"../../category/package\" make it easier to", |
354 | "move a package around in pkgsrc, for example from pkgsrc-wip to the", | | 354 | "move a package around in pkgsrc, for example from pkgsrc-wip to the", |
355 | "main pkgsrc repository."); | | 355 | "main pkgsrc repository."); |
356 | | | 356 | |
357 | # | | 357 | # |
358 | # Global variables. | | 358 | # Global variables. |
359 | # | | 359 | # |
360 | | | 360 | |
361 | my $current_dir; # The currently checked directory. | | 361 | my $current_dir; # The currently checked directory. |
362 | my $is_wip; # Is the current directory from pkgsrc-wip? | | 362 | my $is_wip; # Is the current directory from pkgsrc-wip? |
363 | my $is_internal; # Is the current item from the infrastructure? | | 363 | my $is_internal; # Is the current item from the infrastructure? |
364 | | | 364 | |
365 | # | | 365 | # |
366 | # Variables for inter-package checks. | | 366 | # Variables for inter-package checks. |
367 | # | | 367 | # |
368 | | | 368 | |
369 | my $ipc_distinfo; # Maps "$alg:$fname" => "checksum". | | 369 | my $ipc_distinfo; # Maps "$alg:$fname" => "checksum". |
370 | my %ipc_used_licenses; # { license name => true } | | 370 | my %ipc_used_licenses; # { license name => true } |
371 | my $ipc_checking_root_recursively; # For checking unused licenses | | 371 | my $ipc_checking_root_recursively; # For checking unused licenses |
372 | | | 372 | |
373 | # Context of the package that is currently checked. | | 373 | # Context of the package that is currently checked. |
374 | my $pkgpath; # The relative path to the package within PKGSRC | | 374 | my $pkgpath; # The relative path to the package within PKGSRC |
375 | my $pkgdir; # PKGDIR from the package Makefile | | 375 | my $pkgdir; # PKGDIR from the package Makefile |
376 | my $filesdir; # FILESDIR from the package Makefile | | 376 | my $filesdir; # FILESDIR from the package Makefile |
377 | my $patchdir; # PATCHDIR from the package Makefile | | 377 | my $patchdir; # PATCHDIR from the package Makefile |
378 | my $distinfo_file; # DISTINFO_FILE from the package Makefile | | 378 | my $distinfo_file; # DISTINFO_FILE from the package Makefile |
379 | my $effective_pkgname; # PKGNAME or DISTNAME from the package Makefile | | 379 | my $effective_pkgname; # PKGNAME or DISTNAME from the package Makefile |
380 | my $effective_pkgbase; # The effective PKGNAME without the version | | 380 | my $effective_pkgbase; # The effective PKGNAME without the version |
381 | my $effective_pkgversion; # The version part of the effective PKGNAME | | 381 | my $effective_pkgversion; # The version part of the effective PKGNAME |
382 | my $effective_pkgname_line; # The origin of the three effective_* values | | 382 | my $effective_pkgname_line; # The origin of the three effective_* values |
383 | my $seen_bsd_prefs_mk; # Has bsd.prefs.mk already been included? | | 383 | my $seen_bsd_prefs_mk; # Has bsd.prefs.mk already been included? |
384 | | | 384 | |
385 | my $pkgctx_vardef; # { varname => line } | | 385 | my $pkgctx_vardef; # { varname => line } |
386 | my $pkgctx_varuse; # { varname => line } | | 386 | my $pkgctx_varuse; # { varname => line } |
387 | my $pkgctx_bl3; # { buildlink3.mk name => line } (contains | | 387 | my $pkgctx_bl3; # { buildlink3.mk name => line } (contains |
388 | # only buildlink3.mk files that are directly | | 388 | # only buildlink3.mk files that are directly |
389 | # included) | | 389 | # included) |
390 | my $pkgctx_plist_subst_cond; # { varname => 1 } list of all variables | | 390 | my $pkgctx_plist_subst_cond; # { varname => 1 } list of all variables |
391 | # that are used as conditionals (@comment | | 391 | # that are used as conditionals (@comment |
392 | # or nothing) in PLISTs. | | 392 | # or nothing) in PLISTs. |
393 | my $pkgctx_included; # { fname => line } | | 393 | my $pkgctx_included; # { fname => line } |
394 | my $seen_Makefile_common; # Does the package have any .includes? | | 394 | my $seen_Makefile_common; # Does the package have any .includes? |
395 | | | 395 | |
396 | # Context of the Makefile that is currently checked. | | 396 | # Context of the Makefile that is currently checked. |
397 | my $mkctx_for_variables; # The variables currently used in .for loops | | 397 | my $mkctx_for_variables; # The variables currently used in .for loops |
398 | my $mkctx_indentations; # Indentation depth of preprocessing directives | | 398 | my $mkctx_indentations; # Indentation depth of preprocessing directives |
399 | my $mkctx_target; # Current make(1) target | | 399 | my $mkctx_target; # Current make(1) target |
400 | my $mkctx_vardef; # { varname => line } for all variables that | | 400 | my $mkctx_vardef; # { varname => line } for all variables that |
401 | # are defined in the current file | | 401 | # are defined in the current file |
402 | my $mkctx_varuse; # { varname => line } for all variables | | 402 | my $mkctx_varuse; # { varname => line } for all variables |
403 | # that are used in the current file | | 403 | # that are used in the current file |
404 | my $mkctx_build_defs; # Set of variables that are registered in | | 404 | my $mkctx_build_defs; # Set of variables that are registered in |
405 | # BUILD_DEFS, to assure that all user-defined | | 405 | # BUILD_DEFS, to assure that all user-defined |
406 | # variables are added to it. | | 406 | # variables are added to it. |
407 | my $mkctx_plist_vars; # The same for PLIST_VARS. | | 407 | my $mkctx_plist_vars; # The same for PLIST_VARS. |
408 | my $mkctx_tools; # Set of tools that are declared to be used. | | 408 | my $mkctx_tools; # Set of tools that are declared to be used. |
409 | | | 409 | |
410 | my @todo_items; # The list of directory entries that still need | | 410 | my @todo_items; # The list of directory entries that still need |
411 | # to be checked. Mostly relevant with | | 411 | # to be checked. Mostly relevant with |
412 | # --recursive. | | 412 | # --recursive. |
413 | | | 413 | |
414 | # | | 414 | # |
415 | # Command line parsing and handling. | | 415 | # Command line parsing and handling. |
416 | # | | 416 | # |
417 | | | 417 | |
418 | sub help($$$) { | | 418 | sub help($$$) { |
419 | my ($out, $exitval, $show_all) = @_; | | 419 | my ($out, $exitval, $show_all) = @_; |
420 | my ($prog) = (basename($program, '.pl')); | | 420 | my ($prog) = (basename($program, '.pl')); |
421 | print $out ("usage: $prog [options] [package_directory]\n\n"); | | 421 | print $out ("usage: $prog [options] [package_directory]\n\n"); |
422 | | | 422 | |
423 | my (@option_table) = (); | | 423 | my (@option_table) = (); |
424 | foreach my $opt (@options) { | | 424 | foreach my $opt (@options) { |
425 | push(@option_table, [" ", $opt->[0], $opt->[1]]); | | 425 | push(@option_table, [" ", $opt->[0], $opt->[1]]); |
426 | } | | 426 | } |
427 | print $out ("options:\n"); | | 427 | print $out ("options:\n"); |
428 | PkgLint::Util::print_table($out, \@option_table); | | 428 | PkgLint::Util::print_table($out, \@option_table); |
429 | print $out ("\n"); | | 429 | print $out ("\n"); |
430 | | | 430 | |
431 | if (!$show_all) { | | 431 | if (!$show_all) { |
432 | exit($exitval); | | 432 | exit($exitval); |
433 | } | | 433 | } |
434 | | | 434 | |
435 | my $categories = [ | | 435 | my $categories = [ |
436 | # options, leading text, | | 436 | # options, leading text, |
437 | [ \%checks, "checks", "check" ], | | 437 | [ \%checks, "checks", "check" ], |
438 | [ \%debug, "debugging options", "debug" ], | | 438 | [ \%debug, "debugging options", "debug" ], |
439 | [ \%warnings, "warnings", "warning" ], | | 439 | [ \%warnings, "warnings", "warning" ], |
440 | ]; | | 440 | ]; |
441 | foreach my $category (@{$categories}) { | | 441 | foreach my $category (@{$categories}) { |
442 | my ($options, $leading, $name) = (@{$category}); | | 442 | my ($options, $leading, $name) = (@{$category}); |
443 | my $table = [ | | 443 | my $table = [ |
444 | [" ", "all", "", "enable all ".$category->[1]], | | 444 | [" ", "all", "", "enable all ".$category->[1]], |
445 | [" ", "none", "", "disable all ".$category->[1]], | | 445 | [" ", "none", "", "disable all ".$category->[1]], |
446 | ]; | | 446 | ]; |
447 | | | 447 | |
448 | foreach my $opt (sort keys %{$options}) { | | 448 | foreach my $opt (sort keys %{$options}) { |
449 | push(@{$table}, [ " ", $opt, | | 449 | push(@{$table}, [ " ", $opt, |
450 | (${$options->{$opt}->[0]} ? "(enabled)" : "(disabled)"), | | 450 | (${$options->{$opt}->[0]} ? "(enabled)" : "(disabled)"), |
451 | $options->{$opt}->[1]]); | | 451 | $options->{$opt}->[1]]); |
452 | } | | 452 | } |
453 | | | 453 | |
454 | print $out ("${leading}: (use \"${name}\" to enable, \"no-${name}\" to disable)\n"); | | 454 | print $out ("${leading}: (use \"${name}\" to enable, \"no-${name}\" to disable)\n"); |
455 | PkgLint::Util::print_table($out, $table); | | 455 | PkgLint::Util::print_table($out, $table); |
456 | print $out ("\n"); | | 456 | print $out ("\n"); |
457 | } | | 457 | } |
458 | | | 458 | |
459 | exit($exitval); | | 459 | exit($exitval); |
460 | } | | 460 | } |
461 | | | 461 | |
462 | sub parse_multioption($$) { | | 462 | sub parse_multioption($$) { |
463 | my ($value, $optdefs) = @_; | | 463 | my ($value, $optdefs) = @_; |
464 | foreach my $opt (split(qr",", $value)) { | | 464 | foreach my $opt (split(qr",", $value)) { |
465 | if ($opt eq "none") { | | 465 | if ($opt eq "none") { |
466 | foreach my $key (keys %{$optdefs}) { | | 466 | foreach my $key (keys %{$optdefs}) { |
467 | ${$optdefs->{$key}->[0]} = false; | | 467 | ${$optdefs->{$key}->[0]} = false; |
468 | } | | 468 | } |
469 | | | 469 | |
470 | } elsif ($opt eq "all") { | | 470 | } elsif ($opt eq "all") { |
471 | foreach my $key (keys %{$optdefs}) { | | 471 | foreach my $key (keys %{$optdefs}) { |
472 | ${$optdefs->{$key}->[0]} = true; | | 472 | ${$optdefs->{$key}->[0]} = true; |
473 | } | | 473 | } |
474 | | | 474 | |
475 | } else { | | 475 | } else { |
476 | my ($value) = (($opt =~ s/^no-//) ? false : true); | | 476 | my ($value) = (($opt =~ s/^no-//) ? false : true); |
477 | if (exists($optdefs->{$opt})) { | | 477 | if (exists($optdefs->{$opt})) { |
478 | ${$optdefs->{$opt}->[0]} = $value; | | 478 | ${$optdefs->{$opt}->[0]} = $value; |
479 | } else { | | 479 | } else { |
480 | print STDERR ("Invalid option: ${opt}\n"); | | 480 | print STDERR ("Invalid option: ${opt}\n"); |
481 | help(*STDERR, 1, 0); | | 481 | help(*STDERR, 1, 0); |
482 | } | | 482 | } |
483 | } | | 483 | } |
484 | } | | 484 | } |
485 | } | | 485 | } |
486 | | | 486 | |
487 | sub parse_command_line() { | | 487 | sub parse_command_line() { |
488 | my (%options); | | 488 | my (%options); |
489 | | | 489 | |
490 | foreach my $opt (@options) { | | 490 | foreach my $opt (@options) { |
491 | $options{$opt->[2]} = $opt->[3]; | | 491 | $options{$opt->[2]} = $opt->[3]; |
492 | } | | 492 | } |
493 | | | 493 | |
494 | { | | 494 | { |
495 | local $SIG{__WARN__} = sub {}; | | 495 | local $SIG{__WARN__} = sub {}; |
496 | if (!GetOptions(%options)) { | | 496 | if (!GetOptions(%options)) { |
497 | help(*STDERR, 1, false); | | 497 | help(*STDERR, 1, false); |
498 | } | | 498 | } |
499 | } | | 499 | } |
500 | } | | 500 | } |
501 | | | 501 | |
502 | # | | 502 | # |
503 | # Caching subroutines. | | 503 | # Caching subroutines. |
504 | # | | 504 | # |
505 | | | 505 | |
506 | # The get_regex_plurals() function returns a regular expression that | | 506 | # The get_regex_plurals() function returns a regular expression that |
507 | # matches for all make(1) variable names that are considered lists | | 507 | # matches for all make(1) variable names that are considered lists |
508 | # of something. | | 508 | # of something. |
509 | # | | 509 | # |
510 | # Rationale: | | 510 | # Rationale: |
511 | # | | 511 | # |
512 | # The pkglint author thinks that variables containing lists of things | | 512 | # The pkglint author thinks that variables containing lists of things |
513 | # should have a name indicating some plural form. Sadly, there are other | | 513 | # should have a name indicating some plural form. Sadly, there are other |
514 | # reasons like backwards compatibility and other developer's | | 514 | # reasons like backwards compatibility and other developer's |
515 | # expectations that make changes to most of the following variables | | 515 | # expectations that make changes to most of the following variables |
516 | # highly unlikely. | | 516 | # highly unlikely. |
517 | my $get_regex_plurals_value = undef; | | 517 | my $get_regex_plurals_value = undef; |
518 | sub get_regex_plurals() { | | 518 | sub get_regex_plurals() { |
519 | | | 519 | |
520 | if (defined($get_regex_plurals_value)) { | | 520 | if (defined($get_regex_plurals_value)) { |
521 | return $get_regex_plurals_value; | | 521 | return $get_regex_plurals_value; |
522 | } | | 522 | } |
523 | | | 523 | |
524 | my @plurals_ok = qw( | | 524 | my @plurals_ok = qw( |
525 | .*S | | 525 | .*S |
526 | .*LIST | | 526 | .*LIST |
527 | .*_AWK | | 527 | .*_AWK |
528 | .*_ENV | | 528 | .*_ENV |
529 | .*_REQD | | 529 | .*_REQD |
530 | .*_SED | | 530 | .*_SED |
531 | .*_SKIP | | 531 | .*_SKIP |
532 | BUILDLINK_LDADD | | 532 | BUILDLINK_LDADD |
533 | COMMENT | | 533 | COMMENT |
534 | EXTRACT_ONLY | | 534 | EXTRACT_ONLY |
535 | FETCH_MESSAGE | | 535 | FETCH_MESSAGE |
536 | GENERATE_PLIST | | 536 | GENERATE_PLIST |
537 | PLIST_CAT | | 537 | PLIST_CAT |
538 | PLIST_PRE | | 538 | PLIST_PRE |
539 | PREPEND_PATH | | 539 | PREPEND_PATH |
540 | ); | | 540 | ); |
541 | my @plurals_missing_an_s = qw( | | 541 | my @plurals_missing_an_s = qw( |
542 | .*_OVERRIDE | | 542 | .*_OVERRIDE |
543 | .*_PREREQ | | 543 | .*_PREREQ |
544 | .*_SRC | | 544 | .*_SRC |
545 | .*_SUBST | | 545 | .*_SUBST |
546 | .*_TARGET | | 546 | .*_TARGET |
547 | .*_TMPL | | 547 | .*_TMPL |
548 | BUILDLINK_DEPMETHOD | | 548 | BUILDLINK_DEPMETHOD |
549 | BUILDLINK_TRANSFORM | | 549 | BUILDLINK_TRANSFORM |
550 | EVAL_PREFIX | | 550 | EVAL_PREFIX |
551 | INTERACTIVE_STAGE | | 551 | INTERACTIVE_STAGE |
552 | LICENSE | | 552 | LICENSE |
553 | MASTER_SITE_.* | | 553 | MASTER_SITE_.* |
554 | MASTER_SORT_REGEX | | 554 | MASTER_SORT_REGEX |
555 | NOT_FOR_COMPILER | | 555 | NOT_FOR_COMPILER |
556 | NOT_FOR_PLATFORM | | 556 | NOT_FOR_PLATFORM |
557 | ONLY_FOR_COMPILER | | 557 | ONLY_FOR_COMPILER |
558 | ONLY_FOR_PLATFORM | | 558 | ONLY_FOR_PLATFORM |
559 | PERL5_PACKLIST | | 559 | PERL5_PACKLIST |
560 | PKG_FAIL_REASON | | 560 | PKG_FAIL_REASON |
561 | PKG_SKIP_REASON | | 561 | PKG_SKIP_REASON |
562 | ); | | 562 | ); |
563 | my @plurals_reluctantly_accepted = qw( | | 563 | my @plurals_reluctantly_accepted = qw( |
564 | CRYPTO | | 564 | CRYPTO |
565 | DEINSTALL_TEMPLATE | | 565 | DEINSTALL_TEMPLATE |
566 | FIX_RPATH | | 566 | FIX_RPATH |
567 | INSTALL_TEMPLATE | | 567 | INSTALL_TEMPLATE |
568 | PYTHON_VERSIONS_INCOMPATIBLE | | 568 | PYTHON_VERSIONS_INCOMPATIBLE |
569 | REPLACE_INTERPRETER | | 569 | REPLACE_INTERPRETER |
570 | REPLACE_PERL | | 570 | REPLACE_PERL |
571 | REPLACE_RUBY | | 571 | REPLACE_RUBY |
572 | RESTRICTED | | 572 | RESTRICTED |
573 | SITES_.* | | 573 | SITES_.* |
574 | TOOLS_ALIASES\.* | | 574 | TOOLS_ALIASES\.* |
575 | TOOLS_BROKEN | | 575 | TOOLS_BROKEN |
576 | TOOLS_CREATE | | 576 | TOOLS_CREATE |
577 | TOOLS_GNU_MISSING | | 577 | TOOLS_GNU_MISSING |
578 | TOOLS_NOOP | | 578 | TOOLS_NOOP |
579 | ); | | 579 | ); |
580 | my $plurals = join("|", | | 580 | my $plurals = join("|", |
581 | @plurals_ok, | | 581 | @plurals_ok, |
582 | @plurals_missing_an_s, | | 582 | @plurals_missing_an_s, |
583 | @plurals_reluctantly_accepted | | 583 | @plurals_reluctantly_accepted |
584 | ); | | 584 | ); |
585 | | | 585 | |
586 | $get_regex_plurals_value = qr"^(?:${plurals})$"; | | 586 | $get_regex_plurals_value = qr"^(?:${plurals})$"; |
587 | return $get_regex_plurals_value; | | 587 | return $get_regex_plurals_value; |
588 | } | | 588 | } |
589 | | | 589 | |
590 | # | | 590 | # |
591 | # Loading pkglint-specific data from files. | | 591 | # Loading pkglint-specific data from files. |
592 | # | | 592 | # |
593 | | | 593 | |
594 | # The symbol table for ACL definitions maps ACL names to ACLs. | | 594 | # The symbol table for ACL definitions maps ACL names to ACLs. |
595 | my $acl_definitions = {}; | | 595 | my $acl_definitions = {}; |
596 | | | 596 | |
597 | sub parse_acls($$) { | | 597 | sub parse_acls($$) { |
598 | my ($line, $acltext) = @_; | | 598 | my ($line, $acltext) = @_; |
599 | my ($acls); | | 599 | my ($acls); |
600 | | | 600 | |
601 | use constant ACL_shortcuts => { | | 601 | use constant ACL_shortcuts => { |
602 | "b" => qr"(?:^|/)buildlink3\.mk$", | | 602 | "b" => qr"(?:^|/)buildlink3\.mk$", |
603 | "c" => qr"(?:^|/)Makefile\.common$", | | 603 | "c" => qr"(?:^|/)Makefile\.common$", |
604 | "h" => qr"(?:^|/)hacks\.mk$", | | 604 | "h" => qr"(?:^|/)hacks\.mk$", |
605 | "m" => qr"(?:^|/)Makefile$", | | 605 | "m" => qr"(?:^|/)Makefile$", |
606 | "o" => qr"(?:^|/)options\.mk$", | | 606 | "o" => qr"(?:^|/)options\.mk$", |
607 | }; | | 607 | }; |
608 | | | 608 | |
609 | my $regex_acl_entry = qr"^(?: | | 609 | my $regex_acl_entry = qr"^(?: |
610 | \$([\w_]+) # $acl_name | | 610 | \$([\w_]+) # $acl_name |
611 | | ([\w.*]+|_):([adpsu]*) # file*mask:perms | | 611 | | ([\w.*]+|_):([adpsu]*) # file*mask:perms |
612 | ) (?:\,\s*|$)"x; | | 612 | ) (?:\,\s*|$)"x; |
613 | | | 613 | |
614 | if (!defined($acltext)) { | | 614 | if (!defined($acltext)) { |
615 | return undef; | | 615 | return undef; |
616 | } | | 616 | } |
617 | | | 617 | |
618 | $acls = []; | | 618 | $acls = []; |
619 | while ($acltext =~ s,$regex_acl_entry,,) { | | 619 | while ($acltext =~ s,$regex_acl_entry,,) { |
620 | my ($acldef, $subject, $perms) = ($1, $2, $3); | | 620 | my ($acldef, $subject, $perms) = ($1, $2, $3); |
621 | | | 621 | |
622 | if (defined($acldef)) { | | 622 | if (defined($acldef)) { |
623 | if (!exists($acl_definitions->{$acldef})) { | | 623 | if (!exists($acl_definitions->{$acldef})) { |
624 | $line->log_fatal("ACL definition ${acldef} not found."); | | 624 | $line->log_fatal("ACL definition ${acldef} not found."); |
625 | } else { | | 625 | } else { |
626 | push(@{$acls}, @{$acl_definitions->{$acldef}}); | | 626 | push(@{$acls}, @{$acl_definitions->{$acldef}}); |
627 | } | | 627 | } |
628 | | | 628 | |
629 | } else { | | 629 | } else { |
630 | # Transform $subject to a regular expression. | | 630 | # Transform $subject to a regular expression. |
631 | $subject =~ s/\./[.]/g; | | 631 | $subject =~ s/\./[.]/g; |
632 | $subject =~ s/\*/.*/g; | | 632 | $subject =~ s/\*/.*/g; |
633 | | | 633 | |
634 | push(@{$acls}, [exists(ACL_shortcuts->{$subject}) ? ACL_shortcuts->{$subject} : qr"(?:^|/)${subject}$", $perms]); | | 634 | push(@{$acls}, [exists(ACL_shortcuts->{$subject}) ? ACL_shortcuts->{$subject} : qr"(?:^|/)${subject}$", $perms]); |
635 | } | | 635 | } |
636 | } | | 636 | } |
637 | if ($acltext ne "") { | | 637 | if ($acltext ne "") { |
638 | $line->log_fatal("Invalid ACL: ${acltext}."); | | 638 | $line->log_fatal("Invalid ACL: ${acltext}."); |
639 | } | | 639 | } |
640 | | | 640 | |
641 | return $acls; | | 641 | return $acls; |
642 | } | | 642 | } |
643 | | | 643 | |
644 | my $get_vartypes_basictypes_result = undef; | | 644 | my $get_vartypes_basictypes_result = undef; |
645 | sub get_vartypes_basictypes() { | | 645 | sub get_vartypes_basictypes() { |
646 | if (defined($get_vartypes_basictypes_result)) { | | 646 | if (defined($get_vartypes_basictypes_result)) { |
647 | return $get_vartypes_basictypes_result; | | 647 | return $get_vartypes_basictypes_result; |
648 | } | | 648 | } |
649 | | | 649 | |
650 | my $lines = load_file($program); | | 650 | my $lines = load_file($program); |
651 | my $types = {}; | | 651 | my $types = {}; |
652 | assert($lines, "Couldn't load pkglint.pl from $program"); | | 652 | assert($lines, "Couldn't load pkglint.pl from $program"); |
653 | foreach my $line (@$lines) { | | 653 | foreach my $line (@$lines) { |
654 | if ($line->text =~ m"^\s+(\w+) => sub \{$") { | | 654 | if ($line->text =~ m"^\s+(\w+) => sub \{$") { |
655 | # XXX lookup in %type_dispatch instead | | 655 | # XXX lookup in %type_dispatch instead |
656 | $types->{$1} = 1; | | 656 | $types->{$1} = 1; |
657 | } | | 657 | } |
658 | } | | 658 | } |
659 | return ($get_vartypes_basictypes_result = $types); | | 659 | return ($get_vartypes_basictypes_result = $types); |
660 | } | | 660 | } |
661 | | | 661 | |
662 | my $get_vartypes_map_result = undef; | | 662 | my $get_vartypes_map_result = undef; |
663 | sub get_vartypes_map() { | | 663 | sub get_vartypes_map() { |
664 | my ($fname, $vartypes); | | 664 | my ($fname, $vartypes); |
665 | | | 665 | |
666 | if (defined($get_vartypes_map_result)) { | | 666 | if (defined($get_vartypes_map_result)) { |
667 | return $get_vartypes_map_result; | | 667 | return $get_vartypes_map_result; |
668 | } | | 668 | } |
669 | | | 669 | |
670 | use constant re_acl_def => qr"^ | | 670 | use constant re_acl_def => qr"^ |
671 | acl \s+ | | 671 | acl \s+ |
672 | (\w+) \s+ # ACL name | | 672 | (\w+) \s+ # ACL name |
673 | = \s+ | | 673 | = \s+ |
674 | \[ ([^\]]*) \] # ACL value | | 674 | \[ ([^\]]*) \] # ACL value |
675 | (?:\s*\#.*)? # optional comment | | 675 | (?:\s*\#.*)? # optional comment |
676 | $"x; | | 676 | $"x; |
677 | | | 677 | |
678 | use constant re_vartypedef => qr"^ | | 678 | use constant re_vartypedef => qr"^ |
679 | ([\w\d_.]+?) # $1 = variable name | | 679 | ([\w\d_.]+?) # $1 = variable name |
680 | (\*|\.\*|) \s+ # $2 = parameterized? | | 680 | (\*|\.\*|) \s+ # $2 = parameterized? |
681 | (?:(InternalList|List) \s+ of \s+)? # $3 ?= kind of list | | 681 | (?:(InternalList|List) \s+ of \s+)? # $3 ?= kind of list |
682 | (?:([\w\d_]+) # $4 ?= basic type | | 682 | (?:([\w\d_]+) # $4 ?= basic type |
683 | | \{\s*([\w\d_+,\-.\s]+?)\s*\}) # $5 ?= enumeration values | | 683 | | \{\s*([\w\d_+,\-.\s]+?)\s*\}) # $5 ?= enumeration values |
684 | (?:\s+ \[ ([^\]]*) \])? # $6 ?= optional ACL | | 684 | (?:\s+ \[ ([^\]]*) \])? # $6 ?= optional ACL |
685 | (?:\s*\#.*)? # $7 ?= optional comment | | 685 | (?:\s*\#.*)? # $7 ?= optional comment |
686 | $"x; | | 686 | $"x; |
687 | | | 687 | |
688 | $fname = conf_datadir."/makevars.map"; | | 688 | $fname = conf_datadir."/makevars.map"; |
689 | $vartypes = {}; | | 689 | $vartypes = {}; |
690 | | | 690 | |
691 | if ((my $lines = load_lines($fname, true))) { | | 691 | if ((my $lines = load_lines($fname, true))) { |
692 | foreach my $line (@{$lines}) { | | 692 | foreach my $line (@{$lines}) { |
693 | if ($line->text =~ m"^(?:#.*|\s*)$") { | | 693 | if ($line->text =~ m"^(?:#.*|\s*)$") { |
694 | # ignore empty and comment lines | | 694 | # ignore empty and comment lines |
695 | | | 695 | |
696 | } elsif ($line->text =~ re_acl_def) { | | 696 | } elsif ($line->text =~ re_acl_def) { |
697 | my ($aclname, $aclvalue) = ($1, $2); | | 697 | my ($aclname, $aclvalue) = ($1, $2); |
698 | | | 698 | |
699 | $acl_definitions->{$aclname} = parse_acls($line, $aclvalue); | | 699 | $acl_definitions->{$aclname} = parse_acls($line, $aclvalue); |
700 | | | 700 | |
701 | } elsif ($line->text =~ re_vartypedef) { | | 701 | } elsif ($line->text =~ re_vartypedef) { |
702 | my ($varname, $par, $kind_of_list_text, $typename, $enums, $acltext) = ($1, $2, $3, $4, $5, $6); | | 702 | my ($varname, $par, $kind_of_list_text, $typename, $enums, $acltext) = ($1, $2, $3, $4, $5, $6); |
703 | my $kind_of_list = !defined($kind_of_list_text) ? LK_NONE | | 703 | my $kind_of_list = !defined($kind_of_list_text) ? LK_NONE |
704 | : ($kind_of_list_text eq "List") ? LK_EXTERNAL | | 704 | : ($kind_of_list_text eq "List") ? LK_EXTERNAL |
705 | : LK_INTERNAL; | | 705 | : LK_INTERNAL; |
706 | | | 706 | |
707 | if (defined($typename) && !exists(get_vartypes_basictypes()->{$typename})) { | | 707 | if (defined($typename) && !exists(get_vartypes_basictypes()->{$typename})) { |
708 | $line->log_fatal("Unknown basic type \"$typename\" for variable $varname. " | | 708 | $line->log_fatal("Unknown basic type \"$typename\" for variable $varname. " |
709 | . "Valid basic types are " | | 709 | . "Valid basic types are " |
710 | . join(", ", sort keys %{get_vartypes_basictypes()}) | | 710 | . join(", ", sort keys %{get_vartypes_basictypes()}) |
711 | . "."); | | 711 | . "."); |
712 | } | | 712 | } |
713 | | | 713 | |
714 | my $basic_type = defined($enums) | | 714 | my $basic_type = defined($enums) |
715 | ? array_to_hash(split(qr"\s+", $enums)) | | 715 | ? array_to_hash(split(qr"\s+", $enums)) |
716 | : $typename; | | 716 | : $typename; |
717 | my $type = PkgLint::Type->new($kind_of_list, $basic_type, parse_acls($line, $acltext), NOT_GUESSED); | | 717 | my $type = PkgLint::Type->new($kind_of_list, $basic_type, parse_acls($line, $acltext), NOT_GUESSED); |
718 | if ($par eq "" || $par eq "*") { | | 718 | if ($par eq "" || $par eq "*") { |
719 | $vartypes->{$varname} = $type; | | 719 | $vartypes->{$varname} = $type; |
720 | } | | 720 | } |
721 | if ($par eq "*" || $par eq ".*") { | | 721 | if ($par eq "*" || $par eq ".*") { |
722 | $vartypes->{"${varname}.*"} = $type; | | 722 | $vartypes->{"${varname}.*"} = $type; |
723 | } | | 723 | } |
724 | | | 724 | |
725 | } else { | | 725 | } else { |
726 | $line->log_fatal("Unknown line format."); | | 726 | $line->log_fatal("Unknown line format."); |
727 | } | | 727 | } |
728 | } | | 728 | } |
729 | } else { | | 729 | } else { |
730 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 730 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
731 | } | | 731 | } |
732 | | | 732 | |
733 | # TODO: Enable when the time is ripe. | | 733 | # TODO: Enable when the time is ripe. |
734 | if (false) { | | 734 | if (false) { |
735 | # Additionally, scan mk/defaults/mk.conf for variable | | 735 | # Additionally, scan mk/defaults/mk.conf for variable |
736 | # definitions. All these variables are reserved for the user and | | 736 | # definitions. All these variables are reserved for the user and |
737 | # must not be set within packages. | | 737 | # must not be set within packages. |
738 | $fname = "${cwd_pkgsrcdir}/mk/defaults/mk.conf"; | | 738 | $fname = "${cwd_pkgsrcdir}/mk/defaults/mk.conf"; |
739 | if ((my $lines = load_file($fname))) { | | 739 | if ((my $lines = load_file($fname))) { |
740 | foreach my $line (@{$lines}) { | | 740 | foreach my $line (@{$lines}) { |
741 | if ($line->text =~ m"^#?([\w_]+)\?=") { | | 741 | if ($line->text =~ m"^#?([\w_]+)\?=") { |
742 | my ($varname) = ($1); | | 742 | my ($varname) = ($1); |
743 | $opt_debug_misc and $line->log_debug("Found user-definable variable ${varname}."); | | 743 | $opt_debug_misc and $line->log_debug("Found user-definable variable ${varname}."); |
744 | $vartypes->{$varname} = "Userdefined"; # FIXME: type error | | 744 | $vartypes->{$varname} = "Userdefined"; # FIXME: type error |
745 | } | | 745 | } |
746 | } | | 746 | } |
747 | } else { | | 747 | } else { |
748 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 748 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
749 | } | | 749 | } |
750 | } | | 750 | } |
751 | | | 751 | |
752 | return ($get_vartypes_map_result = $vartypes); | | 752 | return ($get_vartypes_map_result = $vartypes); |
753 | } | | 753 | } |
754 | | | 754 | |
755 | my $get_deprecated_map_result = undef; | | 755 | my $get_deprecated_map_result = undef; |
756 | sub get_deprecated_map() { | | 756 | sub get_deprecated_map() { |
757 | my ($fname, $lines, $vars); | | 757 | my ($fname, $lines, $vars); |
758 | | | 758 | |
759 | if (defined($get_deprecated_map_result)) { | | 759 | if (defined($get_deprecated_map_result)) { |
760 | return $get_deprecated_map_result; | | 760 | return $get_deprecated_map_result; |
761 | } | | 761 | } |
762 | | | 762 | |
763 | $fname = conf_datadir."/deprecated.map"; | | 763 | $fname = conf_datadir."/deprecated.map"; |
764 | if (!($lines = load_file($fname))) { | | 764 | if (!($lines = load_file($fname))) { |
765 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 765 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
766 | } | | 766 | } |
767 | | | 767 | |
768 | $vars = {}; | | 768 | $vars = {}; |
769 | foreach my $line (@{$lines}) { | | 769 | foreach my $line (@{$lines}) { |
770 | if ($line->text =~ m"^#" || $line->text =~ m"^\s*$") { | | 770 | if ($line->text =~ m"^#" || $line->text =~ m"^\s*$") { |
771 | # Ignore empty and comment lines. | | 771 | # Ignore empty and comment lines. |
772 | | | 772 | |
773 | } elsif ($line->text =~ m"^(\S+)\s+(.*)$") { | | 773 | } elsif ($line->text =~ m"^(\S+)\s+(.*)$") { |
774 | $vars->{$1} = $2; | | 774 | $vars->{$1} = $2; |
775 | | | 775 | |
776 | } else { | | 776 | } else { |
777 | $line->log_fatal("Unknown line format."); | | 777 | $line->log_fatal("Unknown line format."); |
778 | } | | 778 | } |
779 | } | | 779 | } |
780 | return ($get_deprecated_map_result = $vars); | | 780 | return ($get_deprecated_map_result = $vars); |
781 | } | | 781 | } |
782 | | | 782 | |
783 | my $load_dist_sites_url2name = undef; | | 783 | my $load_dist_sites_url2name = undef; |
784 | my $load_dist_sites_names = undef; | | 784 | my $load_dist_sites_names = undef; |
785 | sub load_dist_sites() { | | 785 | sub load_dist_sites() { |
786 | my ($fname) = ("${cwd_pkgsrcdir}/mk/fetch/sites.mk"); | | 786 | my ($fname) = ("${cwd_pkgsrcdir}/mk/fetch/sites.mk"); |
787 | my ($lines) = load_file($fname); | | 787 | my ($lines) = load_file($fname); |
788 | my ($varname) = undef; | | 788 | my ($varname) = undef; |
789 | my ($ignoring) = false; | | 789 | my ($ignoring) = false; |
790 | my ($url2name) = {}; | | 790 | my ($url2name) = {}; |
791 | my ($names) = {}; | | 791 | my ($names) = {}; |
792 | | | 792 | |
793 | if (!$lines) { | | 793 | if (!$lines) { |
794 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 794 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
795 | $load_dist_sites_url2name = $url2name; | | 795 | $load_dist_sites_url2name = $url2name; |
796 | $load_dist_sites_names = $names; | | 796 | $load_dist_sites_names = $names; |
797 | return; | | 797 | return; |
798 | } | | 798 | } |
799 | foreach my $line (@{$lines}) { | | 799 | foreach my $line (@{$lines}) { |
800 | my $text = $line->text; | | 800 | my $text = $line->text; |
801 | | | 801 | |
802 | if ($text =~ m"^(MASTER_SITE_\w+)\+=\s*\\$"o) { | | 802 | if ($text =~ m"^(MASTER_SITE_\w+)\+=\s*\\$"o) { |
803 | $varname = $1; | | 803 | $varname = $1; |
804 | $names->{$varname} = true; | | 804 | $names->{$varname} = true; |
805 | $ignoring = false; | | 805 | $ignoring = false; |
806 | | | 806 | |
807 | } elsif ($text eq "MASTER_SITE_BACKUP?=\t\\") { | | 807 | } elsif ($text eq "MASTER_SITE_BACKUP?=\t\\") { |
808 | $ignoring = true; | | 808 | $ignoring = true; |
809 | | | 809 | |
810 | } elsif ($text =~ m"^\t((?:http://|ftp://)\S+/)(?:|\s*\\)$"o) { | | 810 | } elsif ($text =~ m"^\t((?:http://|ftp://)\S+/)(?:|\s*\\)$"o) { |
811 | if (!$ignoring) { | | 811 | if (!$ignoring) { |
812 | if (defined($varname)) { | | 812 | if (defined($varname)) { |
813 | $url2name->{$1} = $varname; | | 813 | $url2name->{$1} = $varname; |
814 | } else { | | 814 | } else { |
815 | $line->log_error("Lonely URL found."); | | 815 | $line->log_error("Lonely URL found."); |
816 | } | | 816 | } |
817 | } | | 817 | } |
818 | | | 818 | |
819 | } elsif ($text =~ m"^(?:#.*|\s*)$") { | | 819 | } elsif ($text =~ m"^(?:#.*|\s*)$") { |
820 | # ignore empty and comment lines | | 820 | # ignore empty and comment lines |
821 | | | 821 | |
822 | } elsif ($text =~ m"BSD_SITES_MK") { | | 822 | } elsif ($text =~ m"BSD_SITES_MK") { |
823 | # ignore multiple inclusion guards | | 823 | # ignore multiple inclusion guards |
824 | | | 824 | |
825 | } else { | | 825 | } else { |
826 | $line->log_fatal("Unknown line type."); | | 826 | $line->log_fatal("Unknown line type."); |
827 | } | | 827 | } |
828 | } | | 828 | } |
829 | | | 829 | |
830 | # Explicitly allowed, although not defined in mk/fetch/sites.mk. | | 830 | # Explicitly allowed, although not defined in mk/fetch/sites.mk. |
831 | $names->{"MASTER_SITE_SUSE_UPD"} = true; | | 831 | $names->{"MASTER_SITE_SUSE_UPD"} = true; |
832 | $names->{"MASTER_SITE_LOCAL"} = true; | | 832 | $names->{"MASTER_SITE_LOCAL"} = true; |
833 | | | 833 | |
834 | $opt_debug_misc and log_debug($fname, NO_LINES, "Loaded " . scalar(keys(%{$url2name})) . " MASTER_SITE_* definitions."); | | 834 | $opt_debug_misc and log_debug($fname, NO_LINES, "Loaded " . scalar(keys(%{$url2name})) . " MASTER_SITE_* definitions."); |
835 | $load_dist_sites_url2name = $url2name; | | 835 | $load_dist_sites_url2name = $url2name; |
836 | $load_dist_sites_names = $names; | | 836 | $load_dist_sites_names = $names; |
837 | } | | 837 | } |
838 | | | 838 | |
839 | sub get_dist_sites() { | | 839 | sub get_dist_sites() { |
840 | if (!defined($load_dist_sites_url2name)) { | | 840 | if (!defined($load_dist_sites_url2name)) { |
841 | load_dist_sites(); | | 841 | load_dist_sites(); |
842 | } | | 842 | } |
843 | return $load_dist_sites_url2name; | | 843 | return $load_dist_sites_url2name; |
844 | } | | 844 | } |
845 | | | 845 | |
846 | sub get_dist_sites_names() { | | 846 | sub get_dist_sites_names() { |
847 | if (!defined($load_dist_sites_names)) { | | 847 | if (!defined($load_dist_sites_names)) { |
848 | load_dist_sites(); | | 848 | load_dist_sites(); |
849 | } | | 849 | } |
850 | return $load_dist_sites_names; | | 850 | return $load_dist_sites_names; |
851 | } | | 851 | } |
852 | | | 852 | |
853 | my $get_pkg_options_result = undef; | | 853 | my $get_pkg_options_result = undef; |
854 | sub get_pkg_options() { | | 854 | sub get_pkg_options() { |
855 | | | 855 | |
856 | if (defined($get_pkg_options_result)) { | | 856 | if (defined($get_pkg_options_result)) { |
857 | return $get_pkg_options_result; | | 857 | return $get_pkg_options_result; |
858 | } | | 858 | } |
859 | | | 859 | |
860 | my ($fname) = ("${cwd_pkgsrcdir}/mk/defaults/options.description"); | | 860 | my ($fname) = ("${cwd_pkgsrcdir}/mk/defaults/options.description"); |
861 | my ($lines, $options); | | 861 | my ($lines, $options); |
862 | | | 862 | |
863 | if (!($lines = load_file($fname))) { | | 863 | if (!($lines = load_file($fname))) { |
864 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 864 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
865 | } | | 865 | } |
866 | | | 866 | |
867 | $options = {}; | | 867 | $options = {}; |
868 | foreach my $line (@{$lines}) { | | 868 | foreach my $line (@{$lines}) { |
869 | if ($line->text =~ m"^([-0-9a-z_+]+)(?:\s+(.*))?$") { | | 869 | if ($line->text =~ m"^([-0-9a-z_+]+)(?:\s+(.*))?$") { |
870 | my ($optname, $optdescr) = ($1, $2); | | 870 | my ($optname, $optdescr) = ($1, $2); |
871 | | | 871 | |
872 | $options->{$optname} = defined($optdescr) | | 872 | $options->{$optname} = defined($optdescr) |
873 | ? $optdescr | | 873 | ? $optdescr |
874 | : ""; | | 874 | : ""; |
875 | } else { | | 875 | } else { |
876 | $line->log_error("Unknown line format."); | | 876 | $line->log_error("Unknown line format."); |
877 | } | | 877 | } |
878 | } | | 878 | } |
879 | | | 879 | |
880 | return ($get_pkg_options_result = $options); | | 880 | return ($get_pkg_options_result = $options); |
881 | } | | 881 | } |
882 | | | 882 | |
883 | my $load_tool_names_system_build_defs = undef; # XXX: misplaced, but works | | 883 | my $load_tool_names_system_build_defs = undef; # XXX: misplaced, but works |
884 | my $load_tool_names_tools = undef; | | 884 | my $load_tool_names_tools = undef; |
885 | my $load_tool_names_vartools = undef; | | 885 | my $load_tool_names_vartools = undef; |
886 | my $load_tool_names_varname_to_toolname = undef; | | 886 | my $load_tool_names_varname_to_toolname = undef; |
887 | my $load_tool_names_predefined_tools = undef; | | 887 | my $load_tool_names_predefined_tools = undef; |
888 | sub load_tool_names() { | | 888 | sub load_tool_names() { |
889 | my ($tools, $vartools, $predefined_tools, $varname_to_toolname, @tool_files); | | 889 | my ($tools, $vartools, $predefined_tools, $varname_to_toolname, @tool_files); |
890 | my ($system_build_defs); | | 890 | my ($system_build_defs); |
891 | | | 891 | |
892 | # | | 892 | # |
893 | # Get the list of files that define the tools from bsd.tools.mk. | | 893 | # Get the list of files that define the tools from bsd.tools.mk. |
894 | # | | 894 | # |
895 | | | 895 | |
896 | @tool_files = ("defaults.mk"); | | 896 | @tool_files = ("defaults.mk"); |
897 | { | | 897 | { |
898 | my $fname = "${cwd_pkgsrcdir}/mk/tools/bsd.tools.mk"; | | 898 | my $fname = "${cwd_pkgsrcdir}/mk/tools/bsd.tools.mk"; |
899 | my $lines = load_lines($fname, true); | | 899 | my $lines = load_lines($fname, true); |
900 | if (!$lines) { | | 900 | if (!$lines) { |
901 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 901 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
902 | } | | 902 | } |
903 | | | 903 | |
904 | foreach my $line (@{$lines}) { | | 904 | foreach my $line (@{$lines}) { |
905 | if ($line->text =~ regex_mk_include) { | | 905 | if ($line->text =~ regex_mk_include) { |
906 | my (undef, $includefile) = ($1, $2); | | 906 | my (undef, $includefile) = ($1, $2); |
907 | if ($includefile =~ m"^(?:\$\{PKGSRCDIR\}/mk/tools/)?([^/]+)$") { | | 907 | if ($includefile =~ m"^(?:\$\{PKGSRCDIR\}/mk/tools/)?([^/]+)$") { |
908 | push(@tool_files, $1); | | 908 | push(@tool_files, $1); |
909 | } | | 909 | } |
910 | } | | 910 | } |
911 | } | | 911 | } |
912 | } | | 912 | } |
913 | assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?"); | | 913 | assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?"); |
914 | | | 914 | |
915 | # | | 915 | # |
916 | # Scan the tool files for the actual definitions of the tools. | | 916 | # Scan the tool files for the actual definitions of the tools. |
917 | # | | 917 | # |
918 | | | 918 | |
919 | $tools = {}; | | 919 | $tools = {}; |
920 | $vartools = {}; | | 920 | $vartools = {}; |
921 | $predefined_tools = {}; | | 921 | $predefined_tools = {}; |
922 | $varname_to_toolname = {}; | | 922 | $varname_to_toolname = {}; |
923 | $system_build_defs = {}; | | 923 | $system_build_defs = {}; |
924 | foreach my $basename (@tool_files) { | | 924 | foreach my $basename (@tool_files) { |
925 | my $fname = "${cwd_pkgsrcdir}/mk/tools/${basename}"; | | 925 | my $fname = "${cwd_pkgsrcdir}/mk/tools/${basename}"; |
926 | my $lines = load_lines($fname, true); | | 926 | my $lines = load_lines($fname, true); |
927 | | | 927 | |
928 | if (!$lines) { | | 928 | if (!$lines) { |
929 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 929 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
930 | } | | 930 | } |
931 | | | 931 | |
932 | foreach my $line (@{$lines}) { | | 932 | foreach my $line (@{$lines}) { |
933 | if ($line->text =~ regex_varassign) { | | 933 | if ($line->text =~ regex_varassign) { |
934 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); | | 934 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); |
935 | if ($varname eq "TOOLS_CREATE" && $value =~ m"^([-\w.]+|\[)$") { | | 935 | if ($varname eq "TOOLS_CREATE" && $value =~ m"^([-\w.]+|\[)$") { |
936 | $tools->{$value} = true; | | 936 | $tools->{$value} = true; |
937 | | | 937 | |
938 | } elsif ($varname =~ m"^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$") { | | 938 | } elsif ($varname =~ m"^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$") { |
939 | $tools->{$1} = true; | | 939 | $tools->{$1} = true; |
940 | $vartools->{$1} = $value; | | 940 | $vartools->{$1} = $value; |
941 | $varname_to_toolname->{$value} = $1; | | 941 | $varname_to_toolname->{$value} = $1; |
942 | | | 942 | |
943 | } elsif ($varname =~ m"^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$") { | | 943 | } elsif ($varname =~ m"^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$") { |
944 | $tools->{$1} = true; | | 944 | $tools->{$1} = true; |
945 | | | 945 | |
946 | } elsif ($varname =~ m"^_TOOLS\.(.*)") { | | 946 | } elsif ($varname =~ m"^_TOOLS\.(.*)") { |
947 | $tools->{$1} = true; | | 947 | $tools->{$1} = true; |
948 | foreach my $tool (split(qr"\s+", $value)) { | | 948 | foreach my $tool (split(qr"\s+", $value)) { |
949 | $tools->{$tool} = true; | | 949 | $tools->{$tool} = true; |
950 | } | | 950 | } |
951 | } | | 951 | } |
952 | } | | 952 | } |
953 | } | | 953 | } |
954 | } | | 954 | } |
955 | | | 955 | |
956 | foreach my $basename ("bsd.pkg.mk") { | | 956 | foreach my $basename ("bsd.pkg.mk") { |
957 | my $fname = "${cwd_pkgsrcdir}/mk/${basename}"; | | 957 | my $fname = "${cwd_pkgsrcdir}/mk/${basename}"; |
958 | my $lines = load_lines($fname, true); | | 958 | my $lines = load_lines($fname, true); |
959 | my $cond_depth = 0; | | 959 | my $cond_depth = 0; |
960 | | | 960 | |
961 | if (!$lines) { | | 961 | if (!$lines) { |
962 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 962 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
963 | } | | 963 | } |
964 | | | 964 | |
965 | foreach my $line (@{$lines}) { | | 965 | foreach my $line (@{$lines}) { |
966 | my $text = $line->text; | | 966 | my $text = $line->text; |
967 | | | 967 | |
968 | if ($text =~ regex_varassign) { | | 968 | if ($text =~ regex_varassign) { |
969 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); | | 969 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); |
970 | | | 970 | |
971 | if ($varname eq "USE_TOOLS") { | | 971 | if ($varname eq "USE_TOOLS") { |
972 | $opt_debug_tools and $line->log_debug("[cond_depth=${cond_depth}] $value"); | | 972 | $opt_debug_tools and $line->log_debug("[cond_depth=${cond_depth}] $value"); |
973 | if ($cond_depth == 0) { | | 973 | if ($cond_depth == 0) { |
974 | foreach my $tool (split(qr"\s+", $value)) { | | 974 | foreach my $tool (split(qr"\s+", $value)) { |
975 | if ($tool !~ regex_unresolved && exists($tools->{$tool})) { | | 975 | if ($tool !~ regex_unresolved && exists($tools->{$tool})) { |
976 | $predefined_tools->{$tool} = true; | | 976 | $predefined_tools->{$tool} = true; |
977 | # The path (without arguments) to the tool | | 977 | # The path (without arguments) to the tool |
978 | $predefined_tools->{"TOOLS_${tool}"} = true; | | 978 | $predefined_tools->{"TOOLS_${tool}"} = true; |
979 | } | | 979 | } |
980 | } | | 980 | } |
981 | } | | 981 | } |
982 | } elsif ($varname eq "_BUILD_DEFS") { | | 982 | } elsif ($varname eq "_BUILD_DEFS") { |
983 | foreach my $bdvar (split(qr"\s+", $value)) { | | 983 | foreach my $bdvar (split(qr"\s+", $value)) { |
984 | $system_build_defs->{$bdvar} = true; | | 984 | $system_build_defs->{$bdvar} = true; |
985 | } | | 985 | } |
986 | } | | 986 | } |
987 | | | 987 | |
988 | } elsif ($text =~ regex_mk_cond) { | | 988 | } elsif ($text =~ regex_mk_cond) { |
989 | my ($indent, $cond, $args, $comment) = ($1, $2, $3, $4); | | 989 | my ($indent, $cond, $args, $comment) = ($1, $2, $3, $4); |
990 | | | 990 | |
991 | if ($cond =~ m"^(?:if|ifdef|ifndef|for)$") { | | 991 | if ($cond =~ m"^(?:if|ifdef|ifndef|for)$") { |
992 | $cond_depth++; | | 992 | $cond_depth++; |
993 | } elsif ($cond =~ m"^(?:endif|endfor)$") { | | 993 | } elsif ($cond =~ m"^(?:endif|endfor)$") { |
994 | $cond_depth--; | | 994 | $cond_depth--; |
995 | } | | 995 | } |
996 | } | | 996 | } |
997 | } | | 997 | } |
998 | } | | 998 | } |
999 | | | 999 | |
1000 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known tools: ".join(" ", sort(keys(%{$tools})))); | | 1000 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known tools: ".join(" ", sort(keys(%{$tools})))); |
1001 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known vartools: ".join(" ", sort(keys(%{$vartools})))); | | 1001 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known vartools: ".join(" ", sort(keys(%{$vartools})))); |
| @@ -6066,1520 +6066,1524 @@ sub checkfile_extra($) { | | | @@ -6066,1520 +6066,1524 @@ sub checkfile_extra($) { |
6066 | checklines_trailing_empty_lines($lines); | | 6066 | checklines_trailing_empty_lines($lines); |
6067 | checkperms($fname); | | 6067 | checkperms($fname); |
6068 | } | | 6068 | } |
6069 | | | 6069 | |
6070 | sub checkfile_INSTALL($) { | | 6070 | sub checkfile_INSTALL($) { |
6071 | my ($fname) = @_; | | 6071 | my ($fname) = @_; |
6072 | my ($lines); | | 6072 | my ($lines); |
6073 | | | 6073 | |
6074 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); | | 6074 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); |
6075 | | | 6075 | |
6076 | checkperms($fname); | | 6076 | checkperms($fname); |
6077 | if (!($lines = load_file($fname))) { | | 6077 | if (!($lines = load_file($fname))) { |
6078 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6078 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6079 | return; | | 6079 | return; |
6080 | } | | 6080 | } |
6081 | } | | 6081 | } |
6082 | | | 6082 | |
6083 | sub checkfile_MESSAGE($) { | | 6083 | sub checkfile_MESSAGE($) { |
6084 | my ($fname) = @_; | | 6084 | my ($fname) = @_; |
6085 | my ($lines); | | 6085 | my ($lines); |
6086 | | | 6086 | |
6087 | my @explanation = ( | | 6087 | my @explanation = ( |
6088 | "A MESSAGE file should consist of a header line, having 75 \"=\"", | | 6088 | "A MESSAGE file should consist of a header line, having 75 \"=\"", |
6089 | "characters, followed by a line containing only the RCS Id, then an", | | 6089 | "characters, followed by a line containing only the RCS Id, then an", |
6090 | "empty line, your text and finally the footer line, which is the", | | 6090 | "empty line, your text and finally the footer line, which is the", |
6091 | "same as the header line."); | | 6091 | "same as the header line."); |
6092 | | | 6092 | |
6093 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); | | 6093 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); |
6094 | | | 6094 | |
6095 | checkperms($fname); | | 6095 | checkperms($fname); |
6096 | if (!($lines = load_file($fname))) { | | 6096 | if (!($lines = load_file($fname))) { |
6097 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6097 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6098 | return; | | 6098 | return; |
6099 | } | | 6099 | } |
6100 | | | 6100 | |
6101 | if (@{$lines} < 3) { | | 6101 | if (@{$lines} < 3) { |
6102 | log_warning($fname, NO_LINE_NUMBER, "File too short."); | | 6102 | log_warning($fname, NO_LINE_NUMBER, "File too short."); |
6103 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6103 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6104 | return; | | 6104 | return; |
6105 | } | | 6105 | } |
6106 | if ($lines->[0]->text ne "=" x 75) { | | 6106 | if ($lines->[0]->text ne "=" x 75) { |
6107 | $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); | | 6107 | $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); |
6108 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6108 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6109 | } | | 6109 | } |
6110 | checkline_rcsid($lines->[1], ""); | | 6110 | checkline_rcsid($lines->[1], ""); |
6111 | foreach my $line (@{$lines}) { | | 6111 | foreach my $line (@{$lines}) { |
6112 | checkline_length($line, 80); | | 6112 | checkline_length($line, 80); |
6113 | checkline_trailing_whitespace($line); | | 6113 | checkline_trailing_whitespace($line); |
6114 | checkline_valid_characters($line, regex_validchars); | | 6114 | checkline_valid_characters($line, regex_validchars); |
6115 | checkline_spellcheck($line); | | 6115 | checkline_spellcheck($line); |
6116 | } | | 6116 | } |
6117 | if ($lines->[-1]->text ne "=" x 75) { | | 6117 | if ($lines->[-1]->text ne "=" x 75) { |
6118 | $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); | | 6118 | $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); |
6119 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6119 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6120 | } | | 6120 | } |
6121 | checklines_trailing_empty_lines($lines); | | 6121 | checklines_trailing_empty_lines($lines); |
6122 | } | | 6122 | } |
6123 | | | 6123 | |
6124 | sub checkfile_mk($) { | | 6124 | sub checkfile_mk($) { |
6125 | my ($fname) = @_; | | 6125 | my ($fname) = @_; |
6126 | my ($lines); | | 6126 | my ($lines); |
6127 | | | 6127 | |
6128 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); | | 6128 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); |
6129 | | | 6129 | |
6130 | checkperms($fname); | | 6130 | checkperms($fname); |
6131 | if (!($lines = load_lines($fname, true))) { | | 6131 | if (!($lines = load_lines($fname, true))) { |
6132 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6132 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6133 | return; | | 6133 | return; |
6134 | } | | 6134 | } |
6135 | | | 6135 | |
6136 | parselines_mk($lines); | | 6136 | parselines_mk($lines); |
6137 | checklines_mk($lines); | | 6137 | checklines_mk($lines); |
6138 | autofix($lines); | | 6138 | autofix($lines); |
6139 | } | | 6139 | } |
6140 | | | 6140 | |
6141 | sub checkfile_package_Makefile($$) { | | 6141 | sub checkfile_package_Makefile($$) { |
6142 | my ($fname, $lines) = @_; | | 6142 | my ($fname, $lines) = @_; |
6143 | | | 6143 | |
6144 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); | | 6144 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); |
6145 | | | 6145 | |
6146 | checkperms($fname); | | 6146 | checkperms($fname); |
6147 | | | 6147 | |
6148 | if (!exists($pkgctx_vardef->{"PLIST_SRC"}) | | 6148 | if (!exists($pkgctx_vardef->{"PLIST_SRC"}) |
6149 | && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) | | 6149 | && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) |
6150 | && !exists($pkgctx_vardef->{"META_PACKAGE"}) | | 6150 | && !exists($pkgctx_vardef->{"META_PACKAGE"}) |
6151 | && defined($pkgdir) | | 6151 | && defined($pkgdir) |
6152 | && !-f "${current_dir}/$pkgdir/PLIST" | | 6152 | && !-f "${current_dir}/$pkgdir/PLIST" |
6153 | && !-f "${current_dir}/$pkgdir/PLIST.common") { | | 6153 | && !-f "${current_dir}/$pkgdir/PLIST.common") { |
6154 | log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); | | 6154 | log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); |
6155 | } | | 6155 | } |
6156 | | | 6156 | |
6157 | if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { | | 6157 | if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { |
6158 | if (-f "${current_dir}/${distinfo_file}") { | | 6158 | if (-f "${current_dir}/${distinfo_file}") { |
6159 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); | | 6159 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); |
6160 | } | | 6160 | } |
6161 | } else { | | 6161 | } else { |
6162 | if (!-f "${current_dir}/${distinfo_file}") { | | 6162 | if (!-f "${current_dir}/${distinfo_file}") { |
6163 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); | | 6163 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); |
6164 | } | | 6164 | } |
6165 | } | | 6165 | } |
6166 | | | 6166 | |
6167 | if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { | | 6167 | if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { |
6168 | $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); | | 6168 | $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); |
6169 | $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); | | 6169 | $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); |
6170 | } | | 6170 | } |
6171 | | | 6171 | |
6172 | if (!exists($pkgctx_vardef->{"LICENSE"})) { | | 6172 | if (!exists($pkgctx_vardef->{"LICENSE"})) { |
6173 | log_error($fname, NO_LINE_NUMBER, "Each package must define its LICENSE."); | | 6173 | log_error($fname, NO_LINE_NUMBER, "Each package must define its LICENSE."); |
6174 | } | | 6174 | } |
6175 | | | 6175 | |
6176 | if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { | | 6176 | if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { |
6177 | my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; | | 6177 | my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; |
6178 | my $value = $languages_line->get("value"); | | 6178 | my $value = $languages_line->get("value"); |
6179 | | | 6179 | |
6180 | if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { | | 6180 | if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { |
6181 | # Don't emit a warning, since the comment | | 6181 | # Don't emit a warning, since the comment |
6182 | # probably contains a statement that C is | | 6182 | # probably contains a statement that C is |
6183 | # really not needed. | | 6183 | # really not needed. |
6184 | | | 6184 | |
6185 | } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { | | 6185 | } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { |
6186 | $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); | | 6186 | $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); |
6187 | $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); | | 6187 | $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); |
6188 | } | | 6188 | } |
6189 | } | | 6189 | } |
6190 | | | 6190 | |
6191 | my $distname_line = $pkgctx_vardef->{"DISTNAME"}; | | 6191 | my $distname_line = $pkgctx_vardef->{"DISTNAME"}; |
6192 | my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; | | 6192 | my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; |
6193 | | | 6193 | |
6194 | my $distname = defined($distname_line) ? $distname_line->get("value") : undef; | | 6194 | my $distname = defined($distname_line) ? $distname_line->get("value") : undef; |
6195 | my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; | | 6195 | my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; |
6196 | my $nbpart = get_nbpart(); | | 6196 | my $nbpart = get_nbpart(); |
6197 | | | 6197 | |
6198 | # Let's do some tricks to get the proper value of the package | | 6198 | # Let's do some tricks to get the proper value of the package |
6199 | # name more often. | | 6199 | # name more often. |
6200 | if (defined($distname) && defined($pkgname)) { | | 6200 | if (defined($distname) && defined($pkgname)) { |
6201 | $pkgname =~ s/\$\{DISTNAME\}/$distname/; | | 6201 | $pkgname =~ s/\$\{DISTNAME\}/$distname/; |
6202 | | | 6202 | |
6203 | if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { | | 6203 | if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { |
6204 | my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); | | 6204 | my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); |
6205 | my $newname = $distname; | | 6205 | my $newname = $distname; |
6206 | $old = quotemeta($old); | | 6206 | $old = quotemeta($old); |
6207 | $old =~ s/^\\\^/^/; | | 6207 | $old =~ s/^\\\^/^/; |
6208 | $old =~ s/\\\$$/\$/; | | 6208 | $old =~ s/\\\$$/\$/; |
6209 | if ($mod eq "g") { | | 6209 | if ($mod eq "g") { |
6210 | $newname =~ s/$old/$new/g; | | 6210 | $newname =~ s/$old/$new/g; |
6211 | } else { | | 6211 | } else { |
6212 | $newname =~ s/$old/$new/; | | 6212 | $newname =~ s/$old/$new/; |
6213 | } | | 6213 | } |
6214 | $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); | | 6214 | $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); |
6215 | $pkgname = $before . $newname . $after; | | 6215 | $pkgname = $before . $newname . $after; |
6216 | $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); | | 6216 | $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); |
6217 | } | | 6217 | } |
6218 | } | | 6218 | } |
6219 | | | 6219 | |
6220 | if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { | | 6220 | if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { |
6221 | $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); | | 6221 | $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); |
6222 | } | | 6222 | } |
6223 | | | 6223 | |
6224 | if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { | | 6224 | if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { |
6225 | $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); | | 6225 | $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); |
6226 | } | | 6226 | } |
6227 | | | 6227 | |
6228 | ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) | | 6228 | ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) |
6229 | = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) | | 6229 | = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) |
6230 | : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) | | 6230 | : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) |
6231 | : (undef, undef, undef, undef); | | 6231 | : (undef, undef, undef, undef); |
6232 | if (defined($effective_pkgname_line)) { | | 6232 | if (defined($effective_pkgname_line)) { |
6233 | $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); | | 6233 | $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); |
6234 | # XXX: too many false positives | | 6234 | # XXX: too many false positives |
6235 | if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { | | 6235 | if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { |
6236 | $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); | | 6236 | $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); |
6237 | } | | 6237 | } |
6238 | } | | 6238 | } |
6239 | | | 6239 | |
6240 | checkpackage_possible_downgrade(); | | 6240 | checkpackage_possible_downgrade(); |
6241 | | | 6241 | |
6242 | if (!exists($pkgctx_vardef->{"COMMENT"})) { | | 6242 | if (!exists($pkgctx_vardef->{"COMMENT"})) { |
6243 | log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); | | 6243 | log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); |
6244 | } | | 6244 | } |
6245 | | | 6245 | |
6246 | if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { | | 6246 | if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { |
6247 | $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); | | 6247 | $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); |
6248 | $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); | | 6248 | $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); |
6249 | } | | 6249 | } |
6250 | | | 6250 | |
6251 | if (defined($effective_pkgbase)) { | | 6251 | if (defined($effective_pkgbase)) { |
6252 | | | 6252 | |
6253 | foreach my $suggested_update (@{get_suggested_package_updates()}) { | | 6253 | foreach my $suggested_update (@{get_suggested_package_updates()}) { |
6254 | my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; | | 6254 | my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; |
6255 | my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); | | 6255 | my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); |
6256 | | | 6256 | |
6257 | next unless $effective_pkgbase eq $suggbase; | | 6257 | next unless $effective_pkgbase eq $suggbase; |
6258 | | | 6258 | |
6259 | if (dewey_cmp($effective_pkgversion, "<", $suggver)) { | | 6259 | if (dewey_cmp($effective_pkgversion, "<", $suggver)) { |
6260 | $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); | | 6260 | $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); |
6261 | $effective_pkgname_line->explain_warning( | | 6261 | $effective_pkgname_line->explain_warning( |
6262 | "The wishlist for package updates in doc/TODO mentions that a newer", | | 6262 | "The wishlist for package updates in doc/TODO mentions that a newer", |
6263 | "version of this package is available."); | | 6263 | "version of this package is available."); |
6264 | } | | 6264 | } |
6265 | if (dewey_cmp($effective_pkgversion, "==", $suggver)) { | | 6265 | if (dewey_cmp($effective_pkgversion, "==", $suggver)) { |
6266 | $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); | | 6266 | $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); |
6267 | } | | 6267 | } |
6268 | if (dewey_cmp($effective_pkgversion, ">", $suggver)) { | | 6268 | if (dewey_cmp($effective_pkgversion, ">", $suggver)) { |
6269 | $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); | | 6269 | $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); |
6270 | } | | 6270 | } |
6271 | } | | 6271 | } |
6272 | } | | 6272 | } |
6273 | | | 6273 | |
6274 | checklines_mk($lines); | | 6274 | checklines_mk($lines); |
6275 | checklines_package_Makefile_varorder($lines); | | 6275 | checklines_package_Makefile_varorder($lines); |
6276 | autofix($lines); | | 6276 | autofix($lines); |
6277 | } | | 6277 | } |
6278 | | | 6278 | |
6279 | sub checkfile_patch($) { | | 6279 | sub checkfile_patch($) { |
6280 | my ($fname) = @_; | | 6280 | my ($fname) = @_; |
6281 | my ($lines); | | 6281 | my ($lines); |
6282 | my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); | | 6282 | my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); |
6283 | my ($seen_comment, $current_fname, $current_ftype, $patched_files); | | 6283 | my ($seen_comment, $current_fname, $current_ftype, $patched_files); |
6284 | my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); | | 6284 | my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); |
6285 | | | 6285 | |
6286 | # Abbreviations used: | | 6286 | # Abbreviations used: |
6287 | # style: [c] = context diff, [u] = unified diff | | 6287 | # style: [c] = context diff, [u] = unified diff |
6288 | # scope: [f] = file, [h] = hunk, [l] = line | | 6288 | # scope: [f] = file, [h] = hunk, [l] = line |
6289 | # action: [d] = delete, [m] = modify, [a] = add, [c] = context | | 6289 | # action: [d] = delete, [m] = modify, [a] = add, [c] = context |
6290 | use constant re_patch_rcsid => qr"^\$.*\$$"; | | 6290 | use constant re_patch_rcsid => qr"^\$.*\$$"; |
6291 | use constant re_patch_text => qr"^(.+)$"; | | 6291 | use constant re_patch_text => qr"^(.+)$"; |
6292 | use constant re_patch_empty => qr"^$"; | | 6292 | use constant re_patch_empty => qr"^$"; |
6293 | use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; | | 6293 | use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; |
6294 | use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; | | 6294 | use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; |
6295 | use constant re_patch_ch => qr"^\*{15}(.*)$"; | | 6295 | use constant re_patch_ch => qr"^\*{15}(.*)$"; |
6296 | use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; | | 6296 | use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; |
6297 | use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; | | 6297 | use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; |
6298 | use constant re_patch_cld => qr"^(?:-\s(.*))?$"; | | 6298 | use constant re_patch_cld => qr"^(?:-\s(.*))?$"; |
6299 | use constant re_patch_clm => qr"^(?:!\s(.*))?$"; | | 6299 | use constant re_patch_clm => qr"^(?:!\s(.*))?$"; |
6300 | use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; | | 6300 | use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; |
6301 | use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; | | 6301 | use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; |
6302 | use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; | | 6302 | use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; |
6303 | use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; | | 6303 | use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; |
6304 | use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; | | 6304 | use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; |
6305 | use constant re_patch_uld => qr"^-(.*)$"; | | 6305 | use constant re_patch_uld => qr"^-(.*)$"; |
6306 | use constant re_patch_ula => qr"^\+(.*)$"; | | 6306 | use constant re_patch_ula => qr"^\+(.*)$"; |
6307 | use constant re_patch_ulc => qr"^\s(.*)$"; | | 6307 | use constant re_patch_ulc => qr"^\s(.*)$"; |
6308 | use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; | | 6308 | use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; |
6309 | | | 6309 | |
6310 | use enum qw(:PST_ | | 6310 | use enum qw(:PST_ |
6311 | START CENTER TEXT | | 6311 | START CENTER TEXT |
6312 | CFA CH CHD CLD0 CLD CLA0 CLA | | 6312 | CFA CH CHD CLD0 CLD CLA0 CLA |
6313 | UFA UH UL | | 6313 | UFA UH UL |
6314 | ); | | 6314 | ); |
6315 | | | 6315 | |
6316 | my @comment_explanation = ( | | 6316 | my @comment_explanation = ( |
6317 | "Each patch must document why it is necessary. If it has been applied", | | 6317 | "Each patch must document why it is necessary. If it has been applied", |
6318 | "because of a security issue, a reference to the CVE should be mentioned", | | 6318 | "because of a security issue, a reference to the CVE should be mentioned", |
6319 | "as well.", | | 6319 | "as well.", |
6320 | "", | | 6320 | "", |
6321 | "Since it is our goal to have as few patches as possible, all patches", | | 6321 | "Since it is our goal to have as few patches as possible, all patches", |
6322 | "should be sent to the upstream maintainers of the package. After you", | | 6322 | "should be sent to the upstream maintainers of the package. After you", |
6323 | "have done so, you should add a reference to the bug report containing", | | 6323 | "have done so, you should add a reference to the bug report containing", |
6324 | "the patch."); | | 6324 | "the patch."); |
6325 | | | 6325 | |
6326 | my ($line, $m); | | 6326 | my ($line, $m); |
6327 | | | 6327 | |
6328 | my $check_text = sub($) { | | 6328 | my $check_text = sub($) { |
6329 | my ($text) = @_; | | 6329 | my ($text) = @_; |
6330 | | | 6330 | |
6331 | if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { | | 6331 | if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { |
6332 | my ($tag) = ($2); | | 6332 | my ($tag) = ($2); |
6333 | | | 6333 | |
6334 | if ($text =~ re_patch_uh) { | | 6334 | if ($text =~ re_patch_uh) { |
6335 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); | | 6335 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); |
6336 | $line->set_text($1); | | 6336 | $line->set_text($1); |
6337 | } else { | | 6337 | } else { |
6338 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); | | 6338 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); |
6339 | } | | 6339 | } |
6340 | } | | 6340 | } |
6341 | }; | | 6341 | }; |
6342 | | | 6342 | |
6343 | my $check_contents = sub() { | | 6343 | my $check_contents = sub() { |
6344 | | | 6344 | |
6345 | if ($m->has(1)) { | | 6345 | if ($m->has(1)) { |
6346 | $check_text->($m->text(1)); | | 6346 | $check_text->($m->text(1)); |
6347 | } | | 6347 | } |
6348 | }; | | 6348 | }; |
6349 | | | 6349 | |
6350 | my $check_added_contents = sub() { | | 6350 | my $check_added_contents = sub() { |
6351 | my $text; | | 6351 | my $text; |
6352 | | | 6352 | |
6353 | return unless $m->has(1); | | 6353 | return unless $m->has(1); |
6354 | $text = $m->text(1); | | 6354 | $text = $m->text(1); |
6355 | checkline_cpp_macro_names($line, $text); | | 6355 | checkline_cpp_macro_names($line, $text); |
6356 | checkline_spellcheck($line); | | 6356 | checkline_spellcheck($line); |
6357 | | | 6357 | |
6358 | # XXX: This check is not as accurate as the similar one in | | 6358 | # XXX: This check is not as accurate as the similar one in |
6359 | # checkline_mk_shelltext(). | | 6359 | # checkline_mk_shelltext(). |
6360 | if (defined($current_fname)) { | | 6360 | if (defined($current_fname)) { |
6361 | if ($current_ftype eq "shell" || $current_ftype eq "make") { | | 6361 | if ($current_ftype eq "shell" || $current_ftype eq "make") { |
6362 | my ($mm, $rest) = match_all($text, $regex_shellword); | | 6362 | my ($mm, $rest) = match_all($text, $regex_shellword); |
6363 | | | 6363 | |
6364 | foreach my $m (@{$mm}) { | | 6364 | foreach my $m (@{$mm}) { |
6365 | my $shellword = $m->text(1); | | 6365 | my $shellword = $m->text(1); |
6366 | | | 6366 | |
6367 | if ($shellword =~ m"^#") { | | 6367 | if ($shellword =~ m"^#") { |
6368 | last; | | 6368 | last; |
6369 | } | | 6369 | } |
6370 | checkline_mk_absolute_pathname($line, $shellword); | | 6370 | checkline_mk_absolute_pathname($line, $shellword); |
6371 | } | | 6371 | } |
6372 | | | 6372 | |
6373 | } elsif ($current_ftype eq "source") { | | 6373 | } elsif ($current_ftype eq "source") { |
6374 | checkline_source_absolute_pathname($line, $text); | | 6374 | checkline_source_absolute_pathname($line, $text); |
6375 | | | 6375 | |
6376 | } elsif ($current_ftype eq "configure") { | | 6376 | } elsif ($current_ftype eq "configure") { |
6377 | if ($text =~ m": Avoid regenerating within pkgsrc$") { | | 6377 | if ($text =~ m": Avoid regenerating within pkgsrc$") { |
6378 | $line->log_error("This code must not be included in patches."); | | 6378 | $line->log_error("This code must not be included in patches."); |
6379 | $line->explain_error( | | 6379 | $line->explain_error( |
6380 | "It is generated automatically by pkgsrc after the patch phase.", | | 6380 | "It is generated automatically by pkgsrc after the patch phase.", |
6381 | "", | | 6381 | "", |
6382 | "For more details, look for \"configure-scripts-override\" in", | | 6382 | "For more details, look for \"configure-scripts-override\" in", |
6383 | "mk/configure/gnu-configure.mk."); | | 6383 | "mk/configure/gnu-configure.mk."); |
6384 | } | | 6384 | } |
6385 | | | 6385 | |
6386 | } elsif ($current_ftype eq "ignore") { | | 6386 | } elsif ($current_ftype eq "ignore") { |
6387 | # Ignore it. | | 6387 | # Ignore it. |
6388 | | | 6388 | |
6389 | } else { | | 6389 | } else { |
6390 | checkline_other_absolute_pathname($line, $text); | | 6390 | checkline_other_absolute_pathname($line, $text); |
6391 | } | | 6391 | } |
6392 | } | | 6392 | } |
6393 | }; | | 6393 | }; |
6394 | | | 6394 | |
6395 | my $check_hunk_end = sub($$$) { | | 6395 | my $check_hunk_end = sub($$$) { |
6396 | my ($deldelta, $adddelta, $newstate) = @_; | | 6396 | my ($deldelta, $adddelta, $newstate) = @_; |
6397 | | | 6397 | |
6398 | if ($deldelta > 0 && $dellines == 0) { | | 6398 | if ($deldelta > 0 && $dellines == 0) { |
6399 | $redostate = $newstate; | | 6399 | $redostate = $newstate; |
6400 | if (defined($addlines) && $addlines > 0) { | | 6400 | if (defined($addlines) && $addlines > 0) { |
6401 | $line->log_error("Expected ${addlines} more lines to be added."); | | 6401 | $line->log_error("Expected ${addlines} more lines to be added."); |
6402 | } | | 6402 | } |
6403 | } elsif ($adddelta > 0 && $addlines == 0) { | | 6403 | } elsif ($adddelta > 0 && $addlines == 0) { |
6404 | $redostate = $newstate; | | 6404 | $redostate = $newstate; |
6405 | if (defined($dellines) && $dellines > 0) { | | 6405 | if (defined($dellines) && $dellines > 0) { |
6406 | $line->log_error("Expected ${dellines} more lines to be deleted."); | | 6406 | $line->log_error("Expected ${dellines} more lines to be deleted."); |
6407 | } | | 6407 | } |
6408 | } else { | | 6408 | } else { |
6409 | if (defined($context_scanning_leading)) { | | 6409 | if (defined($context_scanning_leading)) { |
6410 | if ($deldelta != 0 && $adddelta != 0) { | | 6410 | if ($deldelta != 0 && $adddelta != 0) { |
6411 | if ($context_scanning_leading) { | | 6411 | if ($context_scanning_leading) { |
6412 | $leading_context_lines++; | | 6412 | $leading_context_lines++; |
6413 | } else { | | 6413 | } else { |
6414 | $trailing_context_lines++; | | 6414 | $trailing_context_lines++; |
6415 | } | | 6415 | } |
6416 | } else { | | 6416 | } else { |
6417 | if ($context_scanning_leading) { | | 6417 | if ($context_scanning_leading) { |
6418 | $context_scanning_leading = false; | | 6418 | $context_scanning_leading = false; |
6419 | } else { | | 6419 | } else { |
6420 | $trailing_context_lines = 0; | | 6420 | $trailing_context_lines = 0; |
6421 | } | | 6421 | } |
6422 | } | | 6422 | } |
6423 | } | | 6423 | } |
6424 | | | 6424 | |
6425 | if ($deldelta != 0) { | | 6425 | if ($deldelta != 0) { |
6426 | $dellines -= $deldelta; | | 6426 | $dellines -= $deldelta; |
6427 | } | | 6427 | } |
6428 | if ($adddelta != 0) { | | 6428 | if ($adddelta != 0) { |
6429 | $addlines -= $adddelta; | | 6429 | $addlines -= $adddelta; |
6430 | } | | 6430 | } |
6431 | if (!((defined($dellines) && $dellines > 0) || | | 6431 | if (!((defined($dellines) && $dellines > 0) || |
6432 | (defined($addlines) && $addlines > 0))) { | | 6432 | (defined($addlines) && $addlines > 0))) { |
6433 | if (defined($context_scanning_leading)) { | | 6433 | if (defined($context_scanning_leading)) { |
6434 | if ($leading_context_lines != $trailing_context_lines) { | | 6434 | if ($leading_context_lines != $trailing_context_lines) { |
6435 | $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context."); | | 6435 | $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context."); |
6436 | } | | 6436 | } |
6437 | } | | 6437 | } |
6438 | $nextstate = $newstate; | | 6438 | $nextstate = $newstate; |
6439 | } | | 6439 | } |
6440 | } | | 6440 | } |
6441 | }; | | 6441 | }; |
6442 | | | 6442 | |
6443 | # @param deldelta | | 6443 | # @param deldelta |
6444 | # The number of lines that are deleted from the patched file. | | 6444 | # The number of lines that are deleted from the patched file. |
6445 | # @param adddelta | | 6445 | # @param adddelta |
6446 | # The number of lines that are added to the patched file. | | 6446 | # The number of lines that are added to the patched file. |
6447 | # @param newstate | | 6447 | # @param newstate |
6448 | # The follow-up state when this line is the last line to be | | 6448 | # The follow-up state when this line is the last line to be |
6449 | # added in this hunk of the patch. | | 6449 | # added in this hunk of the patch. |
6450 | # | | 6450 | # |
6451 | my $check_hunk_line = sub($$$) { | | 6451 | my $check_hunk_line = sub($$$) { |
6452 | my ($deldelta, $adddelta, $newstate) = @_; | | 6452 | my ($deldelta, $adddelta, $newstate) = @_; |
6453 | | | 6453 | |
6454 | $check_contents->(); | | 6454 | $check_contents->(); |
6455 | $check_hunk_end->($deldelta, $adddelta, $newstate); | | 6455 | $check_hunk_end->($deldelta, $adddelta, $newstate); |
6456 | | | 6456 | |
6457 | # If -Wextra is given, the context lines are checked for | | 6457 | # If -Wextra is given, the context lines are checked for |
6458 | # absolute paths and similar things. If it is not given, | | 6458 | # absolute paths and similar things. If it is not given, |
6459 | # only those lines that really add something to the patched | | 6459 | # only those lines that really add something to the patched |
6460 | # file are checked. | | 6460 | # file are checked. |
6461 | if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { | | 6461 | if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { |
6462 | $check_added_contents->(); | | 6462 | $check_added_contents->(); |
6463 | } | | 6463 | } |
6464 | }; | | 6464 | }; |
6465 | | | 6465 | |
6466 | my $transitions = | | 6466 | my $transitions = |
6467 | # [ from state, regex, to state, action ] | | 6467 | # [ from state, regex, to state, action ] |
6468 | [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { | | 6468 | [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { |
6469 | checkline_rcsid($line, ""); | | 6469 | checkline_rcsid($line, ""); |
6470 | }], [PST_START, undef, PST_CENTER, sub() { | | 6470 | }], [PST_START, undef, PST_CENTER, sub() { |
6471 | checkline_rcsid($line, ""); | | 6471 | checkline_rcsid($line, ""); |
6472 | }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { | | 6472 | }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { |
6473 | # | | 6473 | # |
6474 | }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { | | 6474 | }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { |
6475 | if (!$seen_comment) { | | 6475 | if (!$seen_comment) { |
6476 | $line->log_error("Comment expected."); | | 6476 | $line->log_error("Comment expected."); |
6477 | $line->explain_error(@comment_explanation); | | 6477 | $line->explain_error(@comment_explanation); |
6478 | } | | 6478 | } |
6479 | $line->log_warning("Please use unified diffs (diff -u) for patches."); | | 6479 | $line->log_warning("Please use unified diffs (diff -u) for patches."); |
6480 | }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { | | 6480 | }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { |
6481 | if (!$seen_comment) { | | 6481 | if (!$seen_comment) { |
6482 | $line->log_error("Comment expected."); | | 6482 | $line->log_error("Comment expected."); |
6483 | $line->explain_error(@comment_explanation); | | 6483 | $line->explain_error(@comment_explanation); |
6484 | } | | 6484 | } |
6485 | }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { | | 6485 | }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { |
6486 | $seen_comment = true; | | 6486 | $seen_comment = true; |
6487 | }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { | | 6487 | }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { |
6488 | # | | 6488 | # |
6489 | }], [PST_TEXT, undef, PST_TEXT, sub() { | | 6489 | }], [PST_TEXT, undef, PST_TEXT, sub() { |
6490 | # | | 6490 | # |
6491 | }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { | | 6491 | }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { |
6492 | if ($seen_comment) { | | 6492 | if ($seen_comment) { |
6493 | $opt_warn_space and $line->log_note("Empty line expected."); | | 6493 | $opt_warn_space and $line->log_note("Empty line expected."); |
6494 | } else { | | 6494 | } else { |
6495 | $line->log_error("Comment expected."); | | 6495 | $line->log_error("Comment expected."); |
6496 | $line->explain_error(@comment_explanation); | | 6496 | $line->explain_error(@comment_explanation); |
6497 | } | | 6497 | } |
6498 | $line->log_warning("Please use unified diffs (diff -u) for patches."); | | 6498 | $line->log_warning("Please use unified diffs (diff -u) for patches."); |
6499 | }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { | | 6499 | }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { |
6500 | if ($seen_comment) { | | 6500 | if ($seen_comment) { |
6501 | $opt_warn_space and $line->log_note("Empty line expected."); | | 6501 | $opt_warn_space and $line->log_note("Empty line expected."); |
6502 | } else { | | 6502 | } else { |
6503 | $line->log_error("Comment expected."); | | 6503 | $line->log_error("Comment expected."); |
6504 | $line->explain_error(@comment_explanation); | | 6504 | $line->explain_error(@comment_explanation); |
6505 | } | | 6505 | } |
6506 | }], [PST_CENTER, undef, PST_TEXT, sub() { | | 6506 | }], [PST_CENTER, undef, PST_TEXT, sub() { |
6507 | $opt_warn_space and $line->log_note("Empty line expected."); | | 6507 | $opt_warn_space and $line->log_note("Empty line expected."); |
6508 | }], [PST_CFA, re_patch_cfa, PST_CH, sub() { | | 6508 | }], [PST_CFA, re_patch_cfa, PST_CH, sub() { |
6509 | $current_fname = $m->text(1); | | 6509 | $current_fname = $m->text(1); |
6510 | $current_ftype = get_filetype($line, $current_fname); | | 6510 | $current_ftype = get_filetype($line, $current_fname); |
6511 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); | | 6511 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); |
6512 | $patched_files++; | | 6512 | $patched_files++; |
6513 | $hunks = 0; | | 6513 | $hunks = 0; |
6514 | }], [PST_CH, re_patch_ch, PST_CHD, sub() { | | 6514 | }], [PST_CH, re_patch_ch, PST_CHD, sub() { |
6515 | $hunks++; | | 6515 | $hunks++; |
6516 | }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { | | 6516 | }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { |
6517 | $dellines = ($m->has(2)) | | 6517 | $dellines = ($m->has(2)) |
6518 | ? (1 + $m->text(2) - $m->text(1)) | | 6518 | ? (1 + $m->text(2) - $m->text(1)) |
6519 | : ($m->text(1)); | | 6519 | : ($m->text(1)); |
6520 | }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { | | 6520 | }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { |
6521 | $check_hunk_line->(1, 0, PST_CLD0); | | 6521 | $check_hunk_line->(1, 0, PST_CLD0); |
6522 | }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { | | 6522 | }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { |
6523 | $check_hunk_line->(1, 0, PST_CLD0); | | 6523 | $check_hunk_line->(1, 0, PST_CLD0); |
6524 | }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { | | 6524 | }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { |
6525 | $check_hunk_line->(1, 0, PST_CLD0); | | 6525 | $check_hunk_line->(1, 0, PST_CLD0); |
6526 | }], [PST_CLD, re_patch_clc, PST_CLD, sub() { | | 6526 | }], [PST_CLD, re_patch_clc, PST_CLD, sub() { |
6527 | $check_hunk_line->(1, 0, PST_CLD0); | | 6527 | $check_hunk_line->(1, 0, PST_CLD0); |
6528 | }], [PST_CLD, re_patch_cld, PST_CLD, sub() { | | 6528 | }], [PST_CLD, re_patch_cld, PST_CLD, sub() { |
6529 | $check_hunk_line->(1, 0, PST_CLD0); | | 6529 | $check_hunk_line->(1, 0, PST_CLD0); |
6530 | }], [PST_CLD, re_patch_clm, PST_CLD, sub() { | | 6530 | }], [PST_CLD, re_patch_clm, PST_CLD, sub() { |
6531 | $check_hunk_line->(1, 0, PST_CLD0); | | 6531 | $check_hunk_line->(1, 0, PST_CLD0); |
6532 | }], [PST_CLD, undef, PST_CLD0, sub() { | | 6532 | }], [PST_CLD, undef, PST_CLD0, sub() { |
6533 | if ($dellines != 0) { | | 6533 | if ($dellines != 0) { |
6534 | $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); | | 6534 | $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); |
6535 | } | | 6535 | } |
6536 | }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { | | 6536 | }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { |
6537 | $dellines = undef; | | 6537 | $dellines = undef; |
6538 | $addlines = ($m->has(2)) | | 6538 | $addlines = ($m->has(2)) |
6539 | ? (1 + $m->text(2) - $m->text(1)) | | 6539 | ? (1 + $m->text(2) - $m->text(1)) |
6540 | : ($m->text(1)); | | 6540 | : ($m->text(1)); |
6541 | }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { | | 6541 | }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { |
6542 | $check_hunk_line->(0, 1, PST_CH); | | 6542 | $check_hunk_line->(0, 1, PST_CH); |
6543 | }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { | | 6543 | }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { |
6544 | $check_hunk_line->(0, 1, PST_CH); | | 6544 | $check_hunk_line->(0, 1, PST_CH); |
6545 | }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { | | 6545 | }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { |
6546 | $check_hunk_line->(0, 1, PST_CH); | | 6546 | $check_hunk_line->(0, 1, PST_CH); |
6547 | }], [PST_CLA, re_patch_clc, PST_CLA, sub() { | | 6547 | }], [PST_CLA, re_patch_clc, PST_CLA, sub() { |
6548 | $check_hunk_line->(0, 1, PST_CH); | | 6548 | $check_hunk_line->(0, 1, PST_CH); |
6549 | }], [PST_CLA, re_patch_clm, PST_CLA, sub() { | | 6549 | }], [PST_CLA, re_patch_clm, PST_CLA, sub() { |
6550 | $check_hunk_line->(0, 1, PST_CH); | | 6550 | $check_hunk_line->(0, 1, PST_CH); |
6551 | }], [PST_CLA, re_patch_cla, PST_CLA, sub() { | | 6551 | }], [PST_CLA, re_patch_cla, PST_CLA, sub() { |
6552 | $check_hunk_line->(0, 1, PST_CH); | | 6552 | $check_hunk_line->(0, 1, PST_CH); |
6553 | }], [PST_CLA, undef, PST_CLA0, sub() { | | 6553 | }], [PST_CLA, undef, PST_CLA0, sub() { |
6554 | if ($addlines != 0) { | | 6554 | if ($addlines != 0) { |
6555 | $line->log_warning("Invalid number of added lines (${addlines} missing)."); | | 6555 | $line->log_warning("Invalid number of added lines (${addlines} missing)."); |
6556 | } | | 6556 | } |
6557 | }], [PST_CLA0, undef, PST_CH, sub() { | | 6557 | }], [PST_CLA0, undef, PST_CH, sub() { |
6558 | # | | 6558 | # |
6559 | }], [PST_CH, undef, PST_TEXT, sub() { | | 6559 | }], [PST_CH, undef, PST_TEXT, sub() { |
6560 | # | | 6560 | # |
6561 | }], [PST_UFA, re_patch_ufa, PST_UH, sub() { | | 6561 | }], [PST_UFA, re_patch_ufa, PST_UH, sub() { |
6562 | $current_fname = $m->text(1); | | 6562 | $current_fname = $m->text(1); |
6563 | $current_ftype = get_filetype($line, $current_fname); | | 6563 | $current_ftype = get_filetype($line, $current_fname); |
6564 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); | | 6564 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); |
6565 | $patched_files++; | | 6565 | $patched_files++; |
6566 | $hunks = 0; | | 6566 | $hunks = 0; |
6567 | }], [PST_UH, re_patch_uh, PST_UL, sub() { | | 6567 | }], [PST_UH, re_patch_uh, PST_UL, sub() { |
6568 | $dellines = ($m->has(1) ? $m->text(2) : 1); | | 6568 | $dellines = ($m->has(1) ? $m->text(2) : 1); |
6569 | $addlines = ($m->has(3) ? $m->text(4) : 1); | | 6569 | $addlines = ($m->has(3) ? $m->text(4) : 1); |
6570 | $check_text->($line->text); | | 6570 | $check_text->($line->text); |
6571 | if ($line->text =~ m"\r$") { | | 6571 | if ($line->text =~ m"\r$") { |
6572 | $line->log_error("The hunk header must not end with a CR character."); | | 6572 | $line->log_error("The hunk header must not end with a CR character."); |
6573 | $line->explain_error( | | 6573 | $line->explain_error( |
6574 | "The MacOS X patch utility cannot handle these."); | | 6574 | "The MacOS X patch utility cannot handle these."); |
6575 | } | | 6575 | } |
6576 | $hunks++; | | 6576 | $hunks++; |
6577 | $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); | | 6577 | $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); |
6578 | $leading_context_lines = 0; | | 6578 | $leading_context_lines = 0; |
6579 | $trailing_context_lines = 0; | | 6579 | $trailing_context_lines = 0; |
6580 | }], [PST_UL, re_patch_uld, PST_UL, sub() { | | 6580 | }], [PST_UL, re_patch_uld, PST_UL, sub() { |
6581 | $check_hunk_line->(1, 0, PST_UH); | | 6581 | $check_hunk_line->(1, 0, PST_UH); |
6582 | }], [PST_UL, re_patch_ula, PST_UL, sub() { | | 6582 | }], [PST_UL, re_patch_ula, PST_UL, sub() { |
6583 | $check_hunk_line->(0, 1, PST_UH); | | 6583 | $check_hunk_line->(0, 1, PST_UH); |
6584 | }], [PST_UL, re_patch_ulc, PST_UL, sub() { | | 6584 | }], [PST_UL, re_patch_ulc, PST_UL, sub() { |
6585 | $check_hunk_line->(1, 1, PST_UH); | | 6585 | $check_hunk_line->(1, 1, PST_UH); |
6586 | }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { | | 6586 | }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { |
6587 | # | | 6587 | # |
6588 | }], [PST_UL, re_patch_empty, PST_UL, sub() { | | 6588 | }], [PST_UL, re_patch_empty, PST_UL, sub() { |
6589 | $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); | | 6589 | $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); |
6590 | $check_hunk_line->(1, 1, PST_UH); | | 6590 | $check_hunk_line->(1, 1, PST_UH); |
6591 | }], [PST_UL, undef, PST_UH, sub() { | | 6591 | }], [PST_UL, undef, PST_UH, sub() { |
6592 | if ($dellines != 0 || $addlines != 0) { | | 6592 | if ($dellines != 0 || $addlines != 0) { |
6593 | $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); | | 6593 | $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); |
6594 | } | | 6594 | } |
6595 | }], [PST_UH, undef, PST_TEXT, sub() { | | 6595 | }], [PST_UH, undef, PST_TEXT, sub() { |
6596 | ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); | | 6596 | ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); |
6597 | }]]; | | 6597 | }]]; |
6598 | | | 6598 | |
6599 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); | | 6599 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); |
6600 | | | 6600 | |
6601 | checkperms($fname); | | 6601 | checkperms($fname); |
6602 | if (!($lines = load_lines($fname, false))) { | | 6602 | if (!($lines = load_lines($fname, false))) { |
6603 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 6603 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
6604 | return; | | 6604 | return; |
6605 | } | | 6605 | } |
6606 | if (@{$lines} == 0) { | | 6606 | if (@{$lines} == 0) { |
6607 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 6607 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
6608 | return; | | 6608 | return; |
6609 | } | | 6609 | } |
6610 | | | 6610 | |
6611 | $state = PST_START; | | 6611 | $state = PST_START; |
6612 | $dellines = undef; | | 6612 | $dellines = undef; |
6613 | $addlines = undef; | | 6613 | $addlines = undef; |
6614 | $patched_files = 0; | | 6614 | $patched_files = 0; |
6615 | $seen_comment = false; | | 6615 | $seen_comment = false; |
6616 | $current_fname = undef; | | 6616 | $current_fname = undef; |
6617 | $current_ftype = undef; | | 6617 | $current_ftype = undef; |
6618 | $hunks = undef; | | 6618 | $hunks = undef; |
6619 | | | 6619 | |
6620 | for (my $lineno = 0; $lineno <= $#{$lines}; ) { | | 6620 | for (my $lineno = 0; $lineno <= $#{$lines}; ) { |
6621 | $line = $lines->[$lineno]; | | 6621 | $line = $lines->[$lineno]; |
6622 | my $text = $line->text; | | 6622 | my $text = $line->text; |
6623 | | | 6623 | |
6624 | $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); | | 6624 | $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); |
6625 | | | 6625 | |
6626 | my $found = false; | | 6626 | my $found = false; |
6627 | foreach my $t (@{$transitions}) { | | 6627 | foreach my $t (@{$transitions}) { |
6628 | if ($state == $t->[0]) { | | 6628 | if ($state == $t->[0]) { |
6629 | if (!defined($t->[1])) { | | 6629 | if (!defined($t->[1])) { |
6630 | $m = undef; | | 6630 | $m = undef; |
6631 | } elsif ($text =~ $t->[1]) { | | 6631 | } elsif ($text =~ $t->[1]) { |
6632 | $opt_debug_patches and $line->log_debug($t->[1]); | | 6632 | $opt_debug_patches and $line->log_debug($t->[1]); |
6633 | $m = PkgLint::SimpleMatch->new($text, \@-, \@+); | | 6633 | $m = PkgLint::SimpleMatch->new($text, \@-, \@+); |
6634 | } else { | | 6634 | } else { |
6635 | next; | | 6635 | next; |
6636 | } | | 6636 | } |
6637 | $redostate = undef; | | 6637 | $redostate = undef; |
6638 | $nextstate = $t->[2]; | | 6638 | $nextstate = $t->[2]; |
6639 | $t->[3]->(); | | 6639 | $t->[3]->(); |
6640 | if (defined($redostate)) { | | 6640 | if (defined($redostate)) { |
6641 | $state = $redostate; | | 6641 | $state = $redostate; |
6642 | } else { | | 6642 | } else { |
6643 | $state = $nextstate; | | 6643 | $state = $nextstate; |
6644 | if (defined($t->[1])) { | | 6644 | if (defined($t->[1])) { |
6645 | $lineno++; | | 6645 | $lineno++; |
6646 | } | | 6646 | } |
6647 | } | | 6647 | } |
6648 | $found = true; | | 6648 | $found = true; |
6649 | last; | | 6649 | last; |
6650 | } | | 6650 | } |
6651 | } | | 6651 | } |
6652 | | | 6652 | |
6653 | if (!$found) { | | 6653 | if (!$found) { |
6654 | $line->log_error("Parse error: state=${state}"); | | 6654 | $line->log_error("Parse error: state=${state}"); |
6655 | $state = PST_TEXT; | | 6655 | $state = PST_TEXT; |
6656 | $lineno++; | | 6656 | $lineno++; |
6657 | } | | 6657 | } |
6658 | } | | 6658 | } |
6659 | | | 6659 | |
6660 | while ($state != PST_TEXT) { | | 6660 | while ($state != PST_TEXT) { |
6661 | $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); | | 6661 | $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); |
6662 | | | 6662 | |
6663 | my $found = false; | | 6663 | my $found = false; |
6664 | foreach my $t (@{$transitions}) { | | 6664 | foreach my $t (@{$transitions}) { |
6665 | if ($state == $t->[0] && !defined($t->[1])) { | | 6665 | if ($state == $t->[0] && !defined($t->[1])) { |
6666 | my $newstate; | | 6666 | my $newstate; |
6667 | | | 6667 | |
6668 | $m = undef; | | 6668 | $m = undef; |
6669 | $redostate = undef; | | 6669 | $redostate = undef; |
6670 | $nextstate = $t->[2]; | | 6670 | $nextstate = $t->[2]; |
6671 | $t->[3]->(); | | 6671 | $t->[3]->(); |
6672 | $newstate = (defined($redostate)) ? $redostate : $nextstate; | | 6672 | $newstate = (defined($redostate)) ? $redostate : $nextstate; |
6673 | if ($newstate == $state) { | | 6673 | if ($newstate == $state) { |
6674 | log_fatal($fname, "EOF", "Internal error in the patch transition table."); | | 6674 | log_fatal($fname, "EOF", "Internal error in the patch transition table."); |
6675 | } | | 6675 | } |
6676 | $state = $newstate; | | 6676 | $state = $newstate; |
6677 | $found = true; | | 6677 | $found = true; |
6678 | last; | | 6678 | last; |
6679 | } | | 6679 | } |
6680 | } | | 6680 | } |
6681 | | | 6681 | |
6682 | if (!$found) { | | 6682 | if (!$found) { |
6683 | log_error($fname, "EOF", "Parse error: state=${state}"); | | 6683 | log_error($fname, "EOF", "Parse error: state=${state}"); |
6684 | $state = PST_TEXT; | | 6684 | $state = PST_TEXT; |
6685 | } | | 6685 | } |
6686 | } | | 6686 | } |
6687 | | | 6687 | |
6688 | if ($patched_files > 1) { | | 6688 | if ($patched_files > 1) { |
6689 | log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); | | 6689 | log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); |
6690 | | | 6690 | |
6691 | } elsif ($patched_files == 0) { | | 6691 | } elsif ($patched_files == 0) { |
6692 | log_error($fname, NO_LINE_NUMBER, "Contains no patch."); | | 6692 | log_error($fname, NO_LINE_NUMBER, "Contains no patch."); |
6693 | } | | 6693 | } |
6694 | | | 6694 | |
6695 | checklines_trailing_empty_lines($lines); | | 6695 | checklines_trailing_empty_lines($lines); |
6696 | } | | 6696 | } |
6697 | | | 6697 | |
6698 | sub checkfile_PLIST($) { | | 6698 | sub checkfile_PLIST($) { |
6699 | my ($fname) = @_; | | 6699 | my ($fname) = @_; |
6700 | my ($lines, $last_file_seen); | | 6700 | my ($lines, $last_file_seen); |
6701 | | | 6701 | |
6702 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); | | 6702 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); |
6703 | | | 6703 | |
6704 | checkperms($fname); | | 6704 | checkperms($fname); |
6705 | if (!($lines = load_file($fname))) { | | 6705 | if (!($lines = load_file($fname))) { |
6706 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6706 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6707 | return; | | 6707 | return; |
6708 | } | | 6708 | } |
6709 | if (@{$lines} == 0) { | | 6709 | if (@{$lines} == 0) { |
6710 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 6710 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
6711 | return; | | 6711 | return; |
6712 | } | | 6712 | } |
6713 | checkline_rcsid($lines->[0], "\@comment "); | | 6713 | checkline_rcsid($lines->[0], "\@comment "); |
6714 | | | 6714 | |
6715 | if (@$lines == 1) { | | 6715 | if (@$lines == 1) { |
6716 | $lines->[0]->log_warning("PLIST files shouldn't be empty."); | | 6716 | $lines->[0]->log_warning("PLIST files shouldn't be empty."); |
6717 | $lines->[0]->explain_warning( | | 6717 | $lines->[0]->explain_warning( |
6718 | "One reason for empty PLISTs is that this is a newly created package", | | 6718 | "One reason for empty PLISTs is that this is a newly created package", |
6719 | "and that the author didn't run \"bmake print-PLIST\" after installing", | | 6719 | "and that the author didn't run \"bmake print-PLIST\" after installing", |
6720 | "the files.", | | 6720 | "the files.", |
6721 | "", | | 6721 | "", |
6722 | "Another reason, common for Perl packages, is that the final PLIST is", | | 6722 | "Another reason, common for Perl packages, is that the final PLIST is", |
6723 | "automatically generated. Since the source PLIST is not used at all,", | | 6723 | "automatically generated. Since the source PLIST is not used at all,", |
6724 | "you can remove it.", | | 6724 | "you can remove it.", |
6725 | "", | | 6725 | "", |
6726 | "Meta packages also don't need a PLIST file."); | | 6726 | "Meta packages also don't need a PLIST file."); |
6727 | } | | 6727 | } |
6728 | | | 6728 | |
6729 | # Get the list of all files from the PLIST. | | 6729 | # Get the list of all files from the PLIST. |
6730 | my $all_files = {}; | | 6730 | my $all_files = {}; |
6731 | my $all_dirs = {}; | | 6731 | my $all_dirs = {}; |
6732 | my $extra_lines = []; | | 6732 | my $extra_lines = []; |
6733 | if (basename($fname) eq "PLIST.common_end") { | | 6733 | if (basename($fname) eq "PLIST.common_end") { |
6734 | my $common_lines = load_file(dirname($fname) . "/PLIST.common"); | | 6734 | my $common_lines = load_file(dirname($fname) . "/PLIST.common"); |
6735 | if ($common_lines) { | | 6735 | if ($common_lines) { |
6736 | $extra_lines = $common_lines; | | 6736 | $extra_lines = $common_lines; |
6737 | } | | 6737 | } |
6738 | } | | 6738 | } |
6739 | | | 6739 | |
6740 | foreach my $line (@{$extra_lines}, @{$lines}) { | | 6740 | foreach my $line (@{$extra_lines}, @{$lines}) { |
6741 | my $text = $line->text; | | 6741 | my $text = $line->text; |
6742 | | | 6742 | |
6743 | if ($text =~ m"\$\{([\w_]+)\}(.*)") { | | 6743 | if ($text =~ m"\$\{([\w_]+)\}(.*)") { |
6744 | if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { | | 6744 | if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { |
6745 | $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); | | 6745 | $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); |
6746 | $text = $2; | | 6746 | $text = $2; |
6747 | } | | 6747 | } |
6748 | } | | 6748 | } |
6749 | | | 6749 | |
6750 | if ($text =~ m"^[\w\$]") { | | 6750 | if ($text =~ m"^[\w\$]") { |
6751 | $all_files->{$text} = $line; | | 6751 | $all_files->{$text} = $line; |
6752 | my $dir = $text; | | 6752 | my $dir = $text; |
6753 | while ($dir =~ s,/[^/]+$,,) { | | 6753 | while ($dir =~ s,/[^/]+$,,) { |
6754 | $all_dirs->{$dir} = $line; | | 6754 | $all_dirs->{$dir} = $line; |
6755 | } | | 6755 | } |
6756 | } | | 6756 | } |
6757 | if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { | | 6757 | if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { |
6758 | my $dir = $1; | | 6758 | my $dir = $1; |
6759 | do { | | 6759 | do { |
6760 | $all_dirs->{$dir} = $line; | | 6760 | $all_dirs->{$dir} = $line; |
6761 | } while ($dir =~ s,/[^/]+$,,); | | 6761 | } while ($dir =~ s,/[^/]+$,,); |
6762 | } | | 6762 | } |
6763 | } | | 6763 | } |
6764 | | | 6764 | |
6765 | foreach my $line (@{$lines}) { | | 6765 | foreach my $line (@{$lines}) { |
6766 | my $text = $line->text; | | 6766 | my $text = $line->text; |
6767 | | | 6767 | |
6768 | if ($text =~ /\s$/) { | | 6768 | if ($text =~ /\s$/) { |
6769 | $line->log_error("pkgsrc does not support filenames ending in white-space."); | | 6769 | $line->log_error("pkgsrc does not support filenames ending in white-space."); |
6770 | $line->explain_error( | | 6770 | $line->explain_error( |
6771 | "Each character in the PLIST is relevant, even trailing white-space."); | | 6771 | "Each character in the PLIST is relevant, even trailing white-space."); |
6772 | } | | 6772 | } |
6773 | | | 6773 | |
6774 | # @foo directives. | | 6774 | # @foo directives. |
6775 | if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { | | 6775 | if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { |
6776 | my ($cmd, $arg) = ($1, $2); | | 6776 | my ($cmd, $arg) = ($1, $2); |
6777 | | | 6777 | |
6778 | if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { | | 6778 | if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { |
6779 | my ($rmdir, $rest) = ($1, $2); | | 6779 | my ($rmdir, $rest) = ($1, $2); |
6780 | if ($rest !~ m"(?:true|\$\{TRUE\})") { | | 6780 | if ($rest !~ m"(?:true|\$\{TRUE\})") { |
6781 | $line->log_warning("Please remove this line. It is no longer necessary."); | | 6781 | $line->log_warning("Please remove this line. It is no longer necessary."); |
6782 | } | | 6782 | } |
6783 | | | 6783 | |
6784 | } elsif (($cmd eq "exec" || $cmd eq "unexec")) { | | 6784 | } elsif (($cmd eq "exec" || $cmd eq "unexec")) { |
6785 | if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { | | 6785 | if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { |
6786 | $line->log_warning("\@exec/unexec install-info is deprecated."); | | 6786 | $line->log_warning("\@exec/unexec install-info is deprecated."); |
6787 | | | 6787 | |
6788 | } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { | | 6788 | } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { |
6789 | $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); | | 6789 | $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); |
6790 | } | | 6790 | } |
6791 | | | 6791 | |
6792 | } elsif ($cmd eq "comment") { | | 6792 | } elsif ($cmd eq "comment") { |
6793 | # nothing to do | | 6793 | # nothing to do |
6794 | | | 6794 | |
6795 | } elsif ($cmd eq "dirrm") { | | 6795 | } elsif ($cmd eq "dirrm") { |
6796 | $line->log_warning("\@dirrm is obsolete. Please remove this line."); | | 6796 | $line->log_warning("\@dirrm is obsolete. Please remove this line."); |
6797 | $line->explain_warning( | | 6797 | $line->explain_warning( |
6798 | "Directories are removed automatically when they are empty.", | | 6798 | "Directories are removed automatically when they are empty.", |
6799 | "When a package needs an empty directory, it can use the \@pkgdir", | | 6799 | "When a package needs an empty directory, it can use the \@pkgdir", |
6800 | "command in the PLIST"); | | 6800 | "command in the PLIST"); |
6801 | } elsif ($cmd eq "imake-man") { | | 6801 | } elsif ($cmd eq "imake-man") { |
6802 | my (@args) = split(/\s+/, $arg); | | 6802 | my (@args) = split(/\s+/, $arg); |
6803 | if (@args != 3) { | | 6803 | if (@args != 3) { |
6804 | $line->log_warning("Invalid number of arguments for imake-man."); | | 6804 | $line->log_warning("Invalid number of arguments for imake-man."); |
6805 | } else { | | 6805 | } else { |
6806 | if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { | | 6806 | if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { |
6807 | warn_about_PLIST_imake_mannewsuffix($line); | | 6807 | warn_about_PLIST_imake_mannewsuffix($line); |
6808 | } | | 6808 | } |
6809 | } | | 6809 | } |
6810 | | | 6810 | |
6811 | } elsif ($cmd eq "pkgdir") { | | 6811 | } elsif ($cmd eq "pkgdir") { |
6812 | # TODO: What can we check here? | | 6812 | # TODO: What can we check here? |
6813 | | | 6813 | |
6814 | } else { | | 6814 | } else { |
6815 | $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); | | 6815 | $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); |
6816 | } | | 6816 | } |
6817 | | | 6817 | |
6818 | # Pathnames. | | 6818 | # Pathnames. |
6819 | } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { | | 6819 | } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { |
6820 | my ($dirname, $basename) = ($1, $2); | | 6820 | my ($dirname, $basename) = ($1, $2); |
6821 | | | 6821 | |
6822 | if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { | | 6822 | if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { |
6823 | if (defined($last_file_seen)) { | | 6823 | if (defined($last_file_seen)) { |
6824 | if ($last_file_seen gt $text) { | | 6824 | if ($last_file_seen gt $text) { |
6825 | $line->log_warning("${text} should be sorted before ${last_file_seen}."); | | 6825 | $line->log_warning("${text} should be sorted before ${last_file_seen}."); |
6826 | $line->explain_warning( | | 6826 | $line->explain_warning( |
6827 | "For aesthetic reasons, the files in the PLIST should be sorted", | | 6827 | "For aesthetic reasons, the files in the PLIST should be sorted", |
6828 | "alphabetically."); | | 6828 | "alphabetically."); |
6829 | } elsif ($last_file_seen eq $text) { | | 6829 | } elsif ($last_file_seen eq $text) { |
6830 | $line->log_warning("Duplicate filename."); | | 6830 | $line->log_warning("Duplicate filename."); |
6831 | } | | 6831 | } |
6832 | } | | 6832 | } |
6833 | $last_file_seen = $text; | | 6833 | $last_file_seen = $text; |
6834 | } | | 6834 | } |
6835 | | | 6835 | |
6836 | if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") { | | 6836 | if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") { |
6837 | warn_about_PLIST_imake_mannewsuffix($line); | | 6837 | warn_about_PLIST_imake_mannewsuffix($line); |
6838 | } | | 6838 | } |
6839 | | | 6839 | |
6840 | if ($dirname =~ m"^bin/") { | | 6840 | if ($dirname =~ m"^bin/") { |
6841 | $line->log_warning("The bin/ directory should not have subdirectories."); | | 6841 | $line->log_warning("The bin/ directory should not have subdirectories."); |
6842 | | | 6842 | |
6843 | } elsif ($dirname eq "bin") { | | 6843 | } elsif ($dirname eq "bin") { |
6844 | | | 6844 | |
6845 | if (exists($all_files->{"man/man1/${basename}.1"})) { | | 6845 | if (exists($all_files->{"man/man1/${basename}.1"})) { |
6846 | # Fine. | | 6846 | # Fine. |
6847 | } elsif (exists($all_files->{"man/man6/${basename}.6"})) { | | 6847 | } elsif (exists($all_files->{"man/man6/${basename}.6"})) { |
6848 | # Fine. | | 6848 | # Fine. |
6849 | } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) { | | 6849 | } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) { |
6850 | # Fine. | | 6850 | # Fine. |
6851 | } else { | | 6851 | } else { |
6852 | $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}."); | | 6852 | $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}."); |
6853 | $opt_warn_extra and $line->explain_warning( | | 6853 | $opt_warn_extra and $line->explain_warning( |
6854 | "All programs that can be run directly by the user should have a manual", | | 6854 | "All programs that can be run directly by the user should have a manual", |
6855 | "page for quick reference. The programs in the bin/ directory should have", | | 6855 | "page for quick reference. The programs in the bin/ directory should have", |
6856 | "corresponding manual pages in section 1 (filename program.1), not in", | | 6856 | "corresponding manual pages in section 1 (filename program.1), not in", |
6857 | "section 8."); | | 6857 | "section 8."); |
6858 | } | | 6858 | } |
6859 | | | 6859 | |
6860 | } elsif ($text =~ m"^doc/") { | | 6860 | } elsif ($text =~ m"^doc/") { |
6861 | $line->log_error("Documentation must be installed under share/doc, not doc."); | | 6861 | $line->log_error("Documentation must be installed under share/doc, not doc."); |
6862 | | | 6862 | |
6863 | } elsif ($text =~ m"^etc/rc\.d/") { | | 6863 | } elsif ($text =~ m"^etc/rc\.d/") { |
6864 | $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework."); | | 6864 | $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework."); |
6865 | | | 6865 | |
6866 | } elsif ($text =~ m"^etc/") { | | 6866 | } elsif ($text =~ m"^etc/") { |
6867 | my $f = "mk/pkginstall/bsd.pkginstall.mk"; | | 6867 | my $f = "mk/pkginstall/bsd.pkginstall.mk"; |
6868 | | | 6868 | |
6869 | assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file."); | | 6869 | assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file."); |
6870 | $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}."); | | 6870 | $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}."); |
6871 | | | 6871 | |
6872 | } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") { | | 6872 | } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") { |
6873 | # Fine. | | 6873 | # Fine. |
6874 | | | 6874 | |
6875 | } elsif ($text eq "info/dir") { | | 6875 | } elsif ($text eq "info/dir") { |
6876 | $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry."); | | 6876 | $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry."); |
6877 | | | 6877 | |
6878 | } elsif ($text =~ m"^info/.+$") { | | 6878 | } elsif ($text =~ m"^info/.+$") { |
6879 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) { | | 6879 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) { |
6880 | $line->log_warning("Packages that install info files should set INFO_FILES."); | | 6880 | $line->log_warning("Packages that install info files should set INFO_FILES."); |
6881 | } | | 6881 | } |
6882 | | | 6882 | |
6883 | } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") { | | 6883 | } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") { |
6884 | # Fine. | | 6884 | # Fine. |
6885 | | | 6885 | |
6886 | } elsif ($text =~ m"^lib/locale/") { | | 6886 | } elsif ($text =~ m"^lib/locale/") { |
6887 | $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead."); | | 6887 | $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead."); |
6888 | | | 6888 | |
6889 | } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") { | | 6889 | } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") { |
6890 | my ($dir, $lib, $ext) = ($1, $2, $3); | | 6890 | my ($dir, $lib, $ext) = ($1, $2, $3); |
6891 | | | 6891 | |
6892 | if ($dir eq "lib/" && $lib !~ m"^lib") { | | 6892 | if ($dir eq "lib/" && $lib !~ m"^lib") { |
6893 | $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\"."); | | 6893 | $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\"."); |
6894 | } | | 6894 | } |
6895 | if ($ext eq "la") { | | 6895 | if ($ext eq "la") { |
6896 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) { | | 6896 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) { |
6897 | $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL."); | | 6897 | $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL."); |
6898 | } | | 6898 | } |
6899 | } | | 6899 | } |
6900 | | | 6900 | |
6901 | } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") { | | 6901 | } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") { |
6902 | my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5); | | 6902 | my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5); |
6903 | | | 6903 | |
6904 | if ($section !~ m"^[\dln]$") { | | 6904 | if ($section !~ m"^[\dln]$") { |
6905 | $line->log_warning("Unknown section \"${section}\" for manual page."); | | 6905 | $line->log_warning("Unknown section \"${section}\" for manual page."); |
6906 | } | | 6906 | } |
6907 | | | 6907 | |
6908 | if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) { | | 6908 | if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) { |
6909 | $line->log_warning("Preformatted manual page without unformatted one."); | | 6909 | $line->log_warning("Preformatted manual page without unformatted one."); |
6910 | } | | 6910 | } |
6911 | | | 6911 | |
6912 | if ($cat_or_man eq "cat") { | | 6912 | if ($cat_or_man eq "cat") { |
6913 | if ($ext ne "0") { | | 6913 | if ($ext ne "0") { |
6914 | $line->log_warning("Preformatted manual pages should end in \".0\"."); | | 6914 | $line->log_warning("Preformatted manual pages should end in \".0\"."); |
6915 | } | | 6915 | } |
6916 | } else { | | 6916 | } else { |
6917 | if ($section ne $ext) { | | 6917 | if ($section ne $ext) { |
6918 | $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page."); | | 6918 | $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page."); |
6919 | } | | 6919 | } |
6920 | } | | 6920 | } |
6921 | | | 6921 | |
6922 | if (defined($gz)) { | | 6922 | if (defined($gz)) { |
6923 | $line->log_note("The .gz extension is unnecessary for manual pages."); | | 6923 | $line->log_note("The .gz extension is unnecessary for manual pages."); |
6924 | $line->explain_note( | | 6924 | $line->explain_note( |
6925 | "Whether the manual pages are installed in compressed form or not is", | | 6925 | "Whether the manual pages are installed in compressed form or not is", |
6926 | "configured by the pkgsrc user. Compression and decompression takes place", | | 6926 | "configured by the pkgsrc user. Compression and decompression takes place", |
6927 | "automatically, no matter if the .gz extension is mentioned in the PLIST", | | 6927 | "automatically, no matter if the .gz extension is mentioned in the PLIST", |
6928 | "or not."); | | 6928 | "or not."); |
6929 | } | | 6929 | } |
6930 | | | 6930 | |
6931 | } elsif ($text =~ m"^man/cat") { | | 6931 | } elsif ($text =~ m"^man/cat") { |
6932 | $line->log_warning("Invalid filename \"${text}\" for preformatted manual page."); | | 6932 | $line->log_warning("Invalid filename \"${text}\" for preformatted manual page."); |
6933 | | | 6933 | |
6934 | } elsif ($text =~ m"^man/man") { | | 6934 | } elsif ($text =~ m"^man/man") { |
6935 | $line->log_warning("Invalid filename \"${text}\" for unformatted manual page."); | | 6935 | $line->log_warning("Invalid filename \"${text}\" for unformatted manual page."); |
6936 | | | 6936 | |
6937 | } elsif ($text =~ m"^sbin/(.*)") { | | 6937 | } elsif ($text =~ m"^sbin/(.*)") { |
6938 | my ($binname) = ($1); | | 6938 | my ($binname) = ($1); |
6939 | | | 6939 | |
6940 | if (!exists($all_files->{"man/man8/${binname}.8"})) { | | 6940 | if (!exists($all_files->{"man/man8/${binname}.8"})) { |
6941 | $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}."); | | 6941 | $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}."); |
6942 | $opt_warn_extra and $line->explain_warning( | | 6942 | $opt_warn_extra and $line->explain_warning( |
6943 | "All programs that can be run directly by the user should have a manual", | | 6943 | "All programs that can be run directly by the user should have a manual", |
6944 | "page for quick reference. The programs in the sbin/ directory should have", | | 6944 | "page for quick reference. The programs in the sbin/ directory should have", |
6945 | "corresponding manual pages in section 8 (filename program.8), not in", | | 6945 | "corresponding manual pages in section 8 (filename program.8), not in", |
6946 | "section 1."); | | 6946 | "section 1."); |
6947 | } | | 6947 | } |
6948 | | | 6948 | |
6949 | } elsif ($text =~ m"^share/applications/.*\.desktop$") { | | 6949 | } elsif ($text =~ m"^share/applications/.*\.desktop$") { |
6950 | my $f = "../../sysutils/desktop-file-utils/desktopdb.mk"; | | 6950 | my $f = "../../sysutils/desktop-file-utils/desktopdb.mk"; |
6951 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { | | 6951 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { |
6952 | $line->log_warning("Packages that install a .desktop entry may .include \"$f\"."); | | 6952 | $line->log_warning("Packages that install a .desktop entry may .include \"$f\"."); |
6953 | $line->explain_warning( | | 6953 | $line->explain_warning( |
6954 | "If *.desktop files contain MimeType keys, global MIME Type registory DB", | | 6954 | "If *.desktop files contain MimeType keys, global MIME Type registory DB", |
6955 | "must be updated by desktop-file-utils.", | | 6955 | "must be updated by desktop-file-utils.", |
6956 | "Otherwise, this warning is harmless."); | | 6956 | "Otherwise, this warning is harmless."); |
6957 | } | | 6957 | } |
6958 | | | 6958 | |
6959 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor(?:$|/)") { | | 6959 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor(?:$|/)") { |
6960 | my $f = "../../graphics/hicolor-icon-theme/buildlink3.mk"; | | 6960 | my $f = "../../graphics/hicolor-icon-theme/buildlink3.mk"; |
6961 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { | | 6961 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { |
6962 | $line->log_error("Please .include \"$f\" in the Makefile"); | | 6962 | $line->log_error("Please .include \"$f\" in the Makefile"); |
6963 | $line->explain_error( | | 6963 | $line->explain_error( |
6964 | "If hicolor icon themes are installed, icon theme cache must be", | | 6964 | "If hicolor icon themes are installed, icon theme cache must be", |
6965 | "maintained. The hicolor-icon-theme package takes care of that."); | | 6965 | "maintained. The hicolor-icon-theme package takes care of that."); |
6966 | } | | 6966 | } |
6967 | | | 6967 | |
6968 | } elsif ($pkgpath ne "graphics/gnome-icon-theme" && $text =~ m"^share/icons/gnome(?:$|/)") { | | 6968 | } elsif ($pkgpath ne "graphics/gnome-icon-theme" && $text =~ m"^share/icons/gnome(?:$|/)") { |
6969 | my $f = "../../graphics/gnome-icon-theme/buildlink3.mk"; | | 6969 | my $f = "../../graphics/gnome-icon-theme/buildlink3.mk"; |
6970 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { | | 6970 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { |
6971 | $line->log_error("Please .include \"$f\""); | | 6971 | $line->log_error("Please .include \"$f\""); |
6972 | $line->explain_error( | | 6972 | $line->explain_error( |
6973 | "If Gnome icon themes are installed, icon theme cache must be maintained."); | | 6973 | "If Gnome icon themes are installed, icon theme cache must be maintained."); |
6974 | } | | 6974 | } |
6975 | } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") { | | 6975 | } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") { |
6976 | # Fine. | | 6976 | # Fine. |
6977 | | | 6977 | |
6978 | } elsif ($text =~ m"^share/doc/html/") { | | 6978 | } elsif ($text =~ m"^share/doc/html/") { |
6979 | $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead."); | | 6979 | $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead."); |
6980 | | | 6980 | |
6981 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") { | | 6981 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") { |
6982 | # Fine. | | 6982 | # Fine. |
6983 | | | 6983 | |
6984 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") { | | 6984 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") { |
6985 | # Fine. | | 6985 | # Fine. |
6986 | | | 6986 | |
6987 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") { | | 6987 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") { |
6988 | # Fine. | | 6988 | # Fine. |
6989 | | | 6989 | |
6990 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") { | | 6990 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") { |
6991 | $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); | | 6991 | $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); |
6992 | | | 6992 | |
6993 | } elsif ($text =~ m"^share/info/") { | | 6993 | } elsif ($text =~ m"^share/info/") { |
6994 | $line->log_warning("Info pages should be installed into info/, not share/info/."); | | 6994 | $line->log_warning("Info pages should be installed into info/, not share/info/."); |
6995 | $line->explain_warning( | | 6995 | $line->explain_warning( |
6996 | "To fix this, you should add INFO_FILES=yes to the package Makefile."); | | 6996 | "To fix this, you should add INFO_FILES=yes to the package Makefile."); |
6997 | | | 6997 | |
6998 | } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") { | | 6998 | } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") { |
6999 | # Fine. | | 6999 | # Fine. |
7000 | | | 7000 | |
7001 | } elsif ($text =~ m"^share/man/") { | | 7001 | } elsif ($text =~ m"^share/man/") { |
7002 | $line->log_warning("Man pages should be installed into man/, not share/man/."); | | 7002 | $line->log_warning("Man pages should be installed into man/, not share/man/."); |
7003 | | | 7003 | |
7004 | } else { | | 7004 | } else { |
7005 | $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\"."); | | 7005 | $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\"."); |
7006 | } | | 7006 | } |
7007 | | | 7007 | |
7008 | if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) { | | 7008 | if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) { |
7009 | $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found."); | | 7009 | $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found."); |
7010 | } | | 7010 | } |
7011 | | | 7011 | |
7012 | if ($text =~ m"/CVS/") { | | 7012 | if ($text =~ m"/CVS/") { |
7013 | $line->log_warning("CVS files should not be in the PLIST."); | | 7013 | $line->log_warning("CVS files should not be in the PLIST."); |
7014 | } | | 7014 | } |
7015 | if ($text =~ m"\.orig$") { | | 7015 | if ($text =~ m"\.orig$") { |
7016 | $line->log_warning(".orig files should not be in the PLIST."); | | 7016 | $line->log_warning(".orig files should not be in the PLIST."); |
7017 | } | | 7017 | } |
7018 | if ($text =~ m"/perllocal\.pod$") { | | 7018 | if ($text =~ m"/perllocal\.pod$") { |
7019 | $line->log_warning("perllocal.pod files should not be in the PLIST."); | | 7019 | $line->log_warning("perllocal.pod files should not be in the PLIST."); |
7020 | $line->explain_warning( | | 7020 | $line->explain_warning( |
7021 | "This file is handled automatically by the INSTALL/DEINSTALL scripts,", | | 7021 | "This file is handled automatically by the INSTALL/DEINSTALL scripts,", |
7022 | "since its contents changes frequently."); | | 7022 | "since its contents changes frequently."); |
7023 | } | | 7023 | } |
7024 | | | 7024 | |
7025 | if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") { | | 7025 | if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") { |
7026 | my ($basename, $ext) = ($1, $2); | | 7026 | my ($basename, $ext) = ($1, $2); |
7027 | | | 7027 | |
7028 | if (exists($all_files->{"${basename}.la"})) { | | 7028 | if (exists($all_files->{"${basename}.la"})) { |
7029 | $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . "."); | | 7029 | $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . "."); |
7030 | } | | 7030 | } |
7031 | } | | 7031 | } |
7032 | | | 7032 | |
7033 | } elsif ($text =~ m"^\$\{[\w_]+\}$") { | | 7033 | } elsif ($text =~ m"^\$\{[\w_]+\}$") { |
7034 | # A variable on its own line. | | 7034 | # A variable on its own line. |
7035 | | | 7035 | |
7036 | } else { | | 7036 | } else { |
7037 | $line->log_error("Unknown line type."); | | 7037 | $line->log_error("Unknown line type."); |
7038 | } | | 7038 | } |
7039 | } | | 7039 | } |
7040 | checklines_trailing_empty_lines($lines); | | 7040 | checklines_trailing_empty_lines($lines); |
7041 | autofix($lines); | | 7041 | autofix($lines); |
7042 | } | | 7042 | } |
7043 | | | 7043 | |
7044 | sub checkfile($) { | | 7044 | sub checkfile($) { |
7045 | my ($fname) = @_; | | 7045 | my ($fname) = @_; |
7046 | my ($st, $basename); | | 7046 | my ($st, $basename); |
7047 | | | 7047 | |
7048 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()"); | | 7048 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()"); |
7049 | | | 7049 | |
7050 | $basename = basename($fname); | | 7050 | $basename = basename($fname); |
7051 | if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") { | | 7051 | if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") { |
7052 | if ($opt_import) { | | 7052 | if ($opt_import) { |
7053 | log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package."); | | 7053 | log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package."); |
7054 | } | | 7054 | } |
7055 | return; | | 7055 | return; |
7056 | } | | 7056 | } |
7057 | | | 7057 | |
7058 | if (!($st = lstat($fname))) { | | 7058 | if (!($st = lstat($fname))) { |
7059 | log_error($fname, NO_LINE_NUMBER, "$!"); | | 7059 | log_error($fname, NO_LINE_NUMBER, "$!"); |
7060 | return; | | 7060 | return; |
7061 | } | | 7061 | } |
7062 | if (S_ISDIR($st->mode)) { | | 7062 | if (S_ISDIR($st->mode)) { |
7063 | if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") { | | 7063 | if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") { |
7064 | # Ok | | 7064 | # Ok |
| | | 7065 | } elsif ($fname =~ m"(?:^|/)files/[^/]*$") { |
| | | 7066 | # Ok |
7065 | | | 7067 | |
7066 | } elsif (!is_emptydir($fname)) { | | 7068 | } elsif (!is_emptydir($fname)) { |
7067 | log_warning($fname, NO_LINE_NUMBER, "Unknown directory name."); | | 7069 | log_warning($fname, NO_LINE_NUMBER, "Unknown directory name."); |
7068 | } | | 7070 | } |
7069 | | | 7071 | |
7070 | } elsif (S_ISLNK($st->mode)) { | | 7072 | } elsif (S_ISLNK($st->mode)) { |
7071 | if ($basename !~ m"^work") { | | 7073 | if ($basename !~ m"^work") { |
7072 | log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name."); | | 7074 | log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name."); |
7073 | } | | 7075 | } |
7074 | | | 7076 | |
7075 | } elsif (!S_ISREG($st->mode)) { | | 7077 | } elsif (!S_ISREG($st->mode)) { |
7076 | log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc."); | | 7078 | log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc."); |
7077 | | | 7079 | |
7078 | } elsif ($basename eq "ALTERNATIVES") { | | 7080 | } elsif ($basename eq "ALTERNATIVES") { |
7079 | $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname); | | 7081 | $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname); |
7080 | | | 7082 | |
7081 | } elsif ($basename eq "buildlink3.mk") { | | 7083 | } elsif ($basename eq "buildlink3.mk") { |
7082 | $opt_check_bl3 and checkfile_buildlink3_mk($fname); | | 7084 | $opt_check_bl3 and checkfile_buildlink3_mk($fname); |
7083 | | | 7085 | |
7084 | } elsif ($basename =~ m"^DESCR") { | | 7086 | } elsif ($basename =~ m"^DESCR") { |
7085 | $opt_check_DESCR and checkfile_DESCR($fname); | | 7087 | $opt_check_DESCR and checkfile_DESCR($fname); |
7086 | | | 7088 | |
7087 | } elsif ($basename =~ m"^distinfo") { | | 7089 | } elsif ($basename =~ m"^distinfo") { |
7088 | $opt_check_distinfo and checkfile_distinfo($fname); | | 7090 | $opt_check_distinfo and checkfile_distinfo($fname); |
7089 | | | 7091 | |
7090 | } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") { | | 7092 | } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") { |
7091 | $opt_check_INSTALL and checkfile_INSTALL($fname); | | 7093 | $opt_check_INSTALL and checkfile_INSTALL($fname); |
7092 | | | 7094 | |
7093 | } elsif ($basename =~ m"^MESSAGE") { | | 7095 | } elsif ($basename =~ m"^MESSAGE") { |
7094 | $opt_check_MESSAGE and checkfile_MESSAGE($fname); | | 7096 | $opt_check_MESSAGE and checkfile_MESSAGE($fname); |
7095 | | | 7097 | |
7096 | } elsif ($basename =~ m"^patch-[-A-Za-z0-9_.~+]*[A-Za-z0-9_]$") { | | 7098 | } elsif ($basename =~ m"^patch-[-A-Za-z0-9_.~+]*[A-Za-z0-9_]$") { |
7097 | $opt_check_patches and checkfile_patch($fname); | | 7099 | $opt_check_patches and checkfile_patch($fname); |
7098 | | | 7100 | |
7099 | } elsif ($fname =~ m"(?:^|/)patches/manual[^/]*$") { | | 7101 | } elsif ($fname =~ m"(?:^|/)patches/manual[^/]*$") { |
7100 | $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\"."); | | 7102 | $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\"."); |
7101 | | | 7103 | |
7102 | } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") { | | 7104 | } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") { |
7103 | log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only."); | | 7105 | log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only."); |
7104 | | | 7106 | |
7105 | } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$" and not $fname =~ m,files/, and not $fname =~ m,patches/,) { | | 7107 | } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$" and not $fname =~ m,files/, and not $fname =~ m,patches/,) { |
7106 | $opt_check_mk and checkfile_mk($fname); | | 7108 | $opt_check_mk and checkfile_mk($fname); |
7107 | | | 7109 | |
7108 | } elsif ($basename =~ m"^PLIST") { | | 7110 | } elsif ($basename =~ m"^PLIST") { |
7109 | $opt_check_PLIST and checkfile_PLIST($fname); | | 7111 | $opt_check_PLIST and checkfile_PLIST($fname); |
7110 | | | 7112 | |
7111 | } elsif ($basename eq "TODO" || $basename eq "README") { | | 7113 | } elsif ($basename eq "TODO" || $basename eq "README") { |
7112 | # Ok | | 7114 | # Ok |
7113 | | | 7115 | |
7114 | } elsif ($basename =~ m"^CHANGES-.*") { | | 7116 | } elsif ($basename =~ m"^CHANGES-.*") { |
7115 | load_doc_CHANGES($fname); | | 7117 | load_doc_CHANGES($fname); |
7116 | | | 7118 | |
7117 | } elsif (!-T $fname) { | | 7119 | } elsif (!-T $fname) { |
7118 | log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file."); | | 7120 | log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file."); |
7119 | | | 7121 | |
| | | 7122 | } elsif ($fname =~ m"(?:^|/)files/[^/]*$") { |
| | | 7123 | # Ok |
7120 | } else { | | 7124 | } else { |
7121 | log_warning($fname, NO_LINE_NUMBER, "Unexpected file found."); | | 7125 | log_warning($fname, NO_LINE_NUMBER, "Unexpected file found."); |
7122 | $opt_check_extra and checkfile_extra($fname); | | 7126 | $opt_check_extra and checkfile_extra($fname); |
7123 | } | | 7127 | } |
7124 | } | | 7128 | } |
7125 | | | 7129 | |
7126 | sub my_split($$) { | | 7130 | sub my_split($$) { |
7127 | my ($delimiter, $s) = @_; | | 7131 | my ($delimiter, $s) = @_; |
7128 | my ($pos, $next, @result); | | 7132 | my ($pos, $next, @result); |
7129 | | | 7133 | |
7130 | $pos = 0; | | 7134 | $pos = 0; |
7131 | for ($pos = 0; $pos != -1; $pos = $next) { | | 7135 | for ($pos = 0; $pos != -1; $pos = $next) { |
7132 | $next = index($s, $delimiter, $pos); | | 7136 | $next = index($s, $delimiter, $pos); |
7133 | push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos)); | | 7137 | push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos)); |
7134 | if ($next != -1) { | | 7138 | if ($next != -1) { |
7135 | $next += length($delimiter); | | 7139 | $next += length($delimiter); |
7136 | } | | 7140 | } |
7137 | } | | 7141 | } |
7138 | return @result; | | 7142 | return @result; |
7139 | } | | 7143 | } |
7140 | | | 7144 | |
7141 | # Checks that the files in the directory are in sync with CVS's status. | | 7145 | # Checks that the files in the directory are in sync with CVS's status. |
7142 | # | | 7146 | # |
7143 | sub checkdir_CVS($) { | | 7147 | sub checkdir_CVS($) { |
7144 | my ($fname) = @_; | | 7148 | my ($fname) = @_; |
7145 | | | 7149 | |
7146 | my $cvs_entries = load_file("$fname/CVS/Entries"); | | 7150 | my $cvs_entries = load_file("$fname/CVS/Entries"); |
7147 | my $cvs_entries_log = load_file("$fname/CVS/Entries.Log"); | | 7151 | my $cvs_entries_log = load_file("$fname/CVS/Entries.Log"); |
7148 | return unless $cvs_entries; | | 7152 | return unless $cvs_entries; |
7149 | | | 7153 | |
7150 | foreach my $line (@$cvs_entries) { | | 7154 | foreach my $line (@$cvs_entries) { |
7151 | my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text); | | 7155 | my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text); |
7152 | next if ($type eq "D" && !defined($fname)); | | 7156 | next if ($type eq "D" && !defined($fname)); |
7153 | assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text); | | 7157 | assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text); |
7154 | assert(defined($tag), "Unknown line format: " . $line->text); | | 7158 | assert(defined($tag), "Unknown line format: " . $line->text); |
7155 | assert(defined($keyword_mode), "Unknown line format: " . $line->text); | | 7159 | assert(defined($keyword_mode), "Unknown line format: " . $line->text); |
7156 | assert(!defined($undef), "Unknown line format: " . $line->text); | | 7160 | assert(!defined($undef), "Unknown line format: " . $line->text); |
7157 | } | | 7161 | } |
7158 | } | | 7162 | } |
7159 | | | 7163 | |
7160 | # | | 7164 | # |
7161 | # Procedures to check a directory including the files in it. | | 7165 | # Procedures to check a directory including the files in it. |
7162 | # | | 7166 | # |
7163 | | | 7167 | |
7164 | sub checkdir_root() { | | 7168 | sub checkdir_root() { |
7165 | my ($fname) = "${current_dir}/Makefile"; | | 7169 | my ($fname) = "${current_dir}/Makefile"; |
7166 | my ($lines, $prev_subdir, @subdirs); | | 7170 | my ($lines, $prev_subdir, @subdirs); |
7167 | | | 7171 | |
7168 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()"); | | 7172 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()"); |
7169 | | | 7173 | |
7170 | if (!($lines = load_lines($fname, true))) { | | 7174 | if (!($lines = load_lines($fname, true))) { |
7171 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 7175 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
7172 | return; | | 7176 | return; |
7173 | } | | 7177 | } |
7174 | | | 7178 | |
7175 | parselines_mk($lines); | | 7179 | parselines_mk($lines); |
7176 | if (0 <= $#{$lines}) { | | 7180 | if (0 <= $#{$lines}) { |
7177 | checkline_rcsid_regex($lines->[0], qr"#\s+", "# "); | | 7181 | checkline_rcsid_regex($lines->[0], qr"#\s+", "# "); |
7178 | } | | 7182 | } |
7179 | | | 7183 | |
7180 | foreach my $line (@{$lines}) { | | 7184 | foreach my $line (@{$lines}) { |
7181 | if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { | | 7185 | if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { |
7182 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); | | 7186 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); |
7183 | | | 7187 | |
7184 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { | | 7188 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { |
7185 | $line->log_warning("${subdir} commented out without giving a reason."); | | 7189 | $line->log_warning("${subdir} commented out without giving a reason."); |
7186 | } | | 7190 | } |
7187 | | | 7191 | |
7188 | if ($indentation ne "\t") { | | 7192 | if ($indentation ne "\t") { |
7189 | $line->log_warning("Indentation should be a single tab character."); | | 7193 | $line->log_warning("Indentation should be a single tab character."); |
7190 | } | | 7194 | } |
7191 | | | 7195 | |
7192 | if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") { | | 7196 | if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") { |
7193 | next; | | 7197 | next; |
7194 | } | | 7198 | } |
7195 | | | 7199 | |
7196 | if (!defined($prev_subdir) || $subdir gt $prev_subdir) { | | 7200 | if (!defined($prev_subdir) || $subdir gt $prev_subdir) { |
7197 | # correctly ordered | | 7201 | # correctly ordered |
7198 | } elsif ($subdir eq $prev_subdir) { | | 7202 | } elsif ($subdir eq $prev_subdir) { |
7199 | $line->log_error("${subdir} must only appear once."); | | 7203 | $line->log_error("${subdir} must only appear once."); |
7200 | } elsif ($prev_subdir eq "x11" && $subdir eq "archivers") { | | 7204 | } elsif ($prev_subdir eq "x11" && $subdir eq "archivers") { |
7201 | # ignore that one, since it is documented in the top-level Makefile | | 7205 | # ignore that one, since it is documented in the top-level Makefile |
7202 | } else { | | 7206 | } else { |
7203 | $line->log_warning("${subdir} should come before ${prev_subdir}."); | | 7207 | $line->log_warning("${subdir} should come before ${prev_subdir}."); |
7204 | } | | 7208 | } |
7205 | | | 7209 | |
7206 | $prev_subdir = $subdir; | | 7210 | $prev_subdir = $subdir; |
7207 | | | 7211 | |
7208 | if ($comment_flag eq "") { | | 7212 | if ($comment_flag eq "") { |
7209 | push(@subdirs, "${current_dir}/${subdir}"); | | 7213 | push(@subdirs, "${current_dir}/${subdir}"); |
7210 | } | | 7214 | } |
7211 | } | | 7215 | } |
7212 | } | | 7216 | } |
7213 | | | 7217 | |
7214 | checklines_mk($lines); | | 7218 | checklines_mk($lines); |
7215 | | | 7219 | |
7216 | if ($opt_recursive) { | | 7220 | if ($opt_recursive) { |
7217 | $ipc_checking_root_recursively = true; | | 7221 | $ipc_checking_root_recursively = true; |
7218 | push(@todo_items, @subdirs); | | 7222 | push(@todo_items, @subdirs); |
7219 | } | | 7223 | } |
7220 | } | | 7224 | } |
7221 | | | 7225 | |
7222 | sub checkdir_category() { | | 7226 | sub checkdir_category() { |
7223 | my $fname = "${current_dir}/Makefile"; | | 7227 | my $fname = "${current_dir}/Makefile"; |
7224 | my ($lines, $lineno); | | 7228 | my ($lines, $lineno); |
7225 | | | 7229 | |
7226 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()"); | | 7230 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()"); |
7227 | | | 7231 | |
7228 | if (!($lines = load_lines($fname, true))) { | | 7232 | if (!($lines = load_lines($fname, true))) { |
7229 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 7233 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
7230 | return; | | 7234 | return; |
7231 | } | | 7235 | } |
7232 | parselines_mk($lines); | | 7236 | parselines_mk($lines); |
7233 | | | 7237 | |
7234 | $lineno = 0; | | 7238 | $lineno = 0; |
7235 | | | 7239 | |
7236 | # The first line must contain the RCS Id | | 7240 | # The first line must contain the RCS Id |
7237 | if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) { | | 7241 | if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) { |
7238 | $lineno++; | | 7242 | $lineno++; |
7239 | } | | 7243 | } |
7240 | | | 7244 | |
7241 | # Then, arbitrary comments may follow | | 7245 | # Then, arbitrary comments may follow |
7242 | while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") { | | 7246 | while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") { |
7243 | $lineno++; | | 7247 | $lineno++; |
7244 | } | | 7248 | } |
7245 | | | 7249 | |
7246 | # Then we need an empty line | | 7250 | # Then we need an empty line |
7247 | expect_empty_line($lines, \$lineno); | | 7251 | expect_empty_line($lines, \$lineno); |
7248 | | | 7252 | |
7249 | # Then comes the COMMENT line | | 7253 | # Then comes the COMMENT line |
7250 | if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") { | | 7254 | if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") { |
7251 | my ($comment) = ($1); | | 7255 | my ($comment) = ($1); |
7252 | | | 7256 | |
7253 | checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]"); | | 7257 | checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]"); |
7254 | $lineno++; | | 7258 | $lineno++; |
7255 | } else { | | 7259 | } else { |
7256 | $lines->[$lineno]->log_error("COMMENT= line expected."); | | 7260 | $lines->[$lineno]->log_error("COMMENT= line expected."); |
7257 | } | | 7261 | } |
7258 | | | 7262 | |
7259 | # Then we need an empty line | | 7263 | # Then we need an empty line |
7260 | expect_empty_line($lines, \$lineno); | | 7264 | expect_empty_line($lines, \$lineno); |
7261 | | | 7265 | |
7262 | # And now to the most complicated part of the category Makefiles, | | 7266 | # And now to the most complicated part of the category Makefiles, |
7263 | # the (hopefully) sorted list of SUBDIRs. The first step is to | | 7267 | # the (hopefully) sorted list of SUBDIRs. The first step is to |
7264 | # collect the SUBDIRs in the Makefile and in the file system. | | 7268 | # collect the SUBDIRs in the Makefile and in the file system. |
7265 | | | 7269 | |
7266 | my (@f_subdirs, @m_subdirs); | | 7270 | my (@f_subdirs, @m_subdirs); |
7267 | | | 7271 | |
7268 | @f_subdirs = sort(get_subdirs($current_dir)); | | 7272 | @f_subdirs = sort(get_subdirs($current_dir)); |
7269 | | | 7273 | |
7270 | my $prev_subdir = undef; | | 7274 | my $prev_subdir = undef; |
7271 | while ($lineno <= $#{$lines}) { | | 7275 | while ($lineno <= $#{$lines}) { |
7272 | my $line = $lines->[$lineno]; | | 7276 | my $line = $lines->[$lineno]; |
7273 | | | 7277 | |
7274 | if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { | | 7278 | if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { |
7275 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); | | 7279 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); |
7276 | | | 7280 | |
7277 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { | | 7281 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { |
7278 | $line->log_warning("${subdir} commented out without giving a reason."); | | 7282 | $line->log_warning("${subdir} commented out without giving a reason."); |
7279 | } | | 7283 | } |
7280 | | | 7284 | |
7281 | if ($indentation ne "\t") { | | 7285 | if ($indentation ne "\t") { |
7282 | $line->log_warning("Indentation should be a single tab character."); | | 7286 | $line->log_warning("Indentation should be a single tab character."); |
7283 | } | | 7287 | } |
7284 | | | 7288 | |
7285 | if (defined($prev_subdir) && $subdir eq $prev_subdir) { | | 7289 | if (defined($prev_subdir) && $subdir eq $prev_subdir) { |
7286 | $line->log_error("${subdir} must only appear once."); | | 7290 | $line->log_error("${subdir} must only appear once."); |
7287 | } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { | | 7291 | } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { |
7288 | $line->log_warning("${subdir} should come before ${prev_subdir}."); | | 7292 | $line->log_warning("${subdir} should come before ${prev_subdir}."); |
7289 | } else { | | 7293 | } else { |
7290 | # correctly ordered | | 7294 | # correctly ordered |
7291 | } | | 7295 | } |
7292 | | | 7296 | |
7293 | push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]); | | 7297 | push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]); |
7294 | $prev_subdir = $subdir; | | 7298 | $prev_subdir = $subdir; |
7295 | $lineno++; | | 7299 | $lineno++; |
7296 | | | 7300 | |
7297 | } else { | | 7301 | } else { |
7298 | if ($line->text ne "") { | | 7302 | if ($line->text ne "") { |
7299 | $line->log_error("SUBDIR+= line or empty line expected."); | | 7303 | $line->log_error("SUBDIR+= line or empty line expected."); |
7300 | } | | 7304 | } |
7301 | last; | | 7305 | last; |
7302 | } | | 7306 | } |
7303 | } | | 7307 | } |
7304 | | | 7308 | |
7305 | # To prevent unnecessary warnings about subdirectories that are | | 7309 | # To prevent unnecessary warnings about subdirectories that are |
7306 | # in one list, but not in the other, we generate the sets of | | 7310 | # in one list, but not in the other, we generate the sets of |
7307 | # subdirs of each list. | | 7311 | # subdirs of each list. |
7308 | my (%f_check, %m_check); | | 7312 | my (%f_check, %m_check); |
7309 | foreach my $f (@f_subdirs) { $f_check{$f} = true; } | | 7313 | foreach my $f (@f_subdirs) { $f_check{$f} = true; } |
7310 | foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; } | | 7314 | foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; } |
7311 | | | 7315 | |
7312 | my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef); | | 7316 | my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef); |
7313 | my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef); | | 7317 | my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef); |
7314 | my ($line, $m_recurse); | | 7318 | my ($line, $m_recurse); |
7315 | my (@subdirs); | | 7319 | my (@subdirs); |
7316 | | | 7320 | |
7317 | while (!($m_atend && $f_atend)) { | | 7321 | while (!($m_atend && $f_atend)) { |
7318 | | | 7322 | |
7319 | if (!$m_atend && $m_neednext) { | | 7323 | if (!$m_atend && $m_neednext) { |
7320 | $m_neednext = false; | | 7324 | $m_neednext = false; |
7321 | if ($m_index > $#m_subdirs) { | | 7325 | if ($m_index > $#m_subdirs) { |
7322 | $m_atend = true; | | 7326 | $m_atend = true; |
7323 | $line = $lines->[$lineno]; | | 7327 | $line = $lines->[$lineno]; |
7324 | next; | | 7328 | next; |
7325 | } else { | | 7329 | } else { |
7326 | $m_current = $m_subdirs[$m_index]->[0]; | | 7330 | $m_current = $m_subdirs[$m_index]->[0]; |
7327 | $line = $m_subdirs[$m_index]->[1]; | | 7331 | $line = $m_subdirs[$m_index]->[1]; |
7328 | $m_recurse = $m_subdirs[$m_index]->[2]; | | 7332 | $m_recurse = $m_subdirs[$m_index]->[2]; |
7329 | $m_index++; | | 7333 | $m_index++; |
7330 | } | | 7334 | } |
7331 | } | | 7335 | } |
7332 | | | 7336 | |
7333 | if (!$f_atend && $f_neednext) { | | 7337 | if (!$f_atend && $f_neednext) { |
7334 | $f_neednext = false; | | 7338 | $f_neednext = false; |
7335 | if ($f_index > $#f_subdirs) { | | 7339 | if ($f_index > $#f_subdirs) { |
7336 | $f_atend = true; | | 7340 | $f_atend = true; |
7337 | next; | | 7341 | next; |
7338 | } else { | | 7342 | } else { |
7339 | $f_current = $f_subdirs[$f_index++]; | | 7343 | $f_current = $f_subdirs[$f_index++]; |
7340 | } | | 7344 | } |
7341 | } | | 7345 | } |
7342 | | | 7346 | |
7343 | if (!$f_atend && ($m_atend || $f_current lt $m_current)) { | | 7347 | if (!$f_atend && ($m_atend || $f_current lt $m_current)) { |
7344 | if (!exists($m_check{$f_current})) { | | 7348 | if (!exists($m_check{$f_current})) { |
7345 | $line->log_error("${f_current} exists in the file system, but not in the Makefile."); | | 7349 | $line->log_error("${f_current} exists in the file system, but not in the Makefile."); |
7346 | $line->append_before("SUBDIR+=\t${f_current}"); | | 7350 | $line->append_before("SUBDIR+=\t${f_current}"); |
7347 | } | | 7351 | } |
7348 | $f_neednext = true; | | 7352 | $f_neednext = true; |
7349 | | | 7353 | |
7350 | } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) { | | 7354 | } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) { |
7351 | if (!exists($f_check{$m_current})) { | | 7355 | if (!exists($f_check{$m_current})) { |
7352 | $line->log_error("${m_current} exists in the Makefile, but not in the file system."); | | 7356 | $line->log_error("${m_current} exists in the Makefile, but not in the file system."); |
7353 | $line->delete(); | | 7357 | $line->delete(); |
7354 | } | | 7358 | } |
7355 | $m_neednext = true; | | 7359 | $m_neednext = true; |
7356 | | | 7360 | |
7357 | } else { # $f_current eq $m_current | | 7361 | } else { # $f_current eq $m_current |
7358 | $f_neednext = true; | | 7362 | $f_neednext = true; |
7359 | $m_neednext = true; | | 7363 | $m_neednext = true; |
7360 | if ($m_recurse) { | | 7364 | if ($m_recurse) { |
7361 | push(@subdirs, "${current_dir}/${m_current}"); | | 7365 | push(@subdirs, "${current_dir}/${m_current}"); |
7362 | } | | 7366 | } |
7363 | } | | 7367 | } |
7364 | } | | 7368 | } |
7365 | | | 7369 | |
7366 | # the wip category Makefile may have its own targets for generating | | 7370 | # the wip category Makefile may have its own targets for generating |
7367 | # indexes and READMEs. Just skip them. | | 7371 | # indexes and READMEs. Just skip them. |
7368 | if ($is_wip) { | | 7372 | if ($is_wip) { |
7369 | while ($lineno <= $#{$lines} - 2) { | | 7373 | while ($lineno <= $#{$lines} - 2) { |
7370 | $lineno++; | | 7374 | $lineno++; |
7371 | } | | 7375 | } |
7372 | } | | 7376 | } |
7373 | | | 7377 | |
7374 | expect_empty_line($lines, \$lineno); | | 7378 | expect_empty_line($lines, \$lineno); |
7375 | | | 7379 | |
7376 | # And, last but not least, the .include line | | 7380 | # And, last but not least, the .include line |
7377 | my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\""; | | 7381 | my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\""; |
7378 | expect($lines, \$lineno, qr"\Q$final_line\E") | | 7382 | expect($lines, \$lineno, qr"\Q$final_line\E") |
7379 | || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\""); | | 7383 | || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\""); |
7380 | | | 7384 | |
7381 | if ($lineno <= $#{$lines}) { | | 7385 | if ($lineno <= $#{$lines}) { |
7382 | $lines->[$lineno]->log_error("The file should end here."); | | 7386 | $lines->[$lineno]->log_error("The file should end here."); |
7383 | } | | 7387 | } |
7384 | | | 7388 | |
7385 | checklines_mk($lines); | | 7389 | checklines_mk($lines); |
7386 | | | 7390 | |
7387 | autofix($lines); | | 7391 | autofix($lines); |
7388 | | | 7392 | |
7389 | if ($opt_recursive) { | | 7393 | if ($opt_recursive) { |
7390 | unshift(@todo_items, @subdirs); | | 7394 | unshift(@todo_items, @subdirs); |
7391 | } | | 7395 | } |
7392 | } | | 7396 | } |
7393 | | | 7397 | |
7394 | sub checkdir_package() { | | 7398 | sub checkdir_package() { |
7395 | my ($lines, $have_distinfo, $have_patches); | | 7399 | my ($lines, $have_distinfo, $have_patches); |
7396 | | | 7400 | |
7397 | # Initialize global variables | | 7401 | # Initialize global variables |
7398 | $pkgdir = undef; | | 7402 | $pkgdir = undef; |
7399 | $filesdir = "files"; | | 7403 | $filesdir = "files"; |
7400 | $patchdir = "patches"; | | 7404 | $patchdir = "patches"; |
7401 | $distinfo_file = "distinfo"; | | 7405 | $distinfo_file = "distinfo"; |
7402 | $effective_pkgname = undef; | | 7406 | $effective_pkgname = undef; |
7403 | $effective_pkgbase = undef; | | 7407 | $effective_pkgbase = undef; |
7404 | $effective_pkgversion = undef; | | 7408 | $effective_pkgversion = undef; |
7405 | $effective_pkgname_line = undef; | | 7409 | $effective_pkgname_line = undef; |
7406 | $seen_bsd_prefs_mk = false; | | 7410 | $seen_bsd_prefs_mk = false; |
7407 | $pkgctx_vardef = {%{get_userdefined_variables()}}; | | 7411 | $pkgctx_vardef = {%{get_userdefined_variables()}}; |
7408 | $pkgctx_varuse = {}; | | 7412 | $pkgctx_varuse = {}; |
7409 | $pkgctx_bl3 = {}; | | 7413 | $pkgctx_bl3 = {}; |
7410 | $pkgctx_plist_subst_cond = {}; | | 7414 | $pkgctx_plist_subst_cond = {}; |
7411 | $pkgctx_included = {}; | | 7415 | $pkgctx_included = {}; |
7412 | $seen_Makefile_common = false; | | 7416 | $seen_Makefile_common = false; |
7413 | | | 7417 | |
7414 | # we need to handle the Makefile first to get some variables | | 7418 | # we need to handle the Makefile first to get some variables |
7415 | if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) { | | 7419 | if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) { |
7416 | log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read."); | | 7420 | log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read."); |
7417 | goto cleanup; | | 7421 | goto cleanup; |
7418 | } | | 7422 | } |
7419 | | | 7423 | |
7420 | my @files = <${current_dir}/*>; | | 7424 | my @files = <${current_dir}/*>; |
7421 | if ($pkgdir ne ".") { | | 7425 | if ($pkgdir ne ".") { |
7422 | push(@files, <${current_dir}/${pkgdir}/*>); | | 7426 | push(@files, <${current_dir}/${pkgdir}/*>); |
7423 | } | | 7427 | } |
7424 | if ($opt_check_extra) { | | 7428 | if ($opt_check_extra) { |
7425 | push(@files, <${current_dir}/${filesdir}/*>); | | 7429 | push(@files, <${current_dir}/${filesdir}/*>); |
7426 | } | | 7430 | } |
7427 | push(@files, <${current_dir}/${patchdir}/*>); | | 7431 | push(@files, <${current_dir}/${patchdir}/*>); |
7428 | if ($distinfo_file !~ m"^(?:\./)?distinfo$") { | | 7432 | if ($distinfo_file !~ m"^(?:\./)?distinfo$") { |
7429 | push(@files, "${current_dir}/${distinfo_file}"); | | 7433 | push(@files, "${current_dir}/${distinfo_file}"); |
7430 | } | | 7434 | } |
7431 | $have_distinfo = false; | | 7435 | $have_distinfo = false; |
7432 | $have_patches = false; | | 7436 | $have_patches = false; |
7433 | | | 7437 | |
7434 | # Determine the used variables before checking any of the | | 7438 | # Determine the used variables before checking any of the |
7435 | # Makefile fragments. | | 7439 | # Makefile fragments. |
7436 | foreach my $fname (@files) { | | 7440 | foreach my $fname (@files) { |
7437 | if (($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$") | | 7441 | if (($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$") |
7438 | && (not $fname =~ m"patch-") | | 7442 | && (not $fname =~ m"patch-") |
7439 | && (not $fname =~ m"${pkgdir}/") | | 7443 | && (not $fname =~ m"${pkgdir}/") |
7440 | && (not $fname =~ m"${filesdir}/") | | 7444 | && (not $fname =~ m"${filesdir}/") |
7441 | && (defined(my $lines = load_lines($fname, true)))) { | | 7445 | && (defined(my $lines = load_lines($fname, true)))) { |
7442 | parselines_mk($lines); | | 7446 | parselines_mk($lines); |
7443 | determine_used_variables($lines); | | 7447 | determine_used_variables($lines); |
7444 | } | | 7448 | } |
7445 | } | | 7449 | } |
7446 | | | 7450 | |
7447 | foreach my $fname (@files) { | | 7451 | foreach my $fname (@files) { |
7448 | if ($fname eq "${current_dir}/Makefile") { | | 7452 | if ($fname eq "${current_dir}/Makefile") { |
7449 | $opt_check_Makefile and checkfile_package_Makefile($fname, $lines); | | 7453 | $opt_check_Makefile and checkfile_package_Makefile($fname, $lines); |
7450 | } else { | | 7454 | } else { |
7451 | checkfile($fname); | | 7455 | checkfile($fname); |
7452 | } | | 7456 | } |
7453 | if ($fname =~ m"/patches/patch-*$") { | | 7457 | if ($fname =~ m"/patches/patch-*$") { |
7454 | $have_patches = true; | | 7458 | $have_patches = true; |
7455 | } elsif ($fname =~ m"/distinfo$") { | | 7459 | } elsif ($fname =~ m"/distinfo$") { |
7456 | $have_distinfo = true; | | 7460 | $have_distinfo = true; |
7457 | } | | 7461 | } |
7458 | } | | 7462 | } |
7459 | | | 7463 | |
7460 | if ($opt_check_distinfo && $opt_check_patches) { | | 7464 | if ($opt_check_distinfo && $opt_check_patches) { |
7461 | if ($have_patches && ! $have_distinfo) { | | 7465 | if ($have_patches && ! $have_distinfo) { |
7462 | log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'."); | | 7466 | log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'."); |
7463 | } | | 7467 | } |
7464 | } | | 7468 | } |
7465 | | | 7469 | |
7466 | if (!is_emptydir("${current_dir}/scripts")) { | | 7470 | if (!is_emptydir("${current_dir}/scripts")) { |
7467 | log_warning("${current_dir}/scripts", NO_LINE_NUMBER, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile."); | | 7471 | log_warning("${current_dir}/scripts", NO_LINE_NUMBER, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile."); |
7468 | } | | 7472 | } |
7469 | | | 7473 | |
7470 | cleanup: | | 7474 | cleanup: |
7471 | # Clean up global variables. | | 7475 | # Clean up global variables. |
7472 | $pkgdir = undef; | | 7476 | $pkgdir = undef; |
7473 | $filesdir = undef; | | 7477 | $filesdir = undef; |
7474 | $patchdir = undef; | | 7478 | $patchdir = undef; |
7475 | $distinfo_file = undef; | | 7479 | $distinfo_file = undef; |
7476 | $effective_pkgname = undef; | | 7480 | $effective_pkgname = undef; |
7477 | $effective_pkgbase = undef; | | 7481 | $effective_pkgbase = undef; |
7478 | $effective_pkgversion = undef; | | 7482 | $effective_pkgversion = undef; |
7479 | $effective_pkgname_line = undef; | | 7483 | $effective_pkgname_line = undef; |
7480 | $seen_bsd_prefs_mk = undef; | | 7484 | $seen_bsd_prefs_mk = undef; |
7481 | $pkgctx_vardef = undef; | | 7485 | $pkgctx_vardef = undef; |
7482 | $pkgctx_varuse = undef; | | 7486 | $pkgctx_varuse = undef; |
7483 | $pkgctx_bl3 = undef; | | 7487 | $pkgctx_bl3 = undef; |
7484 | $pkgctx_plist_subst_cond = undef; | | 7488 | $pkgctx_plist_subst_cond = undef; |
7485 | $pkgctx_included = undef; | | 7489 | $pkgctx_included = undef; |
7486 | $seen_Makefile_common = undef; | | 7490 | $seen_Makefile_common = undef; |
7487 | } | | 7491 | } |
7488 | | | 7492 | |
7489 | # | | 7493 | # |
7490 | # Selecting the proper checking procedures for a directory entry. | | 7494 | # Selecting the proper checking procedures for a directory entry. |
7491 | # | | 7495 | # |
7492 | | | 7496 | |
7493 | sub checkitem($) { | | 7497 | sub checkitem($) { |
7494 | my ($item) = @_; | | 7498 | my ($item) = @_; |
7495 | my ($st, $is_dir, $is_reg); | | 7499 | my ($st, $is_dir, $is_reg); |
7496 | | | 7500 | |
7497 | if (!($st = lstat($item))) { | | 7501 | if (!($st = lstat($item))) { |
7498 | log_error($item, NO_LINE_NUMBER, "Does not exist."); | | 7502 | log_error($item, NO_LINE_NUMBER, "Does not exist."); |
7499 | return; | | 7503 | return; |
7500 | } | | 7504 | } |
7501 | | | 7505 | |
7502 | $is_dir = S_ISDIR($st->mode); | | 7506 | $is_dir = S_ISDIR($st->mode); |
7503 | $is_reg = S_ISREG($st->mode); | | 7507 | $is_reg = S_ISREG($st->mode); |
7504 | if (!$is_reg && !$is_dir) { | | 7508 | if (!$is_reg && !$is_dir) { |
7505 | log_error($item, NO_LINE_NUMBER, "Must be a file or directory."); | | 7509 | log_error($item, NO_LINE_NUMBER, "Must be a file or directory."); |
7506 | return; | | 7510 | return; |
7507 | } | | 7511 | } |
7508 | | | 7512 | |
7509 | $current_dir = $is_dir ? $item : dirname($item); | | 7513 | $current_dir = $is_dir ? $item : dirname($item); |
7510 | my $abs_current_dir = Cwd::abs_path($current_dir); | | 7514 | my $abs_current_dir = Cwd::abs_path($current_dir); |
7511 | $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)"); | | 7515 | $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)"); |
7512 | $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)"); | | 7516 | $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)"); |
7513 | | | 7517 | |
7514 | # Determine the root directory of pkgsrc. By only overwriting | | 7518 | # Determine the root directory of pkgsrc. By only overwriting |
7515 | # the global variable $cwd_pkgsrcdir when we are checking inside | | 7519 | # the global variable $cwd_pkgsrcdir when we are checking inside |
7516 | # a pkgsrc tree, the user can specify a tree with the | | 7520 | # a pkgsrc tree, the user can specify a tree with the |
7517 | # --pkgsrcdir option and then check files (but not directories) | | 7521 | # --pkgsrcdir option and then check files (but not directories) |
7518 | # outside of any pkgsrc tree. | | 7522 | # outside of any pkgsrc tree. |
7519 | $cur_pkgsrcdir = undef; | | 7523 | $cur_pkgsrcdir = undef; |
7520 | $pkgpath = undef; | | 7524 | $pkgpath = undef; |
7521 | foreach my $d (".", "..", "../..", "../../..") { | | 7525 | foreach my $d (".", "..", "../..", "../../..") { |
7522 | if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") { | | 7526 | if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") { |
7523 | $cur_pkgsrcdir = $d; | | 7527 | $cur_pkgsrcdir = $d; |
7524 | $pkgpath = relative_path("${current_dir}/${d}", $current_dir); | | 7528 | $pkgpath = relative_path("${current_dir}/${d}", $current_dir); |
7525 | } | | 7529 | } |
7526 | } | | 7530 | } |
7527 | if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) { | | 7531 | if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) { |
7528 | $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}"; | | 7532 | $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}"; |
7529 | } | | 7533 | } |
7530 | | | 7534 | |
7531 | if (!defined($cwd_pkgsrcdir)) { | | 7535 | if (!defined($cwd_pkgsrcdir)) { |
7532 | log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory."); | | 7536 | log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory."); |
7533 | return; | | 7537 | return; |
7534 | } | | 7538 | } |
7535 | | | 7539 | |
7536 | check_pkglint_version(); # (needs $cwd_pkgsrcdir) | | 7540 | check_pkglint_version(); # (needs $cwd_pkgsrcdir) |
7537 | | | 7541 | |
7538 | return if $is_dir && is_emptydir($item); | | 7542 | return if $is_dir && is_emptydir($item); |
7539 | | | 7543 | |
7540 | if ($is_dir) { | | 7544 | if ($is_dir) { |
7541 | checkdir_CVS($item); | | 7545 | checkdir_CVS($item); |
7542 | } | | 7546 | } |
7543 | | | 7547 | |
7544 | if ($is_reg) { | | 7548 | if ($is_reg) { |
7545 | checkfile($item); | | 7549 | checkfile($item); |
7546 | | | 7550 | |
7547 | } elsif (!defined($cur_pkgsrcdir)) { | | 7551 | } elsif (!defined($cur_pkgsrcdir)) { |
7548 | log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree."); | | 7552 | log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree."); |
7549 | | | 7553 | |
7550 | } elsif ($cur_pkgsrcdir eq "../..") { | | 7554 | } elsif ($cur_pkgsrcdir eq "../..") { |
7551 | checkdir_package(); | | 7555 | checkdir_package(); |
7552 | | | 7556 | |
7553 | } elsif ($cur_pkgsrcdir eq "..") { | | 7557 | } elsif ($cur_pkgsrcdir eq "..") { |
7554 | checkdir_category(); | | 7558 | checkdir_category(); |
7555 | | | 7559 | |
7556 | } elsif ($cur_pkgsrcdir eq ".") { | | 7560 | } elsif ($cur_pkgsrcdir eq ".") { |
7557 | checkdir_root(); | | 7561 | checkdir_root(); |
7558 | | | 7562 | |
7559 | } else { | | 7563 | } else { |
7560 | log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory."); | | 7564 | log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory."); |
7561 | } | | 7565 | } |
7562 | } | | 7566 | } |
7563 | | | 7567 | |
7564 | # | | 7568 | # |
7565 | # The main program | | 7569 | # The main program |
7566 | # | | 7570 | # |
7567 | | | 7571 | |
7568 | sub main() { | | 7572 | sub main() { |
7569 | | | 7573 | |
7570 | $| = true; | | 7574 | $| = true; |
7571 | parse_command_line(); | | 7575 | parse_command_line(); |
7572 | | | 7576 | |
7573 | @todo_items = (@ARGV != 0) ? @ARGV : ("."); | | 7577 | @todo_items = (@ARGV != 0) ? @ARGV : ("."); |
7574 | while (@todo_items != 0) { | | 7578 | while (@todo_items != 0) { |
7575 | checkitem(shift(@todo_items)); | | 7579 | checkitem(shift(@todo_items)); |
7576 | } | | 7580 | } |
7577 | | | 7581 | |
7578 | if ($ipc_checking_root_recursively) { | | 7582 | if ($ipc_checking_root_recursively) { |
7579 | check_unused_licenses(); | | 7583 | check_unused_licenses(); |
7580 | } | | 7584 | } |
7581 | | | 7585 | |
7582 | PkgLint::Logging::print_summary_and_exit($opt_quiet); | | 7586 | PkgLint::Logging::print_summary_and_exit($opt_quiet); |
7583 | } | | 7587 | } |
7584 | | | 7588 | |
7585 | main() unless caller(); | | 7589 | main() unless caller(); |