| Filename | C:/tmp64ng/perl/lib/CPAN/Meta/Validator.pm | 
| Statements | Executed 6344 statements in 0s | 
| Calls | P | F | Exclusive Time  | 
        Inclusive Time  | 
        Subroutine | 
|---|---|---|---|---|---|
| 1 | 1 | 1 | 0s | 0s | CPAN::Meta::Converter::BEGIN@1 | 
| 1 | 1 | 1 | 0s | 0s | CPAN::Meta::Converter::BEGIN@2 | 
| 1 | 1 | 1 | 0s | 0s | CPAN::Meta::Converter::BEGIN@3 | 
| 287 | 9 | 1 | 0s | 0s | CPAN::Meta::Validator::CORE:match (opcode) | 
| 3 | 3 | 1 | 0s | 0s | CPAN::Meta::Validator::_error | 
| 25 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::_uri_split | 
| 1 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::anything | 
| 23 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::boolean | 
| 56 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::check_list | 
| 179 | 3 | 1 | 0s | 0s | CPAN::Meta::Validator::check_map (recurses: max depth 3, inclusive time 0s) | 
| 0 | 0 | 0 | 0s | 0s | CPAN::Meta::Validator::custom_1 | 
| 1 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::custom_2 | 
| 24 | 2 | 2 | 0s | 0s | CPAN::Meta::Validator::errors | 
| 42 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::exversion | 
| 0 | 0 | 0 | 0s | 0s | CPAN::Meta::Validator::file | 
| 0 | 0 | 0 | 0s | 0s | CPAN::Meta::Validator::header | 
| 0 | 0 | 0 | 0s | 0s | CPAN::Meta::Validator::identifier | 
| 23 | 4 | 2 | 0s | 0s | CPAN::Meta::Validator::is_valid | 
| 22 | 2 | 1 | 0s | 0s | CPAN::Meta::Validator::license | 
| 42 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::module | 
| 29 | 5 | 2 | 0s | 0s | CPAN::Meta::Validator::new | 
| 24 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::phase | 
| 24 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::relation | 
| 9 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::release_status | 
| 144 | 2 | 1 | 0s | 0s | CPAN::Meta::Validator::string | 
| 0 | 0 | 0 | 0s | 0s | CPAN::Meta::Validator::string_or_undef | 
| 25 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::url | 
| 13 | 1 | 1 | 0s | 0s | CPAN::Meta::Validator::urlspec | 
| 94 | 3 | 2 | 0s | 0s | CPAN::Meta::Validator::version | 
| Line | State ments  | 
      Time on line  | 
      Calls | Time in subs  | 
      Code | 
|---|---|---|---|---|---|
| 1 | 2 | 0s | 1 | 0s | # spent 0s within CPAN::Meta::Converter::BEGIN@1 which was called:
#    once (0s+0s) by CPAN::Meta::Converter::BEGIN@25 at line 1 # spent     0s making 1 call to CPAN::Meta::Converter::BEGIN@1  | 
| 2 | 2 | 0s | 2 | 0s | # spent 0s within CPAN::Meta::Converter::BEGIN@2 which was called:
#    once (0s+0s) by CPAN::Meta::Converter::BEGIN@25 at line 2 # spent     0s making 1 call to CPAN::Meta::Converter::BEGIN@2
# spent     0s making 1 call to strict::import  | 
| 3 | 2 | 0s | 2 | 0s | # spent 0s within CPAN::Meta::Converter::BEGIN@3 which was called:
#    once (0s+0s) by CPAN::Meta::Converter::BEGIN@25 at line 3 # spent     0s making 1 call to CPAN::Meta::Converter::BEGIN@3
# spent     0s making 1 call to warnings::import  | 
| 4 | package CPAN::Meta::Validator; | ||||
| 5 | # VERSION | ||||
| 6 | 1 | 0s | $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 | |||||
| 36 | 1 | 0s | my %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 | ); | ||||
| 43 | 1 | 0s | my %known_urls = map {$known_specs{$_} => $_} keys %known_specs; | ||
| 44 | |||||
| 45 | 1 | 0s | my $module_map1 = { 'map' => { ':key' => { name => \&module, value => \&exversion } } }; | ||
| 46 | |||||
| 47 | 1 | 0s | my $module_map2 = { 'map' => { ':key' => { name => \&module, value => \&version } } }; | ||
| 48 | |||||
| 49 | 1 | 0s | my $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 | |||||
| 58 | 1 | 0s | my $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 | |||||
| 67 | 1 | 0s | my $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 | |||||
| 76 | 1 | 0s | my $no_index_1_1 = { | ||
| 77 | 'map' => { ':key' => { name => \&string, list => { value => \&string } }, | ||||
| 78 | } | ||||
| 79 | }; | ||||
| 80 | |||||
| 81 | 1 | 0s | my $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 | |||||
| 95 | 1 | 0s | my %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  | ||||
| 449 | 29 | 0s | my ($class,$data) = @_; | ||
| 450 | |||||
| 451 | # create an attributes hash | ||||
| 452 | my $self = { | ||||
| 453 | 'data' => $data, | ||||
| 454 | 58 | 0s | 'spec' => eval { $data->{'meta-spec'}{'version'} } || "1.0", | ||
| 455 | 'errors' => undef, | ||||
| 456 | }; | ||||
| 457 | |||||
| 458 | # create the object | ||||
| 459 | 29 | 0s | 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  | ||||
| 474 | 23 | 0s | my $self = shift; | ||
| 475 | 23 | 0s | my $data = $self->{data}; | ||
| 476 | 23 | 0s | my $spec_version = $self->{spec}; | ||
| 477 | 23 | 0s | 23 | 0s |     $self->check_map($definitions{$spec_version},$data);     # spent     0s making 23 calls to CPAN::Meta::Validator::check_map, avg 0s/call  | 
| 478 | 23 | 0s | 23 | 0s |     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  | ||||
| 490 | 24 | 0s | my $self = shift; | ||
| 491 | 24 | 0s | return () unless(defined $self->{errors}); | ||
| 492 | 2 | 0s | 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 | |||||
| 521 | 1 | 0s | my $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  | ||||
| 525 | 179 | 0s | my ($self,$spec,$data) = @_; | ||
| 526 | |||||
| 527 | 179 | 0s | if(ref($spec) ne 'HASH') { | ||
| 528 | $self->_error( "Unknown META specification, cannot validate." ); | ||||
| 529 | return; | ||||
| 530 | } | ||||
| 531 | |||||
| 532 | 179 | 0s | if(ref($data) ne 'HASH') { | ||
| 533 | $self->_error( "Expected a map structure from string or file." ); | ||||
| 534 | return; | ||||
| 535 | } | ||||
| 536 | |||||
| 537 | 179 | 0s | for my $key (keys %$spec) { | ||
| 538 | 791 | 0s | next unless($spec->{$key}->{mandatory}); | ||
| 539 | 217 | 0s | next if(defined $data->{$key}); | ||
| 540 | 1 | 0s | push @{$self->{stack}}, $key; | ||
| 541 | 1 | 0s | 1 | 0s |         $self->_error( "Missing mandatory field, '$key'" );         # spent     0s making 1 call to CPAN::Meta::Validator::_error  | 
| 542 | 1 | 0s | pop @{$self->{stack}}; | ||
| 543 | } | ||||
| 544 | |||||
| 545 | 179 | 0s | for my $key (keys %$data) { | ||
| 546 | 463 | 0s | push @{$self->{stack}}, $key; | ||
| 547 | 463 | 0s | if($spec->{$key}) { | ||
| 548 | 372 | 0s | 372 | 0s |             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'}) { | ||||
| 559 | 91 | 0s | 91 | 0s |             $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  | 
| 560 | 91 | 0s | 91 | 0s |             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 | } | ||||
| 574 | 463 | 0s | 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  | ||||
| 579 | 56 | 0s | my ($self,$spec,$data) = @_; | ||
| 580 | |||||
| 581 | 56 | 0s | if(ref($data) ne 'ARRAY') { | ||
| 582 | 1 | 0s | 1 | 0s |         $self->_error( "Expected a list structure" );         # spent     0s making 1 call to CPAN::Meta::Validator::_error  | 
| 583 | 1 | 0s | return; | ||
| 584 | } | ||||
| 585 | |||||
| 586 | 55 | 0s | if(defined $spec->{mandatory}) { | ||
| 587 | if(!defined $data->[0]) { | ||||
| 588 | $self->_error( "Missing entries from mandatory list" ); | ||||
| 589 | } | ||||
| 590 | } | ||||
| 591 | |||||
| 592 | 55 | 0s | for my $value (@$data) { | ||
| 593 | 74 | 0s | push @{$self->{stack}}, $value || "<undef>"; | ||
| 594 | 74 | 0s | 74 | 0s |         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 | } | ||||
| 605 | 74 | 0s | 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 | |||||
| 717 | sub 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  | ||||
| 727 | 9 | 0s | my ($self,$key,$value) = @_; | ||
| 728 | 9 | 0s | if(defined $value) { | ||
| 729 | 9 | 0s | my $version = $self->{data}{version} || ''; | ||
| 730 | 9 | 0s | 9 | 0s |     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 { | ||||
| 735 | 9 | 0s | 9 | 0s |       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  | ||||
| 747 | 25 | 0s | 25 | 0s |      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  | ||||
| 751 | 25 | 0s | my ($self,$key,$value) = @_; | ||
| 752 | 25 | 0s | if(defined $value) { | ||
| 753 | 25 | 0s | 25 | 0s |       my ($scheme, $auth, $path, $query, $frag) = _uri_split($value);       # spent     0s making 25 calls to CPAN::Meta::Validator::_uri_split, avg 0s/call  | 
| 754 | 25 | 0s | unless ( defined $scheme && length $scheme ) { | ||
| 755 | $self->_error( "'$value' for '$key' does not have a URL scheme" ); | ||||
| 756 | return 0; | ||||
| 757 | } | ||||
| 758 | 25 | 0s | unless ( defined $auth && length $auth ) { | ||
| 759 | $self->_error( "'$value' for '$key' does not have a URL authority" ); | ||||
| 760 | return 0; | ||||
| 761 | } | ||||
| 762 | 25 | 0s | 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  | ||||
| 770 | 13 | 0s | my ($self,$key,$value) = @_; | ||
| 771 | 13 | 0s | if(defined $value) { | ||
| 772 | 13 | 0s | 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 | |||||
| 782 | 1 | 0s | # spent 0s within CPAN::Meta::Validator::anything which was called:
#    once (0s+0s) by CPAN::Meta::Validator::check_map at line 560  | ||
| 783 | |||||
| 784 | sub string { | ||||
| 785 | 144 | 0s | my ($self,$key,$value) = @_; | ||
| 786 | 144 | 0s | if(defined $value) { | ||
| 787 | 144 | 0s | return 1 if($value || $value =~ /^0$/); | ||
| 788 | } | ||||
| 789 | $self->_error( "value is an undefined string" ); | ||||
| 790 | return 0; | ||||
| 791 | } | ||||
| 792 | |||||
| 793 | sub 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 | |||||
| 801 | sub 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  | ||||
| 809 | 42 | 0s | my ($self,$key,$value) = @_; | ||
| 810 | 42 | 0s | 42 | 0s |     if(defined $value && ($value || $value =~ /0/)) {     # spent     0s making 42 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call  | 
| 811 | 42 | 0s | my $pass = 1; | ||
| 812 | 84 | 0s | 42 | 0s |         for(split(",",$value)) { $self->version($key,$_) or ($pass = 0); }         # spent     0s making 42 calls to CPAN::Meta::Validator::version, avg 0s/call  | 
| 813 | 42 | 0s | 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  | ||||
| 821 | 94 | 0s | my ($self,$key,$value) = @_; | ||
| 822 | 94 | 0s | if(defined $value) { | ||
| 823 | 94 | 0s | 42 | 0s |         return 0    unless($value || $value =~ /0/);         # spent     0s making 42 calls to CPAN::Meta::Validator::CORE:match, avg 0s/call  | 
| 824 | 94 | 0s | 94 | 0s |         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  | ||||
| 833 | 23 | 0s | my ($self,$key,$value) = @_; | ||
| 834 | 23 | 0s | if(defined $value) { | ||
| 835 | 23 | 0s | 23 | 0s |         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 | |||||
| 843 | 1 | 0s | my %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 | |||||
| 860 | 1 | 0s | my %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 | sub license { | ||||
| 891 | 22 | 0s | my ($self,$key,$value) = @_; | ||
| 892 | 22 | 0s | my $licenses = $self->{spec} < 2 ? \%v1_licenses : \%v2_licenses; | ||
| 893 | 22 | 0s | 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 | |||||
| 902 | sub 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  | ||||
| 916 | 1 | 0s | my ($self,$key) = @_; | ||
| 917 | 1 | 0s | if(defined $key) { | ||
| 918 | 1 | 0s | 1 | 0s |         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 | } | ||||
| 922 | 1 | 0s | 1 | 0s |     $self->_error( "Custom key '$key' must begin with 'x_' or 'X_'." );     # spent     0s making 1 call to CPAN::Meta::Validator::_error  | 
| 923 | 1 | 0s | return 0; | ||
| 924 | } | ||||
| 925 | |||||
| 926 | sub 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  | ||||
| 938 | 42 | 0s | my ($self,$key) = @_; | ||
| 939 | 42 | 0s | if(defined $key) { | ||
| 940 | 42 | 0s | 42 | 0s |         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 | |||||
| 948 | 1 | 0s | my @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  | ||||
| 950 | 24 | 0s | my ($self,$key) = @_; | ||
| 951 | 24 | 0s | if(defined $key) { | ||
| 952 | 24 | 0s | 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 | |||||
| 961 | 1 | 0s | my @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  | ||||
| 963 | 24 | 0s | my ($self,$key) = @_; | ||
| 964 | 24 | 0s | if(defined $key) { | ||
| 965 | 24 | 0s | 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 | sub _error { | ||||
| 975 | 3 | 0s | my $self = shift; | ||
| 976 | 3 | 0s | my $mess = shift; | ||
| 977 | |||||
| 978 | 3 | 0s | $mess .= ' ('.join(' -> ',@{$self->{stack}}).')' if($self->{stack}); | ||
| 979 | 3 | 0s | $mess .= " [Validation: $self->{spec}]"; | ||
| 980 | |||||
| 981 | 3 | 0s | push @{$self->{errors}}, $mess; | ||
| 982 | } | ||||
| 983 | |||||
| 984 | 1 | 0s | 1; | ||
| 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  |