← Index
NYTProf Performance Profile   « line view »
For Makefile.PL
  Run on Sun Mar 1 16:04:44 2015
Reported on Sun Mar 1 16:09:02 2015

FilenameC:/tmp64ng/perl/lib/CPAN/Meta/Validator.pm
StatementsExecuted 6344 statements in 0s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1110s0sCPAN::Meta::Converter::::BEGIN@1CPAN::Meta::Converter::BEGIN@1
1110s0sCPAN::Meta::Converter::::BEGIN@2CPAN::Meta::Converter::BEGIN@2
1110s0sCPAN::Meta::Converter::::BEGIN@3CPAN::Meta::Converter::BEGIN@3
287910s0sCPAN::Meta::Validator::::CORE:matchCPAN::Meta::Validator::CORE:match (opcode)
3310s0sCPAN::Meta::Validator::::_errorCPAN::Meta::Validator::_error
25110s0sCPAN::Meta::Validator::::_uri_splitCPAN::Meta::Validator::_uri_split
1110s0sCPAN::Meta::Validator::::anythingCPAN::Meta::Validator::anything
23110s0sCPAN::Meta::Validator::::booleanCPAN::Meta::Validator::boolean
56110s0sCPAN::Meta::Validator::::check_listCPAN::Meta::Validator::check_list
179310s0sCPAN::Meta::Validator::::check_mapCPAN::Meta::Validator::check_map (recurses: max depth 3, inclusive time 0s)
0000s0sCPAN::Meta::Validator::::custom_1CPAN::Meta::Validator::custom_1
1110s0sCPAN::Meta::Validator::::custom_2CPAN::Meta::Validator::custom_2
24220s0sCPAN::Meta::Validator::::errorsCPAN::Meta::Validator::errors
42110s0sCPAN::Meta::Validator::::exversionCPAN::Meta::Validator::exversion
0000s0sCPAN::Meta::Validator::::fileCPAN::Meta::Validator::file
0000s0sCPAN::Meta::Validator::::headerCPAN::Meta::Validator::header
0000s0sCPAN::Meta::Validator::::identifierCPAN::Meta::Validator::identifier
23420s0sCPAN::Meta::Validator::::is_validCPAN::Meta::Validator::is_valid
22210s0sCPAN::Meta::Validator::::licenseCPAN::Meta::Validator::license
42110s0sCPAN::Meta::Validator::::moduleCPAN::Meta::Validator::module
29520s0sCPAN::Meta::Validator::::newCPAN::Meta::Validator::new
24110s0sCPAN::Meta::Validator::::phaseCPAN::Meta::Validator::phase
24110s0sCPAN::Meta::Validator::::relationCPAN::Meta::Validator::relation
9110s0sCPAN::Meta::Validator::::release_statusCPAN::Meta::Validator::release_status
144210s0sCPAN::Meta::Validator::::stringCPAN::Meta::Validator::string
0000s0sCPAN::Meta::Validator::::string_or_undefCPAN::Meta::Validator::string_or_undef
25110s0sCPAN::Meta::Validator::::urlCPAN::Meta::Validator::url
13110s0sCPAN::Meta::Validator::::urlspecCPAN::Meta::Validator::urlspec
94320s0sCPAN::Meta::Validator::::versionCPAN::Meta::Validator::version
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
120s10s
# spent 0s within CPAN::Meta::Converter::BEGIN@1 which was called: # once (0s+0s) by CPAN::Meta::Converter::BEGIN@25 at line 1
use 5.006;
# spent 0s making 1 call to CPAN::Meta::Converter::BEGIN@1
220s20s
# spent 0s within CPAN::Meta::Converter::BEGIN@2 which was called: # once (0s+0s) by CPAN::Meta::Converter::BEGIN@25 at line 2
use strict;
# spent 0s making 1 call to CPAN::Meta::Converter::BEGIN@2 # spent 0s making 1 call to strict::import
320s20s
# spent 0s within CPAN::Meta::Converter::BEGIN@3 which was called: # once (0s+0s) by CPAN::Meta::Converter::BEGIN@25 at line 3
use warnings;
# spent 0s making 1 call to CPAN::Meta::Converter::BEGIN@3 # spent 0s making 1 call to warnings::import
4package CPAN::Meta::Validator;
5# VERSION
610s$CPAN::Meta::Validator::VERSION = '2.143240';
7#pod =head1 SYNOPSIS
8#pod
9#pod my $struct = decode_json_file('META.json');
10#pod
11#pod my $cmv = CPAN::Meta::Validator->new( $struct );
12#pod
13#pod unless ( $cmv->is_valid ) {
14#pod my $msg = "Invalid META structure. Errors found:\n";
15#pod $msg .= join( "\n", $cmv->errors );
16#pod die $msg;
17#pod }
18#pod
19#pod =head1 DESCRIPTION
20#pod
21#pod This module validates a CPAN Meta structure against the version of the
22#pod the specification claimed in the C<meta-spec> field of the structure.
23#pod
24#pod =cut
25
26#--------------------------------------------------------------------------#
27# This code copied and adapted from Test::CPAN::Meta
28# by Barbie, <barbie@cpan.org> for Miss Barbell Productions,
29# L<http://www.missbarbell.co.uk>
30#--------------------------------------------------------------------------#
31
32#--------------------------------------------------------------------------#
33# Specification Definitions
34#--------------------------------------------------------------------------#
35
3610smy %known_specs = (
37 '1.4' => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
38 '1.3' => 'http://module-build.sourceforge.net/META-spec-v1.3.html',
39 '1.2' => 'http://module-build.sourceforge.net/META-spec-v1.2.html',
40 '1.1' => 'http://module-build.sourceforge.net/META-spec-v1.1.html',
41 '1.0' => 'http://module-build.sourceforge.net/META-spec-v1.0.html'
42);
4310smy %known_urls = map {$known_specs{$_} => $_} keys %known_specs;
44
4510smy $module_map1 = { 'map' => { ':key' => { name => \&module, value => \&exversion } } };
46
4710smy $module_map2 = { 'map' => { ':key' => { name => \&module, value => \&version } } };
48
4910smy $no_index_2 = {
50 'map' => { file => { list => { value => \&string } },
51 directory => { list => { value => \&string } },
52 'package' => { list => { value => \&string } },
53 namespace => { list => { value => \&string } },
54 ':key' => { name => \&custom_2, value => \&anything },
55 }
56};
57
5810smy $no_index_1_3 = {
59 'map' => { file => { list => { value => \&string } },
60 directory => { list => { value => \&string } },
61 'package' => { list => { value => \&string } },
62 namespace => { list => { value => \&string } },
63 ':key' => { name => \&string, value => \&anything },
64 }
65};
66
6710smy $no_index_1_2 = {
68 'map' => { file => { list => { value => \&string } },
69 dir => { list => { value => \&string } },
70 'package' => { list => { value => \&string } },
71 namespace => { list => { value => \&string } },
72 ':key' => { name => \&string, value => \&anything },
73 }
74};
75
7610smy $no_index_1_1 = {
77 'map' => { ':key' => { name => \&string, list => { value => \&string } },
78 }
79};
80
8110smy $prereq_map = {
82 map => {
83 ':key' => {
84 name => \&phase,
85 'map' => {
86 ':key' => {
87 name => \&relation,
88 %$module_map1,
89 },
90 },
91 }
92 },
93};
94
9510smy %definitions = (
96 '2' => {
97 # REQUIRED
98 'abstract' => { mandatory => 1, value => \&string },
99 'author' => { mandatory => 1, list => { value => \&string } },
100 'dynamic_config' => { mandatory => 1, value => \&boolean },
101 'generated_by' => { mandatory => 1, value => \&string },
102 'license' => { mandatory => 1, list => { value => \&license } },
103 'meta-spec' => {
104 mandatory => 1,
105 'map' => {
106 version => { mandatory => 1, value => \&version},
107 url => { value => \&url },
108 ':key' => { name => \&custom_2, value => \&anything },
109 }
110 },
111 'name' => { mandatory => 1, value => \&string },
112 'release_status' => { mandatory => 1, value => \&release_status },
113 'version' => { mandatory => 1, value => \&version },
114
115 # OPTIONAL
116 'description' => { value => \&string },
117 'keywords' => { list => { value => \&string } },
118 'no_index' => $no_index_2,
119 'optional_features' => {
120 'map' => {
121 ':key' => {
122 name => \&string,
123 'map' => {
124 description => { value => \&string },
125 prereqs => $prereq_map,
126 ':key' => { name => \&custom_2, value => \&anything },
127 }
128 }
129 }
130 },
131 'prereqs' => $prereq_map,
132 'provides' => {
133 'map' => {
134 ':key' => {
135 name => \&module,
136 'map' => {
137 file => { mandatory => 1, value => \&file },
138 version => { value => \&version },
139 ':key' => { name => \&custom_2, value => \&anything },
140 }
141 }
142 }
143 },
144 'resources' => {
145 'map' => {
146 license => { list => { value => \&url } },
147 homepage => { value => \&url },
148 bugtracker => {
149 'map' => {
150 web => { value => \&url },
151 mailto => { value => \&string},
152 ':key' => { name => \&custom_2, value => \&anything },
153 }
154 },
155 repository => {
156 'map' => {
157 web => { value => \&url },
158 url => { value => \&url },
159 type => { value => \&string },
160 ':key' => { name => \&custom_2, value => \&anything },
161 }
162 },
163 ':key' => { value => \&string, name => \&custom_2 },
164 }
165 },
166
167 # CUSTOM -- additional user defined key/value pairs
168 # note we can only validate the key name, as the structure is user defined
169 ':key' => { name => \&custom_2, value => \&anything },
170 },
171
172'1.4' => {
173 'meta-spec' => {
174 mandatory => 1,
175 'map' => {
176 version => { mandatory => 1, value => \&version},
177 url => { mandatory => 1, value => \&urlspec },
178 ':key' => { name => \&string, value => \&anything },
179 },
180 },
181
182 'name' => { mandatory => 1, value => \&string },
183 'version' => { mandatory => 1, value => \&version },
184 'abstract' => { mandatory => 1, value => \&string },
185 'author' => { mandatory => 1, list => { value => \&string } },
186 'license' => { mandatory => 1, value => \&license },
187 'generated_by' => { mandatory => 1, value => \&string },
188
189 'distribution_type' => { value => \&string },
190 'dynamic_config' => { value => \&boolean },
191
192 'requires' => $module_map1,
193 'recommends' => $module_map1,
194 'build_requires' => $module_map1,
195 'configure_requires' => $module_map1,
196 'conflicts' => $module_map2,
197
198 'optional_features' => {
199 'map' => {
200 ':key' => { name => \&string,
201 'map' => { description => { value => \&string },
202 requires => $module_map1,
203 recommends => $module_map1,
204 build_requires => $module_map1,
205 conflicts => $module_map2,
206 ':key' => { name => \&string, value => \&anything },
207 }
208 }
209 }
210 },
211
212 'provides' => {
213 'map' => {
214 ':key' => { name => \&module,
215 'map' => {
216 file => { mandatory => 1, value => \&file },
217 version => { value => \&version },
218 ':key' => { name => \&string, value => \&anything },
219 }
220 }
221 }
222 },
223
224 'no_index' => $no_index_1_3,
225 'private' => $no_index_1_3,
226
227 'keywords' => { list => { value => \&string } },
228
229 'resources' => {
230 'map' => { license => { value => \&url },
231 homepage => { value => \&url },
232 bugtracker => { value => \&url },
233 repository => { value => \&url },
234 ':key' => { value => \&string, name => \&custom_1 },
235 }
236 },
237
238 # additional user defined key/value pairs
239 # note we can only validate the key name, as the structure is user defined
240 ':key' => { name => \&string, value => \&anything },
241},
242
243'1.3' => {
244 'meta-spec' => {
245 mandatory => 1,
246 'map' => {
247 version => { mandatory => 1, value => \&version},
248 url => { mandatory => 1, value => \&urlspec },
249 ':key' => { name => \&string, value => \&anything },
250 },
251 },
252
253 'name' => { mandatory => 1, value => \&string },
254 'version' => { mandatory => 1, value => \&version },
255 'abstract' => { mandatory => 1, value => \&string },
256 'author' => { mandatory => 1, list => { value => \&string } },
257 'license' => { mandatory => 1, value => \&license },
258 'generated_by' => { mandatory => 1, value => \&string },
259
260 'distribution_type' => { value => \&string },
261 'dynamic_config' => { value => \&boolean },
262
263 'requires' => $module_map1,
264 'recommends' => $module_map1,
265 'build_requires' => $module_map1,
266 'conflicts' => $module_map2,
267
268 'optional_features' => {
269 'map' => {
270 ':key' => { name => \&string,
271 'map' => { description => { value => \&string },
272 requires => $module_map1,
273 recommends => $module_map1,
274 build_requires => $module_map1,
275 conflicts => $module_map2,
276 ':key' => { name => \&string, value => \&anything },
277 }
278 }
279 }
280 },
281
282 'provides' => {
283 'map' => {
284 ':key' => { name => \&module,
285 'map' => {
286 file => { mandatory => 1, value => \&file },
287 version => { value => \&version },
288 ':key' => { name => \&string, value => \&anything },
289 }
290 }
291 }
292 },
293
294
295 'no_index' => $no_index_1_3,
296 'private' => $no_index_1_3,
297
298 'keywords' => { list => { value => \&string } },
299
300 'resources' => {
301 'map' => { license => { value => \&url },
302 homepage => { value => \&url },
303 bugtracker => { value => \&url },
304 repository => { value => \&url },
305 ':key' => { value => \&string, name => \&custom_1 },
306 }
307 },
308
309 # additional user defined key/value pairs
310 # note we can only validate the key name, as the structure is user defined
311 ':key' => { name => \&string, value => \&anything },
312},
313
314# v1.2 is misleading, it seems to assume that a number of fields where created
315# within v1.1, when they were created within v1.2. This may have been an
316# original mistake, and that a v1.1 was retro fitted into the timeline, when
317# v1.2 was originally slated as v1.1. But I could be wrong ;)
318'1.2' => {
319 'meta-spec' => {
320 mandatory => 1,
321 'map' => {
322 version => { mandatory => 1, value => \&version},
323 url => { mandatory => 1, value => \&urlspec },
324 ':key' => { name => \&string, value => \&anything },
325 },
326 },
327
328
329 'name' => { mandatory => 1, value => \&string },
330 'version' => { mandatory => 1, value => \&version },
331 'license' => { mandatory => 1, value => \&license },
332 'generated_by' => { mandatory => 1, value => \&string },
333 'author' => { mandatory => 1, list => { value => \&string } },
334 'abstract' => { mandatory => 1, value => \&string },
335
336 'distribution_type' => { value => \&string },
337 'dynamic_config' => { value => \&boolean },
338
339 'keywords' => { list => { value => \&string } },
340
341 'private' => $no_index_1_2,
342 '$no_index' => $no_index_1_2,
343
344 'requires' => $module_map1,
345 'recommends' => $module_map1,
346 'build_requires' => $module_map1,
347 'conflicts' => $module_map2,
348
349 'optional_features' => {
350 'map' => {
351 ':key' => { name => \&string,
352 'map' => { description => { value => \&string },
353 requires => $module_map1,
354 recommends => $module_map1,
355 build_requires => $module_map1,
356 conflicts => $module_map2,
357 ':key' => { name => \&string, value => \&anything },
358 }
359 }
360 }
361 },
362
363 'provides' => {
364 'map' => {
365 ':key' => { name => \&module,
366 'map' => {
367 file => { mandatory => 1, value => \&file },
368 version => { value => \&version },
369 ':key' => { name => \&string, value => \&anything },
370 }
371 }
372 }
373 },
374
375 'resources' => {
376 'map' => { license => { value => \&url },
377 homepage => { value => \&url },
378 bugtracker => { value => \&url },
379 repository => { value => \&url },
380 ':key' => { value => \&string, name => \&custom_1 },
381 }
382 },
383
384 # additional user defined key/value pairs
385 # note we can only validate the key name, as the structure is user defined
386 ':key' => { name => \&string, value => \&anything },
387},
388
389# note that the 1.1 spec only specifies 'version' as mandatory
390'1.1' => {
391 'name' => { value => \&string },
392 'version' => { mandatory => 1, value => \&version },
393 'license' => { value => \&license },
394 'generated_by' => { value => \&string },
395
396 'license_uri' => { value => \&url },
397 'distribution_type' => { value => \&string },
398 'dynamic_config' => { value => \&boolean },
399
400 'private' => $no_index_1_1,
401
402 'requires' => $module_map1,
403 'recommends' => $module_map1,
404 'build_requires' => $module_map1,
405 'conflicts' => $module_map2,
406
407 # additional user defined key/value pairs
408 # note we can only validate the key name, as the structure is user defined
409 ':key' => { name => \&string, value => \&anything },
410},
411
412# note that the 1.0 spec doesn't specify optional or mandatory fields
413# but we will treat version as mandatory since otherwise META 1.0 is
414# completely arbitrary and pointless
415'1.0' => {
416 'name' => { value => \&string },
417 'version' => { mandatory => 1, value => \&version },
418 'license' => { value => \&license },
419 'generated_by' => { value => \&string },
420
421 'license_uri' => { value => \&url },
422 'distribution_type' => { value => \&string },
423 'dynamic_config' => { value => \&boolean },
424
425 'requires' => $module_map1,
426 'recommends' => $module_map1,
427 'build_requires' => $module_map1,
428 'conflicts' => $module_map2,
429
430 # additional user defined key/value pairs
431 # note we can only validate the key name, as the structure is user defined
432 ':key' => { name => \&string, value => \&anything },
433},
434);
435
436#--------------------------------------------------------------------------#
437# Code
438#--------------------------------------------------------------------------#
439
440#pod =method new
441#pod
442#pod my $cmv = CPAN::Meta::Validator->new( $struct )
443#pod
444#pod The constructor must be passed a metadata structure.
445#pod
446#pod =cut
447
448
# spent 0s within CPAN::Meta::Validator::new which was called 29 times, avg 0s/call: # 9 times (0s+0s) by CPAN::Meta::Converter::convert at line 1429 of CPAN/Meta/Converter.pm, avg 0s/call # 6 times (0s+0s) by ExtUtils::MM_Any::_fix_metadata_before_conversion at line 1026 of ExtUtils/MM_Any.pm, avg 0s/call # 6 times (0s+0s) by ExtUtils::MM_Any::_fix_metadata_before_conversion at line 1035 of ExtUtils/MM_Any.pm, avg 0s/call # 4 times (0s+0s) by CPAN::Meta::Converter::convert at line 1413 of CPAN/Meta/Converter.pm, avg 0s/call # 4 times (0s+0s) by CPAN::Meta::Converter::convert at line 1446 of CPAN/Meta/Converter.pm, avg 0s/call
sub new {
449290s my ($class,$data) = @_;
450
451 # create an attributes hash
452 my $self = {
453 'data' => $data,
454580s 'spec' => eval { $data->{'meta-spec'}{'version'} } || "1.0",
455 'errors' => undef,
456 };
457
458 # create the object
459290s return bless $self, $class;
460}
461
462#pod =method is_valid
463#pod
464#pod if ( $cmv->is_valid ) {
465#pod ...
466#pod }
467#pod
468#pod Returns a boolean value indicating whether the metadata provided
469#pod is valid.
470#pod
471#pod =cut
472
473
# spent 0s within CPAN::Meta::Validator::is_valid which was called 23 times, avg 0s/call: # 9 times (0s+0s) by CPAN::Meta::Converter::convert at line 1430 of CPAN/Meta/Converter.pm, avg 0s/call # 6 times (0s+0s) by ExtUtils::MM_Any::_fix_metadata_before_conversion at line 1036 of ExtUtils/MM_Any.pm, avg 0s/call # 4 times (0s+0s) by CPAN::Meta::Converter::convert at line 1447 of CPAN/Meta/Converter.pm, avg 0s/call # 4 times (0s+0s) by CPAN::Meta::Converter::convert at line 1414 of CPAN/Meta/Converter.pm, avg 0s/call
sub is_valid {
474230s my $self = shift;
475230s my $data = $self->{data};
476230s my $spec_version = $self->{spec};
477230s230s $self->check_map($definitions{$spec_version},$data);
# spent 0s making 23 calls to CPAN::Meta::Validator::check_map, avg 0s/call
478230s230s return ! $self->errors;
# spent 0s making 23 calls to CPAN::Meta::Validator::errors, avg 0s/call
479}
480
481#pod =method errors
482#pod
483#pod warn( join "\n", $cmv->errors );
484#pod
485#pod Returns a list of errors seen during validation.
486#pod
487#pod =cut
488
489
# spent 0s within CPAN::Meta::Validator::errors which was called 24 times, avg 0s/call: # 23 times (0s+0s) by CPAN::Meta::Validator::is_valid at line 478, avg 0s/call # once (0s+0s) by ExtUtils::MM_Any::_fix_metadata_before_conversion at line 1039 of ExtUtils/MM_Any.pm
sub errors {
490240s my $self = shift;
491240s return () unless(defined $self->{errors});
49220s return @{$self->{errors}};
493}
494
495#pod =begin :internals
496#pod
497#pod =head2 Check Methods
498#pod
499#pod =over
500#pod
501#pod =item *
502#pod
503#pod check_map($spec,$data)
504#pod
505#pod Checks whether a map (or hash) part of the data structure conforms to the
506#pod appropriate specification definition.
507#pod
508#pod =item *
509#pod
510#pod check_list($spec,$data)
511#pod
512#pod Checks whether a list (or array) part of the data structure conforms to
513#pod the appropriate specification definition.
514#pod
515#pod =item *
516#pod
517#pod =back
518#pod
519#pod =cut
520
52110smy $spec_error = "Missing validation action in specification. "
522 . "Must be one of 'map', 'list', or 'value'";
523
524
# spent 0s within CPAN::Meta::Validator::check_map which was called 179 times, avg 0s/call: # 108 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call # 48 times (0s+0s) by CPAN::Meta::Validator::check_map at line 560, avg 0s/call # 23 times (0s+0s) by CPAN::Meta::Validator::is_valid at line 477, avg 0s/call
sub check_map {
5251790s my ($self,$spec,$data) = @_;
526
5271790s if(ref($spec) ne 'HASH') {
528 $self->_error( "Unknown META specification, cannot validate." );
529 return;
530 }
531
5321790s if(ref($data) ne 'HASH') {
533 $self->_error( "Expected a map structure from string or file." );
534 return;
535 }
536
5371790s for my $key (keys %$spec) {
5387910s next unless($spec->{$key}->{mandatory});
5392170s next if(defined $data->{$key});
54010s push @{$self->{stack}}, $key;
54110s10s $self->_error( "Missing mandatory field, '$key'" );
# spent 0s making 1 call to CPAN::Meta::Validator::_error
54210s pop @{$self->{stack}};
543 }
544
5451790s for my $key (keys %$data) {
5464630s push @{$self->{stack}}, $key;
5474630s if($spec->{$key}) {
5483720s3720s if($spec->{$key}{value}) {
# spent 0s making 23 calls to CPAN::Meta::Validator::boolean, avg 0s/call # spent 0s making 56 calls to CPAN::Meta::Validator::check_list, avg 0s/call # spent 0s making 108 calls to CPAN::Meta::Validator::check_map, avg 0s/call, recursion: max depth 2, sum of overlapping time 0s # spent 0s making 13 calls to CPAN::Meta::Validator::license, avg 0s/call # spent 0s making 9 calls to CPAN::Meta::Validator::release_status, avg 0s/call # spent 0s making 79 calls to CPAN::Meta::Validator::string, avg 0s/call # spent 0s making 25 calls to CPAN::Meta::Validator::url, avg 0s/call # spent 0s making 13 calls to CPAN::Meta::Validator::urlspec, avg 0s/call # spent 0s making 46 calls to CPAN::Meta::Validator::version, avg 0s/call
549 $spec->{$key}{value}->($self,$key,$data->{$key});
550 } elsif($spec->{$key}{'map'}) {
551 $self->check_map($spec->{$key}{'map'},$data->{$key});
552 } elsif($spec->{$key}{'list'}) {
553 $self->check_list($spec->{$key}{'list'},$data->{$key});
554 } else {
555 $self->_error( "$spec_error for '$key'" );
556 }
557
558 } elsif ($spec->{':key'}) {
559910s910s $spec->{':key'}{name}->($self,$key,$key);
# spent 0s making 1 call to CPAN::Meta::Validator::custom_2 # spent 0s making 42 calls to CPAN::Meta::Validator::module, avg 0s/call # spent 0s making 24 calls to CPAN::Meta::Validator::phase, avg 0s/call # spent 0s making 24 calls to CPAN::Meta::Validator::relation, avg 0s/call
560910s910s if($spec->{':key'}{value}) {
# spent 0s making 1 call to CPAN::Meta::Validator::anything # spent 0s making 48 calls to CPAN::Meta::Validator::check_map, avg 0s/call, recursion: max depth 3, sum of overlapping time 0s # spent 0s making 42 calls to CPAN::Meta::Validator::exversion, avg 0s/call
561 $spec->{':key'}{value}->($self,$key,$data->{$key});
562 } elsif($spec->{':key'}{'map'}) {
563 $self->check_map($spec->{':key'}{'map'},$data->{$key});
564 } elsif($spec->{':key'}{'list'}) {
565 $self->check_list($spec->{':key'}{'list'},$data->{$key});
566 } else {
567 $self->_error( "$spec_error for ':key'" );
568 }
569
570
571 } else {
572 $self->_error( "Unknown key, '$key', found in map structure" );
573 }
5744630s pop @{$self->{stack}};
575 }
576}
577
578
# spent 0s within CPAN::Meta::Validator::check_list which was called 56 times, avg 0s/call: # 56 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call
sub check_list {
579560s my ($self,$spec,$data) = @_;
580
581560s if(ref($data) ne 'ARRAY') {
58210s10s $self->_error( "Expected a list structure" );
# spent 0s making 1 call to CPAN::Meta::Validator::_error
58310s return;
584 }
585
586550s if(defined $spec->{mandatory}) {
587 if(!defined $data->[0]) {
588 $self->_error( "Missing entries from mandatory list" );
589 }
590 }
591
592550s for my $value (@$data) {
593740s push @{$self->{stack}}, $value || "<undef>";
594740s740s if(defined $spec->{value}) {
# spent 0s making 9 calls to CPAN::Meta::Validator::license, avg 0s/call # spent 0s making 65 calls to CPAN::Meta::Validator::string, avg 0s/call
595 $spec->{value}->($self,'list',$value);
596 } elsif(defined $spec->{'map'}) {
597 $self->check_map($spec->{'map'},$value);
598 } elsif(defined $spec->{'list'}) {
599 $self->check_list($spec->{'list'},$value);
600 } elsif ($spec->{':key'}) {
601 $self->check_map($spec,$value);
602 } else {
603 $self->_error( "$spec_error associated with '$self->{stack}[-2]'" );
604 }
605740s pop @{$self->{stack}};
606 }
607}
608
609#pod =head2 Validator Methods
610#pod
611#pod =over
612#pod
613#pod =item *
614#pod
615#pod header($self,$key,$value)
616#pod
617#pod Validates that the header is valid.
618#pod
619#pod Note: No longer used as we now read the data structure, not the file.
620#pod
621#pod =item *
622#pod
623#pod url($self,$key,$value)
624#pod
625#pod Validates that a given value is in an acceptable URL format
626#pod
627#pod =item *
628#pod
629#pod urlspec($self,$key,$value)
630#pod
631#pod Validates that the URL to a META specification is a known one.
632#pod
633#pod =item *
634#pod
635#pod string_or_undef($self,$key,$value)
636#pod
637#pod Validates that the value is either a string or an undef value. Bit of a
638#pod catchall function for parts of the data structure that are completely user
639#pod defined.
640#pod
641#pod =item *
642#pod
643#pod string($self,$key,$value)
644#pod
645#pod Validates that a string exists for the given key.
646#pod
647#pod =item *
648#pod
649#pod file($self,$key,$value)
650#pod
651#pod Validate that a file is passed for the given key. This may be made more
652#pod thorough in the future. For now it acts like \&string.
653#pod
654#pod =item *
655#pod
656#pod exversion($self,$key,$value)
657#pod
658#pod Validates a list of versions, e.g. '<= 5, >=2, ==3, !=4, >1, <6, 0'.
659#pod
660#pod =item *
661#pod
662#pod version($self,$key,$value)
663#pod
664#pod Validates a single version string. Versions of the type '5.8.8' and '0.00_00'
665#pod are both valid. A leading 'v' like 'v1.2.3' is also valid.
666#pod
667#pod =item *
668#pod
669#pod boolean($self,$key,$value)
670#pod
671#pod Validates for a boolean value. Currently these values are '1', '0', 'true',
672#pod 'false', however the latter 2 may be removed.
673#pod
674#pod =item *
675#pod
676#pod license($self,$key,$value)
677#pod
678#pod Validates that a value is given for the license. Returns 1 if an known license
679#pod type, or 2 if a value is given but the license type is not a recommended one.
680#pod
681#pod =item *
682#pod
683#pod custom_1($self,$key,$value)
684#pod
685#pod Validates that the given key is in CamelCase, to indicate a user defined
686#pod keyword and only has characters in the class [-_a-zA-Z]. In version 1.X
687#pod of the spec, this was only explicitly stated for 'resources'.
688#pod
689#pod =item *
690#pod
691#pod custom_2($self,$key,$value)
692#pod
693#pod Validates that the given key begins with 'x_' or 'X_', to indicate a user
694#pod defined keyword and only has characters in the class [-_a-zA-Z]
695#pod
696#pod =item *
697#pod
698#pod identifier($self,$key,$value)
699#pod
700#pod Validates that key is in an acceptable format for the META specification,
701#pod for an identifier, i.e. any that matches the regular expression
702#pod qr/[a-z][a-z_]/i.
703#pod
704#pod =item *
705#pod
706#pod module($self,$key,$value)
707#pod
708#pod Validates that a given key is in an acceptable module name format, e.g.
709#pod 'Test::CPAN::Meta::Version'.
710#pod
711#pod =back
712#pod
713#pod =end :internals
714#pod
715#pod =cut
716
717sub header {
718 my ($self,$key,$value) = @_;
719 if(defined $value) {
720 return 1 if($value && $value =~ /^--- #YAML:1.0/);
721 }
722 $self->_error( "file does not have a valid YAML header." );
723 return 0;
724}
725
726
# spent 0s within CPAN::Meta::Validator::release_status which was called 9 times, avg 0s/call: # 9 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call
sub release_status {
72790s my ($self,$key,$value) = @_;
72890s if(defined $value) {
72990s my $version = $self->{data}{version} || '';
73090s90s if ( $version =~ /_/ ) {
# spent 0s making 9 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
731 return 1 if ( $value =~ /\A(?:testing|unstable)\z/ );
732 $self->_error( "'$value' for '$key' is invalid for version '$version'" );
733 }
734 else {
73590s90s return 1 if ( $value =~ /\A(?:stable|testing|unstable)\z/ );
# spent 0s making 9 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
736 $self->_error( "'$value' for '$key' is invalid" );
737 }
738 }
739 else {
740 $self->_error( "'$key' is not defined" );
741 }
742 return 0;
743}
744
745# _uri_split taken from URI::Split by Gisle Aas, Copyright 2003
746
# spent 0s within CPAN::Meta::Validator::_uri_split which was called 25 times, avg 0s/call: # 25 times (0s+0s) by CPAN::Meta::Validator::url at line 753, avg 0s/call
sub _uri_split {
747250s250s return $_[0] =~ m,(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?,;
# spent 0s making 25 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
748}
749
750
# spent 0s within CPAN::Meta::Validator::url which was called 25 times, avg 0s/call: # 25 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call
sub url {
751250s my ($self,$key,$value) = @_;
752250s if(defined $value) {
753250s250s my ($scheme, $auth, $path, $query, $frag) = _uri_split($value);
# spent 0s making 25 calls to CPAN::Meta::Validator::_uri_split, avg 0s/call
754250s unless ( defined $scheme && length $scheme ) {
755 $self->_error( "'$value' for '$key' does not have a URL scheme" );
756 return 0;
757 }
758250s unless ( defined $auth && length $auth ) {
759 $self->_error( "'$value' for '$key' does not have a URL authority" );
760 return 0;
761 }
762250s return 1;
763 }
764 $value ||= '';
765 $self->_error( "'$value' for '$key' is not a valid URL." );
766 return 0;
767}
768
769
# spent 0s within CPAN::Meta::Validator::urlspec which was called 13 times, avg 0s/call: # 13 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call
sub urlspec {
770130s my ($self,$key,$value) = @_;
771130s if(defined $value) {
772130s return 1 if($value && $known_specs{$self->{spec}} eq $value);
773 if($value && $known_urls{$value}) {
774 $self->_error( 'META specification URL does not match version' );
775 return 0;
776 }
777 }
778 $self->_error( 'Unknown META specification' );
779 return 0;
780}
781
78210s
# spent 0s within CPAN::Meta::Validator::anything which was called: # once (0s+0s) by CPAN::Meta::Validator::check_map at line 560
sub anything { return 1 }
783
784
# spent 0s within CPAN::Meta::Validator::string which was called 144 times, avg 0s/call: # 79 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call # 65 times (0s+0s) by CPAN::Meta::Validator::check_list at line 594, avg 0s/call
sub string {
7851440s my ($self,$key,$value) = @_;
7861440s if(defined $value) {
7871440s return 1 if($value || $value =~ /^0$/);
788 }
789 $self->_error( "value is an undefined string" );
790 return 0;
791}
792
793sub string_or_undef {
794 my ($self,$key,$value) = @_;
795 return 1 unless(defined $value);
796 return 1 if($value || $value =~ /^0$/);
797 $self->_error( "No string defined for '$key'" );
798 return 0;
799}
800
801sub file {
802 my ($self,$key,$value) = @_;
803 return 1 if(defined $value);
804 $self->_error( "No file defined for '$key'" );
805 return 0;
806}
807
808
# spent 0s within CPAN::Meta::Validator::exversion which was called 42 times, avg 0s/call: # 42 times (0s+0s) by CPAN::Meta::Validator::check_map at line 560, avg 0s/call
sub exversion {
809420s my ($self,$key,$value) = @_;
810420s420s if(defined $value && ($value || $value =~ /0/)) {
# spent 0s making 42 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
811420s my $pass = 1;
812840s420s for(split(",",$value)) { $self->version($key,$_) or ($pass = 0); }
# spent 0s making 42 calls to CPAN::Meta::Validator::version, avg 0s/call
813420s return $pass;
814 }
815 $value = '<undef>' unless(defined $value);
816 $self->_error( "'$value' for '$key' is not a valid version." );
817 return 0;
818}
819
820
# spent 0s within CPAN::Meta::Validator::version which was called 94 times, avg 0s/call: # 46 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call # 42 times (0s+0s) by CPAN::Meta::Validator::exversion at line 812, avg 0s/call # 6 times (0s+0s) by ExtUtils::MM_Any::_fix_metadata_before_conversion at line 1026 of ExtUtils/MM_Any.pm, avg 0s/call
sub version {
821940s my ($self,$key,$value) = @_;
822940s if(defined $value) {
823940s420s return 0 unless($value || $value =~ /0/);
# spent 0s making 42 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
824940s940s return 1 if($value =~ /^\s*((<|<=|>=|>|!=|==)\s*)?v?\d+((\.\d+((_|\.)\d+)?)?)/);
# spent 0s making 94 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
825 } else {
826 $value = '<undef>';
827 }
828 $self->_error( "'$value' for '$key' is not a valid version." );
829 return 0;
830}
831
832
# spent 0s within CPAN::Meta::Validator::boolean which was called 23 times, avg 0s/call: # 23 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call
sub boolean {
833230s my ($self,$key,$value) = @_;
834230s if(defined $value) {
835230s230s return 1 if($value =~ /^(0|1|true|false)$/);
# spent 0s making 23 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
836 } else {
837 $value = '<undef>';
838 }
839 $self->_error( "'$value' for '$key' is not a boolean value." );
840 return 0;
841}
842
84310smy %v1_licenses = (
844 'perl' => 'http://dev.perl.org/licenses/',
845 'gpl' => 'http://www.opensource.org/licenses/gpl-license.php',
846 'apache' => 'http://apache.org/licenses/LICENSE-2.0',
847 'artistic' => 'http://opensource.org/licenses/artistic-license.php',
848 'artistic_2' => 'http://opensource.org/licenses/artistic-license-2.0.php',
849 'lgpl' => 'http://www.opensource.org/licenses/lgpl-license.php',
850 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
851 'gpl' => 'http://www.opensource.org/licenses/gpl-license.php',
852 'mit' => 'http://opensource.org/licenses/mit-license.php',
853 'mozilla' => 'http://opensource.org/licenses/mozilla1.1.php',
854 'open_source' => undef,
855 'unrestricted' => undef,
856 'restrictive' => undef,
857 'unknown' => undef,
858);
859
86010smy %v2_licenses = map { $_ => 1 } qw(
861 agpl_3
862 apache_1_1
863 apache_2_0
864 artistic_1
865 artistic_2
866 bsd
867 freebsd
868 gfdl_1_2
869 gfdl_1_3
870 gpl_1
871 gpl_2
872 gpl_3
873 lgpl_2_1
874 lgpl_3_0
875 mit
876 mozilla_1_0
877 mozilla_1_1
878 openssl
879 perl_5
880 qpl_1_0
881 ssleay
882 sun
883 zlib
884 open_source
885 restricted
886 unrestricted
887 unknown
888);
889
890
# spent 0s within CPAN::Meta::Validator::license which was called 22 times, avg 0s/call: # 13 times (0s+0s) by CPAN::Meta::Validator::check_map at line 548, avg 0s/call # 9 times (0s+0s) by CPAN::Meta::Validator::check_list at line 594, avg 0s/call
sub license {
891220s my ($self,$key,$value) = @_;
892220s my $licenses = $self->{spec} < 2 ? \%v1_licenses : \%v2_licenses;
893220s if(defined $value) {
894 return 1 if($value && exists $licenses->{$value});
895 } else {
896 $value = '<undef>';
897 }
898 $self->_error( "License '$value' is invalid" );
899 return 0;
900}
901
902sub custom_1 {
903 my ($self,$key) = @_;
904 if(defined $key) {
905 # a valid user defined key should be alphabetic
906 # and contain at least one capital case letter.
907 return 1 if($key && $key =~ /^[_a-z]+$/i && $key =~ /[A-Z]/);
908 } else {
909 $key = '<undef>';
910 }
911 $self->_error( "Custom resource '$key' must be in CamelCase." );
912 return 0;
913}
914
915
# spent 0s within CPAN::Meta::Validator::custom_2 which was called: # once (0s+0s) by CPAN::Meta::Validator::check_map at line 559
sub custom_2 {
91610s my ($self,$key) = @_;
91710s if(defined $key) {
91810s10s return 1 if($key && $key =~ /^x_/i); # user defined
# spent 0s making 1 call to CPAN::Meta::Validator::CORE:match
919 } else {
920 $key = '<undef>';
921 }
92210s10s $self->_error( "Custom key '$key' must begin with 'x_' or 'X_'." );
# spent 0s making 1 call to CPAN::Meta::Validator::_error
92310s return 0;
924}
925
926sub identifier {
927 my ($self,$key) = @_;
928 if(defined $key) {
929 return 1 if($key && $key =~ /^([a-z][_a-z]+)$/i); # spec 2.0 defined
930 } else {
931 $key = '<undef>';
932 }
933 $self->_error( "Key '$key' is not a legal identifier." );
934 return 0;
935}
936
937
# spent 0s within CPAN::Meta::Validator::module which was called 42 times, avg 0s/call: # 42 times (0s+0s) by CPAN::Meta::Validator::check_map at line 559, avg 0s/call
sub module {
938420s my ($self,$key) = @_;
939420s if(defined $key) {
940420s420s return 1 if($key && $key =~ /^[A-Za-z0-9_]+(::[A-Za-z0-9_]+)*$/);
# spent 0s making 42 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call
941 } else {
942 $key = '<undef>';
943 }
944 $self->_error( "Key '$key' is not a legal module name." );
945 return 0;
946}
947
94810smy @valid_phases = qw/ configure build test runtime develop /;
949
# spent 0s within CPAN::Meta::Validator::phase which was called 24 times, avg 0s/call: # 24 times (0s+0s) by CPAN::Meta::Validator::check_map at line 559, avg 0s/call
sub phase {
950240s my ($self,$key) = @_;
951240s if(defined $key) {
952240s return 1 if( length $key && grep { $key eq $_ } @valid_phases );
953 return 1 if $key =~ /x_/i;
954 } else {
955 $key = '<undef>';
956 }
957 $self->_error( "Key '$key' is not a legal phase." );
958 return 0;
959}
960
96110smy @valid_relations = qw/ requires recommends suggests conflicts /;
962
# spent 0s within CPAN::Meta::Validator::relation which was called 24 times, avg 0s/call: # 24 times (0s+0s) by CPAN::Meta::Validator::check_map at line 559, avg 0s/call
sub relation {
963240s my ($self,$key) = @_;
964240s if(defined $key) {
965240s return 1 if( length $key && grep { $key eq $_ } @valid_relations );
966 return 1 if $key =~ /x_/i;
967 } else {
968 $key = '<undef>';
969 }
970 $self->_error( "Key '$key' is not a legal prereq relationship." );
971 return 0;
972}
973
974
# spent 0s within CPAN::Meta::Validator::_error which was called 3 times, avg 0s/call: # once (0s+0s) by CPAN::Meta::Validator::custom_2 at line 922 # once (0s+0s) by CPAN::Meta::Validator::check_list at line 582 # once (0s+0s) by CPAN::Meta::Validator::check_map at line 541
sub _error {
97530s my $self = shift;
97630s my $mess = shift;
977
97830s $mess .= ' ('.join(' -> ',@{$self->{stack}}).')' if($self->{stack});
97930s $mess .= " [Validation: $self->{spec}]";
980
98130s push @{$self->{errors}}, $mess;
982}
983
98410s1;
985
986# ABSTRACT: validate CPAN distribution metadata structures
987
988__END__
 
# spent 0s within CPAN::Meta::Validator::CORE:match which was called 287 times, avg 0s/call: # 94 times (0s+0s) by CPAN::Meta::Validator::version at line 824, avg 0s/call # 42 times (0s+0s) by CPAN::Meta::Validator::module at line 940, avg 0s/call # 42 times (0s+0s) by CPAN::Meta::Validator::version at line 823, avg 0s/call # 42 times (0s+0s) by CPAN::Meta::Validator::exversion at line 810, avg 0s/call # 25 times (0s+0s) by CPAN::Meta::Validator::_uri_split at line 747, avg 0s/call # 23 times (0s+0s) by CPAN::Meta::Validator::boolean at line 835, avg 0s/call # 9 times (0s+0s) by CPAN::Meta::Validator::release_status at line 730, avg 0s/call # 9 times (0s+0s) by CPAN::Meta::Validator::release_status at line 735, avg 0s/call # once (0s+0s) by CPAN::Meta::Validator::custom_2 at line 918
sub CPAN::Meta::Validator::CORE:match; # opcode