import Devel-Size 0.71 from CPAN
[p5sagit/Devel-Size.git] / inc / Module / Install / Metadata.pm
CommitLineData
0430b7f7 1#line 1
2package Module::Install::Metadata;
3
4use strict 'vars';
5use Module::Install::Base;
6
7use vars qw{$VERSION $ISCORE @ISA};
8BEGIN {
f44772ad 9 $VERSION = '0.77';
0430b7f7 10 $ISCORE = 1;
11 @ISA = qw{Module::Install::Base};
12}
13
14my @scalar_keys = qw{
6ea94d90 15 name
16 module_name
17 abstract
18 author
19 version
6ea94d90 20 distribution_type
6ea94d90 21 tests
22 installdirs
0430b7f7 23};
24
25my @tuple_keys = qw{
6ea94d90 26 configure_requires
27 build_requires
28 requires
29 recommends
30 bundles
f44772ad 31 resources
32};
33
34my @resource_keys = qw{
35 homepage
36 bugtracker
37 repository
0430b7f7 38};
39
f44772ad 40sub Meta { shift }
41sub Meta_ScalarKeys { @scalar_keys }
42sub Meta_TupleKeys { @tuple_keys }
43sub Meta_ResourceKeys { @resource_keys }
0430b7f7 44
f44772ad 45foreach my $key ( @scalar_keys ) {
6ea94d90 46 *$key = sub {
47 my $self = shift;
48 return $self->{values}{$key} if defined wantarray and !@_;
49 $self->{values}{$key} = shift;
50 return $self;
51 };
52}
53
f44772ad 54foreach my $key ( @resource_keys ) {
55 *$key = sub {
56 my $self = shift;
57 unless ( @_ ) {
58 return () unless $self->{values}{resources};
59 return map { $_->[1] }
60 grep { $_->[0] eq $key }
61 @{ $self->{values}{resources} };
62 }
63 return $self->{values}{resources}{$key} unless @_;
64 my $uri = shift or die(
65 "Did not provide a value to $key()"
66 );
67 $self->resources( $key => $uri );
68 return 1;
69 };
70}
71
6ea94d90 72sub requires {
73 my $self = shift;
74 while ( @_ ) {
75 my $module = shift or last;
76 my $version = shift || 0;
f44772ad 77 push @{ $self->{values}{requires} }, [ $module, $version ];
6ea94d90 78 }
79 $self->{values}{requires};
0430b7f7 80}
81
6ea94d90 82sub build_requires {
83 my $self = shift;
84 while ( @_ ) {
85 my $module = shift or last;
86 my $version = shift || 0;
f44772ad 87 push @{ $self->{values}{build_requires} }, [ $module, $version ];
6ea94d90 88 }
89 $self->{values}{build_requires};
0430b7f7 90}
91
6ea94d90 92sub configure_requires {
93 my $self = shift;
94 while ( @_ ) {
95 my $module = shift or last;
96 my $version = shift || 0;
f44772ad 97 push @{ $self->{values}{configure_requires} }, [ $module, $version ];
6ea94d90 98 }
99 $self->{values}{configure_requires};
100}
101
102sub recommends {
103 my $self = shift;
104 while ( @_ ) {
105 my $module = shift or last;
106 my $version = shift || 0;
f44772ad 107 push @{ $self->{values}{recommends} }, [ $module, $version ];
6ea94d90 108 }
109 $self->{values}{recommends};
110}
111
112sub bundles {
113 my $self = shift;
114 while ( @_ ) {
115 my $module = shift or last;
116 my $version = shift || 0;
f44772ad 117 push @{ $self->{values}{bundles} }, [ $module, $version ];
6ea94d90 118 }
119 $self->{values}{bundles};
120}
8b959707 121
f44772ad 122# Resource handling
123my %lc_resource = map { $_ => 1 } qw{
124 homepage
125 license
126 bugtracker
127 repository
128};
129
130sub resources {
131 my $self = shift;
132 while ( @_ ) {
133 my $name = shift or last;
134 my $value = shift or next;
135 if ( $name eq lc $name and ! $lc_resource{$name} ) {
136 die("Unsupported reserved lowercase resource '$name'");
137 }
138 $self->{values}{resources} ||= [];
139 push @{ $self->{values}{resources} }, [ $name, $value ];
140 }
141 $self->{values}{resources};
142}
143
8b959707 144# Aliases for build_requires that will have alternative
145# meanings in some future version of META.yml.
6ea94d90 146sub test_requires { shift->build_requires(@_) }
147sub install_requires { shift->build_requires(@_) }
8b959707 148
149# Aliases for installdirs options
150sub install_as_core { $_[0]->installdirs('perl') }
151sub install_as_cpan { $_[0]->installdirs('site') }
152sub install_as_site { $_[0]->installdirs('site') }
153sub install_as_vendor { $_[0]->installdirs('vendor') }
b1e5ad85 154
0430b7f7 155sub sign {
6ea94d90 156 my $self = shift;
f44772ad 157 return $self->{values}{sign} if defined wantarray and ! @_;
158 $self->{values}{sign} = ( @_ ? $_[0] : 1 );
6ea94d90 159 return $self;
0430b7f7 160}
161
162sub dynamic_config {
163 my $self = shift;
164 unless ( @_ ) {
f44772ad 165 warn "You MUST provide an explicit true/false value to dynamic_config\n";
0430b7f7 166 return $self;
167 }
6ea94d90 168 $self->{values}{dynamic_config} = $_[0] ? 1 : 0;
f44772ad 169 return 1;
170}
171
172sub perl_version {
173 my $self = shift;
174 return $self->{values}{perl_version} unless @_;
175 my $version = shift or die(
176 "Did not provide a value to perl_version()"
177 );
178
179 # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to
180 # numbers (eg, 5.006001 or 5.008009).
181
182 $version =~ s/^(\d+)\.(\d+)\.(\d+)$/sprintf("%d.%03d%03d",$1,$2,$3)/e;
183
184 $version =~ s/_.+$//;
185 $version = $version + 0; # Numify
186 unless ( $version >= 5.005 ) {
187 die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n";
188 }
189 $self->{values}{perl_version} = $version;
190 return 1;
191}
192
193sub license {
194 my $self = shift;
195 return $self->{values}{license} unless @_;
196 my $license = shift or die(
197 'Did not provide a value to license()'
198 );
199 $self->{values}{license} = $license;
200
201 # Automatically fill in license URLs
202 if ( $license eq 'perl' ) {
203 $self->resources( license => 'http://dev.perl.org/licenses/' );
204 }
205
206 return 1;
0430b7f7 207}
208
209sub all_from {
6ea94d90 210 my ( $self, $file ) = @_;
211
212 unless ( defined($file) ) {
f44772ad 213 my $name = $self->name or die(
214 "all_from called with no args without setting name() first"
215 );
6ea94d90 216 $file = join('/', 'lib', split(/-/, $name)) . '.pm';
217 $file =~ s{.*/}{} unless -e $file;
f44772ad 218 unless ( -e $file ) {
219 die("all_from cannot find $file from $name");
220 }
221 }
222 unless ( -f $file ) {
223 die("The path '$file' does not exist, or is not a file");
6ea94d90 224 }
225
226 # Some methods pull from POD instead of code.
227 # If there is a matching .pod, use that instead
228 my $pod = $file;
229 $pod =~ s/\.pm$/.pod/i;
230 $pod = $file unless -e $pod;
231
232 # Pull the different values
233 $self->name_from($file) unless $self->name;
234 $self->version_from($file) unless $self->version;
235 $self->perl_version_from($file) unless $self->perl_version;
236 $self->author_from($pod) unless $self->author;
237 $self->license_from($pod) unless $self->license;
238 $self->abstract_from($pod) unless $self->abstract;
239
240 return 1;
0430b7f7 241}
242
243sub provides {
6ea94d90 244 my $self = shift;
245 my $provides = ( $self->{values}{provides} ||= {} );
246 %$provides = (%$provides, @_) if @_;
247 return $provides;
0430b7f7 248}
249
250sub auto_provides {
6ea94d90 251 my $self = shift;
252 return $self unless $self->is_admin;
253 unless (-e 'MANIFEST') {
254 warn "Cannot deduce auto_provides without a MANIFEST, skipping\n";
255 return $self;
256 }
257 # Avoid spurious warnings as we are not checking manifest here.
258 local $SIG{__WARN__} = sub {1};
259 require ExtUtils::Manifest;
260 local *ExtUtils::Manifest::manicheck = sub { return };
261
262 require Module::Build;
263 my $build = Module::Build->new(
264 dist_name => $self->name,
265 dist_version => $self->version,
266 license => $self->license,
267 );
268 $self->provides( %{ $build->find_dist_packages || {} } );
0430b7f7 269}
270
271sub feature {
6ea94d90 272 my $self = shift;
273 my $name = shift;
274 my $features = ( $self->{values}{features} ||= [] );
275 my $mods;
276
277 if ( @_ == 1 and ref( $_[0] ) ) {
278 # The user used ->feature like ->features by passing in the second
279 # argument as a reference. Accomodate for that.
280 $mods = $_[0];
281 } else {
282 $mods = \@_;
283 }
284
285 my $count = 0;
286 push @$features, (
287 $name => [
288 map {
289 ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_
290 } @$mods
291 ]
292 );
293
294 return @$features;
0430b7f7 295}
296
297sub features {
6ea94d90 298 my $self = shift;
299 while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) {
300 $self->feature( $name, @$mods );
301 }
f44772ad 302 return $self->{values}{features}
303 ? @{ $self->{values}{features} }
6ea94d90 304 : ();
0430b7f7 305}
306
307sub no_index {
6ea94d90 308 my $self = shift;
309 my $type = shift;
310 push @{ $self->{values}{no_index}{$type} }, @_ if $type;
311 return $self->{values}{no_index};
0430b7f7 312}
313
314sub read {
6ea94d90 315 my $self = shift;
316 $self->include_deps( 'YAML::Tiny', 0 );
317
318 require YAML::Tiny;
319 my $data = YAML::Tiny::LoadFile('META.yml');
320
321 # Call methods explicitly in case user has already set some values.
322 while ( my ( $key, $value ) = each %$data ) {
323 next unless $self->can($key);
324 if ( ref $value eq 'HASH' ) {
325 while ( my ( $module, $version ) = each %$value ) {
326 $self->can($key)->($self, $module => $version );
327 }
328 } else {
329 $self->can($key)->($self, $value);
330 }
331 }
332 return $self;
0430b7f7 333}
334
335sub write {
6ea94d90 336 my $self = shift;
337 return $self unless $self->is_admin;
338 $self->admin->write_meta;
339 return $self;
0430b7f7 340}
341
342sub version_from {
6ea94d90 343 require ExtUtils::MM_Unix;
344 my ( $self, $file ) = @_;
345 $self->version( ExtUtils::MM_Unix->parse_version($file) );
0430b7f7 346}
347
348sub abstract_from {
6ea94d90 349 require ExtUtils::MM_Unix;
350 my ( $self, $file ) = @_;
351 $self->abstract(
352 bless(
353 { DISTNAME => $self->name },
354 'ExtUtils::MM_Unix'
355 )->parse_abstract($file)
356 );
0430b7f7 357}
358
f44772ad 359# Add both distribution and module name
6ea94d90 360sub name_from {
f44772ad 361 my ($self, $file) = @_;
6ea94d90 362 if (
f44772ad 363 Module::Install::_read($file) =~ m/
364 ^ \s*
6ea94d90 365 package \s*
366 ([\w:]+)
367 \s* ;
368 /ixms
369 ) {
f44772ad 370 my ($name, $module_name) = ($1, $1);
6ea94d90 371 $name =~ s{::}{-}g;
372 $self->name($name);
f44772ad 373 unless ( $self->module_name ) {
374 $self->module_name($module_name);
375 }
6ea94d90 376 } else {
f44772ad 377 die("Cannot determine name from $file\n");
6ea94d90 378 }
0430b7f7 379}
380
381sub perl_version_from {
6ea94d90 382 my $self = shift;
383 if (
384 Module::Install::_read($_[0]) =~ m/
385 ^
f44772ad 386 (?:use|require) \s*
6ea94d90 387 v?
388 ([\d_\.]+)
389 \s* ;
390 /ixms
391 ) {
392 my $perl_version = $1;
393 $perl_version =~ s{_}{}g;
394 $self->perl_version($perl_version);
395 } else {
396 warn "Cannot determine perl version info from $_[0]\n";
397 return;
398 }
0430b7f7 399}
400
401sub author_from {
6ea94d90 402 my $self = shift;
403 my $content = Module::Install::_read($_[0]);
404 if ($content =~ m/
405 =head \d \s+ (?:authors?)\b \s*
406 ([^\n]*)
407 |
408 =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s*
409 .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s*
410 ([^\n]*)
411 /ixms) {
412 my $author = $1 || $2;
413 $author =~ s{E<lt>}{<}g;
414 $author =~ s{E<gt>}{>}g;
415 $self->author($author);
416 } else {
417 warn "Cannot determine author info from $_[0]\n";
418 }
0430b7f7 419}
420
421sub license_from {
6ea94d90 422 my $self = shift;
423 if (
424 Module::Install::_read($_[0]) =~ m/
425 (
426 =head \d \s+
427 (?:licen[cs]e|licensing|copyright|legal)\b
428 .*?
429 )
430 (=head\\d.*|=cut.*|)
431 \z
432 /ixms ) {
433 my $license_text = $1;
434 my @phrases = (
435 'under the same (?:terms|license) as perl itself' => 'perl', 1,
f44772ad 436 'GNU general public license' => 'gpl', 1,
6ea94d90 437 'GNU public license' => 'gpl', 1,
f44772ad 438 'GNU lesser general public license' => 'lgpl', 1,
6ea94d90 439 'GNU lesser public license' => 'lgpl', 1,
f44772ad 440 'GNU library general public license' => 'lgpl', 1,
441 'GNU library public license' => 'lgpl', 1,
6ea94d90 442 'BSD license' => 'bsd', 1,
443 'Artistic license' => 'artistic', 1,
444 'GPL' => 'gpl', 1,
445 'LGPL' => 'lgpl', 1,
446 'BSD' => 'bsd', 1,
447 'Artistic' => 'artistic', 1,
448 'MIT' => 'mit', 1,
449 'proprietary' => 'proprietary', 0,
450 );
451 while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
452 $pattern =~ s{\s+}{\\s+}g;
453 if ( $license_text =~ /\b$pattern\b/i ) {
454 if ( $osi and $license_text =~ /All rights reserved/i ) {
f44772ad 455 print "WARNING: 'All rights reserved' in copyright may invalidate Open Source license.\n";
6ea94d90 456 }
457 $self->license($license);
458 return 1;
459 }
8b959707 460 }
6ea94d90 461 }
462
463 warn "Cannot determine license info from $_[0]\n";
464 return 'unknown';
0430b7f7 465}
466
f44772ad 467sub bugtracker_from {
468 my $self = shift;
469 my $content = Module::Install::_read($_[0]);
470 my @links = $content =~ m/L\<(http\:\/\/rt\.cpan\.org\/[^>]+)\>/g;
471 unless ( @links ) {
472 warn "Cannot determine bugtracker info from $_[0]\n";
473 return 0;
474 }
475 if ( @links > 1 ) {
476 warn "Found more than on rt.cpan.org link in $_[0]\n";
477 return 0;
478 }
479
480 # Set the bugtracker
481 bugtracker( $links[0] );
482 return 1;
483}
484
485sub install_script {
486 my $self = shift;
487 my $args = $self->makemaker_args;
488 my $exe = $args->{EXE_FILES} ||= [];
489 foreach ( @_ ) {
490 if ( -f $_ ) {
491 push @$exe, $_;
492 } elsif ( -d 'script' and -f "script/$_" ) {
493 push @$exe, "script/$_";
494 } else {
495 die("Cannot find script '$_'");
496 }
497 }
498}
499
0430b7f7 5001;