Codebase list libdbix-class-inflatecolumn-ip-perl / 2ea6850
[svn-inject] Installing original source of libdbix-class-inflatecolumn-ip-perl (0.02001) Jonathan Yu 13 years ago
28 changed file(s) with 2751 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Revision history for DBIx::Class::InflateColumn::IP
1
2 0.02001 Sun Jun 17 20:27:34 2007
3 - Initial version of format autodetection, based solely on column type.
4
5 0.02000 Thu May 24 11:28:40 2007
6 - First release uploaded to CPAN.
7 - Added configuration options for format and class.
8
9 0.01 Wed May 23 14:53:10 2007
10 - First version, released on an unsuspecting world.
11
0 Changes
1 inc/Module/AutoInstall.pm
2 inc/Module/Install.pm
3 inc/Module/Install/AutoInstall.pm
4 inc/Module/Install/Base.pm
5 inc/Module/Install/Can.pm
6 inc/Module/Install/Fetch.pm
7 inc/Module/Install/Include.pm
8 inc/Module/Install/Makefile.pm
9 inc/Module/Install/Metadata.pm
10 inc/Module/Install/Win32.pm
11 inc/Module/Install/WriteAll.pm
12 lib/DBIx/Class/InflateColumn/IP.pm
13 Makefile.PL
14 MANIFEST
15 META.yml # Will be created by "make dist"
16 README
17 t/00-load.t
18 t/01-ip.t
19 t/boilerplate.t
20 t/lib/DBICTest.pm
21 t/lib/DBICTest/Schema.pm
22 t/lib/DBICTest/Schema/Host.pm
23 t/lib/DBICTest/Schema/Network.pm
24 t/lib/sqlite.sql
25 t/pod-coverage.t
26 t/pod.t
27 t/style-notabs.t
0 ---
1 abstract: Auto-create NetAddr::IP objects from columns.
2 author: "Dagfinn Ilmari Manns\xE5ker, C<< <ilmari at ilmari.org> >>"
3 distribution_type: module
4 generated_by: Module::Install version 0.67
5 license: perl
6 meta-spec:
7 url: http://module-build.sourceforge.net/META-spec-v1.3.html
8 version: 1.3
9 name: DBIx-Class-InflateColumn-IP
10 no_index:
11 directory:
12 - inc
13 - t
14 requires:
15 DBIx::Class: 0.07005
16 NetAddr::IP: 0
17 perl: 5.6.1
18 tests: t/*.t
19 version: 0.02001
0 use strict;
1 use warnings;
2 use inc::Module::Install 0.65;
3
4 name 'DBIx-Class-InflateColumn-IP';
5 license 'perl';
6 perl_version '5.006001';
7 all_from 'lib/DBIx/Class/InflateColumn/IP.pm';
8
9 requires 'DBIx::Class' => 0.07005;
10 requires 'NetAddr::IP';
11
12 tests 't/*.t';
13 clean_files 'DBIx-Class-InflateColumn-IP-* t/var README';
14
15 eval {
16 system 'pod2text lib/DBIx/Class/InflateColumn/IP.pm > README';
17 };
18
19 auto_install;
20 WriteAll;
0 NAME
1 DBIx::Class::InflateColumn::IP - Auto-create NetAddr::IP objects from
2 columns.
3
4 SYNOPSIS
5 Load this component and declare columns as IP addresses with the
6 appropriate format.
7
8 package Host;
9 __PACKAGE__->load_components(qw/InflateColumn::IP Core/);
10 __PACKAGE__->add_columns(
11 ip_address => {
12 data_type => 'integer',
13 is_nullable => 0,
14 is_ip => 1,
15 ip_format => 'numeric',
16 }
17 );
18
19 package Network;
20 __PACKAGE__->load_components(qw/InflateColumn::IP Core/);
21 __PACKAGE__->add_columns(
22 address => {
23 data_type => 'varchar',
24 size => 18
25 is_nullable => 0,
26 is_ip => 1,
27 ip_format => 'cidr',
28 }
29 );
30
31 Then you can treat the specified column as a NetAddr::IP object.
32
33 print 'IP address: ', $host->ip_address->addr;
34 print 'Address type: ', $host->ip_address->iptype;
35
36 DBIx::Class::InflateColumn::IP supports a limited amount of
37 auto-detection of the format based on the column type. If the type
38 begins with "int", it's assumed to be numeric, while "inet" and "cidr"
39 (as used by e.g. PostgreSQL) are assumed to be "cidr" format.
40
41 METHODS
42 ip_class
43 Arguments: $class
44
45 Gets/sets the address class that the columns should be inflated into.
46 The default class is NetAddr::IP.
47
48 ip_format
49 Arguments: $format
50
51 Gets/sets the name of the method used to deflate the address for the
52 database. This must return a value suitable for "$ip_class-"new(); The
53 default format is "addr", which returns the address in dotted-quad
54 notation. See "Methods" in NetAddr::IP for suitable values.
55
56 register_column
57 Chains with "register_column" in DBIx::Class::Row, and sets up IP
58 address columns appropriately. This would not normally be called
59 directly by end users.
60
61 AUTHOR
62 Dagfinn Ilmari Mannsåker, "<ilmari at ilmari.org>"
63
64 BUGS
65 Please report any bugs or feature requests to
66 "bug-dbix-class-inflatecolumn-ip at rt.cpan.org", or through the web
67 interface at
68 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBIx-Class-InflateColumn
69 -IP>. I will be notified, and then you'll automatically be notified of
70 progress on your bug as I make changes.
71
72 SUPPORT
73 You can find documentation for this module with the perldoc command.
74
75 perldoc DBIx::Class::InflateColumn::IP
76
77 You can also look for information at:
78
79 * AnnoCPAN: Annotated CPAN documentation
80 <http://annocpan.org/dist/DBIx-Class-InflateColumn-IP>
81
82 * CPAN Ratings
83 <http://cpanratings.perl.org/d/DBIx-Class-InflateColumn-IP>
84
85 * RT: CPAN's request tracker
86 <http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBIx-Class-InflateColumn-I
87 P>
88
89 * Search CPAN
90 <http://search.cpan.org/dist/DBIx-Class-InflateColumn-IP>
91
92 SEE ALSO
93 DBIx::Class, NetAddr::IP
94
95 COPYRIGHT & LICENSE
96 Copyright 2007 Dagfinn Ilmari Mannsåker, all rights reserved.
97
98 This program is free software; you can redistribute it and/or modify it
99 under the same terms as Perl itself.
100
0 #line 1
1 package Module::AutoInstall;
2
3 use strict;
4 use Cwd ();
5 use ExtUtils::MakeMaker ();
6
7 use vars qw{$VERSION};
8 BEGIN {
9 $VERSION = '1.03';
10 }
11
12 # special map on pre-defined feature sets
13 my %FeatureMap = (
14 '' => 'Core Features', # XXX: deprecated
15 '-core' => 'Core Features',
16 );
17
18 # various lexical flags
19 my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS );
20 my ( $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly );
21 my ( $PostambleActions, $PostambleUsed );
22
23 # See if it's a testing or non-interactive session
24 _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN );
25 _init();
26
27 sub _accept_default {
28 $AcceptDefault = shift;
29 }
30
31 sub missing_modules {
32 return @Missing;
33 }
34
35 sub do_install {
36 __PACKAGE__->install(
37 [
38 $Config
39 ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
40 : ()
41 ],
42 @Missing,
43 );
44 }
45
46 # initialize various flags, and/or perform install
47 sub _init {
48 foreach my $arg (
49 @ARGV,
50 split(
51 /[\s\t]+/,
52 $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || ''
53 )
54 )
55 {
56 if ( $arg =~ /^--config=(.*)$/ ) {
57 $Config = [ split( ',', $1 ) ];
58 }
59 elsif ( $arg =~ /^--installdeps=(.*)$/ ) {
60 __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) );
61 exit 0;
62 }
63 elsif ( $arg =~ /^--default(?:deps)?$/ ) {
64 $AcceptDefault = 1;
65 }
66 elsif ( $arg =~ /^--check(?:deps)?$/ ) {
67 $CheckOnly = 1;
68 }
69 elsif ( $arg =~ /^--skip(?:deps)?$/ ) {
70 $SkipInstall = 1;
71 }
72 elsif ( $arg =~ /^--test(?:only)?$/ ) {
73 $TestOnly = 1;
74 }
75 }
76 }
77
78 # overrides MakeMaker's prompt() to automatically accept the default choice
79 sub _prompt {
80 goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault;
81
82 my ( $prompt, $default ) = @_;
83 my $y = ( $default =~ /^[Yy]/ );
84
85 print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] ';
86 print "$default\n";
87 return $default;
88 }
89
90 # the workhorse
91 sub import {
92 my $class = shift;
93 my @args = @_ or return;
94 my $core_all;
95
96 print "*** $class version " . $class->VERSION . "\n";
97 print "*** Checking for Perl dependencies...\n";
98
99 my $cwd = Cwd::cwd();
100
101 $Config = [];
102
103 my $maxlen = length(
104 (
105 sort { length($b) <=> length($a) }
106 grep { /^[^\-]/ }
107 map {
108 ref($_)
109 ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} )
110 : ''
111 }
112 map { +{@args}->{$_} }
113 grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} }
114 )[0]
115 );
116
117 while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) {
118 my ( @required, @tests, @skiptests );
119 my $default = 1;
120 my $conflict = 0;
121
122 if ( $feature =~ m/^-(\w+)$/ ) {
123 my $option = lc($1);
124
125 # check for a newer version of myself
126 _update_to( $modules, @_ ) and return if $option eq 'version';
127
128 # sets CPAN configuration options
129 $Config = $modules if $option eq 'config';
130
131 # promote every features to core status
132 $core_all = ( $modules =~ /^all$/i ) and next
133 if $option eq 'core';
134
135 next unless $option eq 'core';
136 }
137
138 print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n";
139
140 $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' );
141
142 unshift @$modules, -default => &{ shift(@$modules) }
143 if ( ref( $modules->[0] ) eq 'CODE' ); # XXX: bugward combatability
144
145 while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) {
146 if ( $mod =~ m/^-(\w+)$/ ) {
147 my $option = lc($1);
148
149 $default = $arg if ( $option eq 'default' );
150 $conflict = $arg if ( $option eq 'conflict' );
151 @tests = @{$arg} if ( $option eq 'tests' );
152 @skiptests = @{$arg} if ( $option eq 'skiptests' );
153
154 next;
155 }
156
157 printf( "- %-${maxlen}s ...", $mod );
158
159 if ( $arg and $arg =~ /^\D/ ) {
160 unshift @$modules, $arg;
161 $arg = 0;
162 }
163
164 # XXX: check for conflicts and uninstalls(!) them.
165 if (
166 defined( my $cur = _version_check( _load($mod), $arg ||= 0 ) ) )
167 {
168 print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n";
169 push @Existing, $mod => $arg;
170 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
171 }
172 else {
173 print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n";
174 push @required, $mod => $arg;
175 }
176 }
177
178 next unless @required;
179
180 my $mandatory = ( $feature eq '-core' or $core_all );
181
182 if (
183 !$SkipInstall
184 and (
185 $CheckOnly
186 or _prompt(
187 qq{==> Auto-install the }
188 . ( @required / 2 )
189 . ( $mandatory ? ' mandatory' : ' optional' )
190 . qq{ module(s) from CPAN?},
191 $default ? 'y' : 'n',
192 ) =~ /^[Yy]/
193 )
194 )
195 {
196 push( @Missing, @required );
197 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
198 }
199
200 elsif ( !$SkipInstall
201 and $default
202 and $mandatory
203 and
204 _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', )
205 =~ /^[Nn]/ )
206 {
207 push( @Missing, @required );
208 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
209 }
210
211 else {
212 $DisabledTests{$_} = 1 for map { glob($_) } @tests;
213 }
214 }
215
216 $UnderCPAN = _check_lock(); # check for $UnderCPAN
217
218 if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) {
219 require Config;
220 print
221 "*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n";
222
223 # make an educated guess of whether we'll need root permission.
224 print " (You may need to do that as the 'root' user.)\n"
225 if eval '$>';
226 }
227 print "*** $class configuration finished.\n";
228
229 chdir $cwd;
230
231 # import to main::
232 no strict 'refs';
233 *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main';
234 }
235
236 # Check to see if we are currently running under CPAN.pm and/or CPANPLUS;
237 # if we are, then we simply let it taking care of our dependencies
238 sub _check_lock {
239 return unless @Missing;
240
241 if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) {
242 print <<'END_MESSAGE';
243
244 *** Since we're running under CPANPLUS, I'll just let it take care
245 of the dependency's installation later.
246 END_MESSAGE
247 return 1;
248 }
249
250 _load_cpan();
251
252 # Find the CPAN lock-file
253 my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" );
254 return unless -f $lock;
255
256 # Check the lock
257 local *LOCK;
258 return unless open(LOCK, $lock);
259
260 if (
261 ( $^O eq 'MSWin32' ? _under_cpan() : <LOCK> == getppid() )
262 and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore'
263 ) {
264 print <<'END_MESSAGE';
265
266 *** Since we're running under CPAN, I'll just let it take care
267 of the dependency's installation later.
268 END_MESSAGE
269 return 1;
270 }
271
272 close LOCK;
273 return;
274 }
275
276 sub install {
277 my $class = shift;
278
279 my $i; # used below to strip leading '-' from config keys
280 my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } );
281
282 my ( @modules, @installed );
283 while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) {
284
285 # grep out those already installed
286 if ( defined( _version_check( _load($pkg), $ver ) ) ) {
287 push @installed, $pkg;
288 }
289 else {
290 push @modules, $pkg, $ver;
291 }
292 }
293
294 return @installed unless @modules; # nothing to do
295 return @installed if _check_lock(); # defer to the CPAN shell
296
297 print "*** Installing dependencies...\n";
298
299 return unless _connected_to('cpan.org');
300
301 my %args = @config;
302 my %failed;
303 local *FAILED;
304 if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) {
305 while (<FAILED>) { chomp; $failed{$_}++ }
306 close FAILED;
307
308 my @newmod;
309 while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) {
310 push @newmod, ( $k => $v ) unless $failed{$k};
311 }
312 @modules = @newmod;
313 }
314
315 if ( _has_cpanplus() ) {
316 _install_cpanplus( \@modules, \@config );
317 } else {
318 _install_cpan( \@modules, \@config );
319 }
320
321 print "*** $class installation finished.\n";
322
323 # see if we have successfully installed them
324 while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
325 if ( defined( _version_check( _load($pkg), $ver ) ) ) {
326 push @installed, $pkg;
327 }
328 elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) {
329 print FAILED "$pkg\n";
330 }
331 }
332
333 close FAILED if $args{do_once};
334
335 return @installed;
336 }
337
338 sub _install_cpanplus {
339 my @modules = @{ +shift };
340 my @config = _cpanplus_config( @{ +shift } );
341 my $installed = 0;
342
343 require CPANPLUS::Backend;
344 my $cp = CPANPLUS::Backend->new;
345 my $conf = $cp->configure_object;
346
347 return unless $conf->can('conf') # 0.05x+ with "sudo" support
348 or _can_write($conf->_get_build('base')); # 0.04x
349
350 # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
351 my $makeflags = $conf->get_conf('makeflags') || '';
352 if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) {
353 # 0.03+ uses a hashref here
354 $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST};
355
356 } else {
357 # 0.02 and below uses a scalar
358 $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' )
359 if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } );
360
361 }
362 $conf->set_conf( makeflags => $makeflags );
363 $conf->set_conf( prereqs => 1 );
364
365
366
367 while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) {
368 $conf->set_conf( $key, $val );
369 }
370
371 my $modtree = $cp->module_tree;
372 while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
373 print "*** Installing $pkg...\n";
374
375 MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall;
376
377 my $success;
378 my $obj = $modtree->{$pkg};
379
380 if ( $obj and defined( _version_check( $obj->{version}, $ver ) ) ) {
381 my $pathname = $pkg;
382 $pathname =~ s/::/\\W/;
383
384 foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) {
385 delete $INC{$inc};
386 }
387
388 my $rv = $cp->install( modules => [ $obj->{module} ] );
389
390 if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) {
391 print "*** $pkg successfully installed.\n";
392 $success = 1;
393 } else {
394 print "*** $pkg installation cancelled.\n";
395 $success = 0;
396 }
397
398 $installed += $success;
399 } else {
400 print << ".";
401 *** Could not find a version $ver or above for $pkg; skipping.
402 .
403 }
404
405 MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall;
406 }
407
408 return $installed;
409 }
410
411 sub _cpanplus_config {
412 my @config = ();
413 while ( @_ ) {
414 my ($key, $value) = (shift(), shift());
415 if ( $key eq 'prerequisites_policy' ) {
416 if ( $value eq 'follow' ) {
417 $value = CPANPLUS::Internals::Constants::PREREQ_INSTALL();
418 } elsif ( $value eq 'ask' ) {
419 $value = CPANPLUS::Internals::Constants::PREREQ_ASK();
420 } elsif ( $value eq 'ignore' ) {
421 $value = CPANPLUS::Internals::Constants::PREREQ_IGNORE();
422 } else {
423 die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n";
424 }
425 } else {
426 die "*** Cannot convert option $key to CPANPLUS version.\n";
427 }
428 }
429 return @config;
430 }
431
432 sub _install_cpan {
433 my @modules = @{ +shift };
434 my @config = @{ +shift };
435 my $installed = 0;
436 my %args;
437
438 _load_cpan();
439 require Config;
440
441 if (CPAN->VERSION < 1.80) {
442 # no "sudo" support, probe for writableness
443 return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) )
444 and _can_write( $Config::Config{sitelib} );
445 }
446
447 # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
448 my $makeflags = $CPAN::Config->{make_install_arg} || '';
449 $CPAN::Config->{make_install_arg} =
450 join( ' ', split( ' ', $makeflags ), 'UNINST=1' )
451 if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } );
452
453 # don't show start-up info
454 $CPAN::Config->{inhibit_startup_message} = 1;
455
456 # set additional options
457 while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) {
458 ( $args{$opt} = $arg, next )
459 if $opt =~ /^force$/; # pseudo-option
460 $CPAN::Config->{$opt} = $arg;
461 }
462
463 local $CPAN::Config->{prerequisites_policy} = 'follow';
464
465 while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
466 MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall;
467
468 print "*** Installing $pkg...\n";
469
470 my $obj = CPAN::Shell->expand( Module => $pkg );
471 my $success = 0;
472
473 if ( $obj and defined( _version_check( $obj->cpan_version, $ver ) ) ) {
474 my $pathname = $pkg;
475 $pathname =~ s/::/\\W/;
476
477 foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) {
478 delete $INC{$inc};
479 }
480
481 my $rv = $args{force} ? CPAN::Shell->force( install => $pkg )
482 : CPAN::Shell->install($pkg);
483 $rv ||= eval {
484 $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, )
485 ->{install}
486 if $CPAN::META;
487 };
488
489 if ( $rv eq 'YES' ) {
490 print "*** $pkg successfully installed.\n";
491 $success = 1;
492 }
493 else {
494 print "*** $pkg installation failed.\n";
495 $success = 0;
496 }
497
498 $installed += $success;
499 }
500 else {
501 print << ".";
502 *** Could not find a version $ver or above for $pkg; skipping.
503 .
504 }
505
506 MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall;
507 }
508
509 return $installed;
510 }
511
512 sub _has_cpanplus {
513 return (
514 $HasCPANPLUS = (
515 $INC{'CPANPLUS/Config.pm'}
516 or _load('CPANPLUS::Shell::Default')
517 )
518 );
519 }
520
521 # make guesses on whether we're under the CPAN installation directory
522 sub _under_cpan {
523 require Cwd;
524 require File::Spec;
525
526 my $cwd = File::Spec->canonpath( Cwd::cwd() );
527 my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} );
528
529 return ( index( $cwd, $cpan ) > -1 );
530 }
531
532 sub _update_to {
533 my $class = __PACKAGE__;
534 my $ver = shift;
535
536 return
537 if defined( _version_check( _load($class), $ver ) ); # no need to upgrade
538
539 if (
540 _prompt( "==> A newer version of $class ($ver) is required. Install?",
541 'y' ) =~ /^[Nn]/
542 )
543 {
544 die "*** Please install $class $ver manually.\n";
545 }
546
547 print << ".";
548 *** Trying to fetch it from CPAN...
549 .
550
551 # install ourselves
552 _load($class) and return $class->import(@_)
553 if $class->install( [], $class, $ver );
554
555 print << '.'; exit 1;
556
557 *** Cannot bootstrap myself. :-( Installation terminated.
558 .
559 }
560
561 # check if we're connected to some host, using inet_aton
562 sub _connected_to {
563 my $site = shift;
564
565 return (
566 ( _load('Socket') and Socket::inet_aton($site) ) or _prompt(
567 qq(
568 *** Your host cannot resolve the domain name '$site', which
569 probably means the Internet connections are unavailable.
570 ==> Should we try to install the required module(s) anyway?), 'n'
571 ) =~ /^[Yy]/
572 );
573 }
574
575 # check if a directory is writable; may create it on demand
576 sub _can_write {
577 my $path = shift;
578 mkdir( $path, 0755 ) unless -e $path;
579
580 return 1 if -w $path;
581
582 print << ".";
583 *** You are not allowed to write to the directory '$path';
584 the installation may fail due to insufficient permissions.
585 .
586
587 if (
588 eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt(
589 qq(
590 ==> Should we try to re-execute the autoinstall process with 'sudo'?),
591 ((-t STDIN) ? 'y' : 'n')
592 ) =~ /^[Yy]/
593 )
594 {
595
596 # try to bootstrap ourselves from sudo
597 print << ".";
598 *** Trying to re-execute the autoinstall process with 'sudo'...
599 .
600 my $missing = join( ',', @Missing );
601 my $config = join( ',',
602 UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
603 if $Config;
604
605 return
606 unless system( 'sudo', $^X, $0, "--config=$config",
607 "--installdeps=$missing" );
608
609 print << ".";
610 *** The 'sudo' command exited with error! Resuming...
611 .
612 }
613
614 return _prompt(
615 qq(
616 ==> Should we try to install the required module(s) anyway?), 'n'
617 ) =~ /^[Yy]/;
618 }
619
620 # load a module and return the version it reports
621 sub _load {
622 my $mod = pop; # class/instance doesn't matter
623 my $file = $mod;
624
625 $file =~ s|::|/|g;
626 $file .= '.pm';
627
628 local $@;
629 return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 );
630 }
631
632 # Load CPAN.pm and it's configuration
633 sub _load_cpan {
634 return if $CPAN::VERSION;
635 require CPAN;
636 if ( $CPAN::HandleConfig::VERSION ) {
637 # Newer versions of CPAN have a HandleConfig module
638 CPAN::HandleConfig->load;
639 } else {
640 # Older versions had the load method in Config directly
641 CPAN::Config->load;
642 }
643 }
644
645 # compare two versions, either use Sort::Versions or plain comparison
646 sub _version_check {
647 my ( $cur, $min ) = @_;
648 return unless defined $cur;
649
650 $cur =~ s/\s+$//;
651
652 # check for version numbers that are not in decimal format
653 if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) {
654 if ( ( $version::VERSION or defined( _load('version') )) and
655 version->can('new')
656 ) {
657
658 # use version.pm if it is installed.
659 return (
660 ( version->new($cur) >= version->new($min) ) ? $cur : undef );
661 }
662 elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) )
663 {
664
665 # use Sort::Versions as the sorting algorithm for a.b.c versions
666 return ( ( Sort::Versions::versioncmp( $cur, $min ) != -1 )
667 ? $cur
668 : undef );
669 }
670
671 warn "Cannot reliably compare non-decimal formatted versions.\n"
672 . "Please install version.pm or Sort::Versions.\n";
673 }
674
675 # plain comparison
676 local $^W = 0; # shuts off 'not numeric' bugs
677 return ( $cur >= $min ? $cur : undef );
678 }
679
680 # nothing; this usage is deprecated.
681 sub main::PREREQ_PM { return {}; }
682
683 sub _make_args {
684 my %args = @_;
685
686 $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing }
687 if $UnderCPAN or $TestOnly;
688
689 if ( $args{EXE_FILES} and -e 'MANIFEST' ) {
690 require ExtUtils::Manifest;
691 my $manifest = ExtUtils::Manifest::maniread('MANIFEST');
692
693 $args{EXE_FILES} =
694 [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ];
695 }
696
697 $args{test}{TESTS} ||= 't/*.t';
698 $args{test}{TESTS} = join( ' ',
699 grep { !exists( $DisabledTests{$_} ) }
700 map { glob($_) } split( /\s+/, $args{test}{TESTS} ) );
701
702 my $missing = join( ',', @Missing );
703 my $config =
704 join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
705 if $Config;
706
707 $PostambleActions = (
708 $missing
709 ? "\$(PERL) $0 --config=$config --installdeps=$missing"
710 : "\$(NOECHO) \$(NOOP)"
711 );
712
713 return %args;
714 }
715
716 # a wrapper to ExtUtils::MakeMaker::WriteMakefile
717 sub Write {
718 require Carp;
719 Carp::croak "WriteMakefile: Need even number of args" if @_ % 2;
720
721 if ($CheckOnly) {
722 print << ".";
723 *** Makefile not written in check-only mode.
724 .
725 return;
726 }
727
728 my %args = _make_args(@_);
729
730 no strict 'refs';
731
732 $PostambleUsed = 0;
733 local *MY::postamble = \&postamble unless defined &MY::postamble;
734 ExtUtils::MakeMaker::WriteMakefile(%args);
735
736 print << "." unless $PostambleUsed;
737 *** WARNING: Makefile written with customized MY::postamble() without
738 including contents from Module::AutoInstall::postamble() --
739 auto installation features disabled. Please contact the author.
740 .
741
742 return 1;
743 }
744
745 sub postamble {
746 $PostambleUsed = 1;
747
748 return << ".";
749
750 config :: installdeps
751 \t\$(NOECHO) \$(NOOP)
752
753 checkdeps ::
754 \t\$(PERL) $0 --checkdeps
755
756 installdeps ::
757 \t$PostambleActions
758
759 .
760
761 }
762
763 1;
764
765 __END__
766
767 #line 1003
0 #line 1
1 package Module::Install::AutoInstall;
2
3 use strict;
4 use Module::Install::Base;
5
6 use vars qw{$VERSION $ISCORE @ISA};
7 BEGIN {
8 $VERSION = '0.67';
9 $ISCORE = 1;
10 @ISA = qw{Module::Install::Base};
11 }
12
13 sub AutoInstall { $_[0] }
14
15 sub run {
16 my $self = shift;
17 $self->auto_install_now(@_);
18 }
19
20 sub write {
21 my $self = shift;
22 $self->auto_install(@_);
23 }
24
25 sub auto_install {
26 my $self = shift;
27 return if $self->{done}++;
28
29 # Flatten array of arrays into a single array
30 my @core = map @$_, map @$_, grep ref,
31 $self->build_requires, $self->requires;
32
33 my @config = @_;
34
35 # We'll need Module::AutoInstall
36 $self->include('Module::AutoInstall');
37 require Module::AutoInstall;
38
39 Module::AutoInstall->import(
40 (@config ? (-config => \@config) : ()),
41 (@core ? (-core => \@core) : ()),
42 $self->features,
43 );
44
45 $self->makemaker_args( Module::AutoInstall::_make_args() );
46
47 my $class = ref($self);
48 $self->postamble(
49 "# --- $class section:\n" .
50 Module::AutoInstall::postamble()
51 );
52 }
53
54 sub auto_install_now {
55 my $self = shift;
56 $self->auto_install(@_);
57 Module::AutoInstall::do_install();
58 }
59
60 1;
0 #line 1
1 package Module::Install::Base;
2
3 $VERSION = '0.67';
4
5 # Suspend handler for "redefined" warnings
6 BEGIN {
7 my $w = $SIG{__WARN__};
8 $SIG{__WARN__} = sub { $w };
9 }
10
11 ### This is the ONLY module that shouldn't have strict on
12 # use strict;
13
14 #line 41
15
16 sub new {
17 my ($class, %args) = @_;
18
19 foreach my $method ( qw(call load) ) {
20 *{"$class\::$method"} = sub {
21 shift()->_top->$method(@_);
22 } unless defined &{"$class\::$method"};
23 }
24
25 bless( \%args, $class );
26 }
27
28 #line 61
29
30 sub AUTOLOAD {
31 my $self = shift;
32 local $@;
33 my $autoload = eval { $self->_top->autoload } or return;
34 goto &$autoload;
35 }
36
37 #line 76
38
39 sub _top { $_[0]->{_top} }
40
41 #line 89
42
43 sub admin {
44 $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new;
45 }
46
47 sub is_admin {
48 $_[0]->admin->VERSION;
49 }
50
51 sub DESTROY {}
52
53 package Module::Install::Base::FakeAdmin;
54
55 my $Fake;
56 sub new { $Fake ||= bless(\@_, $_[0]) }
57
58 sub AUTOLOAD {}
59
60 sub DESTROY {}
61
62 # Restore warning handler
63 BEGIN {
64 $SIG{__WARN__} = $SIG{__WARN__}->();
65 }
66
67 1;
68
69 #line 138
0 #line 1
1 package Module::Install::Can;
2
3 use strict;
4 use Module::Install::Base;
5 use Config ();
6 ### This adds a 5.005 Perl version dependency.
7 ### This is a bug and will be fixed.
8 use File::Spec ();
9 use ExtUtils::MakeMaker ();
10
11 use vars qw{$VERSION $ISCORE @ISA};
12 BEGIN {
13 $VERSION = '0.67';
14 $ISCORE = 1;
15 @ISA = qw{Module::Install::Base};
16 }
17
18 # check if we can load some module
19 ### Upgrade this to not have to load the module if possible
20 sub can_use {
21 my ($self, $mod, $ver) = @_;
22 $mod =~ s{::|\\}{/}g;
23 $mod .= '.pm' unless $mod =~ /\.pm$/i;
24
25 my $pkg = $mod;
26 $pkg =~ s{/}{::}g;
27 $pkg =~ s{\.pm$}{}i;
28
29 local $@;
30 eval { require $mod; $pkg->VERSION($ver || 0); 1 };
31 }
32
33 # check if we can run some command
34 sub can_run {
35 my ($self, $cmd) = @_;
36
37 my $_cmd = $cmd;
38 return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));
39
40 for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') {
41 my $abs = File::Spec->catfile($dir, $_[1]);
42 return $abs if (-x $abs or $abs = MM->maybe_command($abs));
43 }
44
45 return;
46 }
47
48 # can we locate a (the) C compiler
49 sub can_cc {
50 my $self = shift;
51 my @chunks = split(/ /, $Config::Config{cc}) or return;
52
53 # $Config{cc} may contain args; try to find out the program part
54 while (@chunks) {
55 return $self->can_run("@chunks") || (pop(@chunks), next);
56 }
57
58 return;
59 }
60
61 # Fix Cygwin bug on maybe_command();
62 if ( $^O eq 'cygwin' ) {
63 require ExtUtils::MM_Cygwin;
64 require ExtUtils::MM_Win32;
65 if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) {
66 *ExtUtils::MM_Cygwin::maybe_command = sub {
67 my ($self, $file) = @_;
68 if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) {
69 ExtUtils::MM_Win32->maybe_command($file);
70 } else {
71 ExtUtils::MM_Unix->maybe_command($file);
72 }
73 }
74 }
75 }
76
77 1;
78
79 __END__
80
81 #line 157
0 #line 1
1 package Module::Install::Fetch;
2
3 use strict;
4 use Module::Install::Base;
5
6 use vars qw{$VERSION $ISCORE @ISA};
7 BEGIN {
8 $VERSION = '0.67';
9 $ISCORE = 1;
10 @ISA = qw{Module::Install::Base};
11 }
12
13 sub get_file {
14 my ($self, %args) = @_;
15 my ($scheme, $host, $path, $file) =
16 $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
17
18 if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) {
19 $args{url} = $args{ftp_url}
20 or (warn("LWP support unavailable!\n"), return);
21 ($scheme, $host, $path, $file) =
22 $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
23 }
24
25 $|++;
26 print "Fetching '$file' from $host... ";
27
28 unless (eval { require Socket; Socket::inet_aton($host) }) {
29 warn "'$host' resolve failed!\n";
30 return;
31 }
32
33 return unless $scheme eq 'ftp' or $scheme eq 'http';
34
35 require Cwd;
36 my $dir = Cwd::getcwd();
37 chdir $args{local_dir} or return if exists $args{local_dir};
38
39 if (eval { require LWP::Simple; 1 }) {
40 LWP::Simple::mirror($args{url}, $file);
41 }
42 elsif (eval { require Net::FTP; 1 }) { eval {
43 # use Net::FTP to get past firewall
44 my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600);
45 $ftp->login("anonymous", 'anonymous@example.com');
46 $ftp->cwd($path);
47 $ftp->binary;
48 $ftp->get($file) or (warn("$!\n"), return);
49 $ftp->quit;
50 } }
51 elsif (my $ftp = $self->can_run('ftp')) { eval {
52 # no Net::FTP, fallback to ftp.exe
53 require FileHandle;
54 my $fh = FileHandle->new;
55
56 local $SIG{CHLD} = 'IGNORE';
57 unless ($fh->open("|$ftp -n")) {
58 warn "Couldn't open ftp: $!\n";
59 chdir $dir; return;
60 }
61
62 my @dialog = split(/\n/, <<"END_FTP");
63 open $host
64 user anonymous anonymous\@example.com
65 cd $path
66 binary
67 get $file $file
68 quit
69 END_FTP
70 foreach (@dialog) { $fh->print("$_\n") }
71 $fh->close;
72 } }
73 else {
74 warn "No working 'ftp' program available!\n";
75 chdir $dir; return;
76 }
77
78 unless (-f $file) {
79 warn "Fetching failed: $@\n";
80 chdir $dir; return;
81 }
82
83 return if exists $args{size} and -s $file != $args{size};
84 system($args{run}) if exists $args{run};
85 unlink($file) if $args{remove};
86
87 print(((!exists $args{check_for} or -e $args{check_for})
88 ? "done!" : "failed! ($!)"), "\n");
89 chdir $dir; return !$?;
90 }
91
92 1;
0 #line 1
1 package Module::Install::Include;
2
3 use strict;
4 use Module::Install::Base;
5
6 use vars qw{$VERSION $ISCORE @ISA};
7 BEGIN {
8 $VERSION = '0.67';
9 $ISCORE = 1;
10 @ISA = qw{Module::Install::Base};
11 }
12
13 sub include {
14 shift()->admin->include(@_);
15 }
16
17 sub include_deps {
18 shift()->admin->include_deps(@_);
19 }
20
21 sub auto_include {
22 shift()->admin->auto_include(@_);
23 }
24
25 sub auto_include_deps {
26 shift()->admin->auto_include_deps(@_);
27 }
28
29 sub auto_include_dependent_dists {
30 shift()->admin->auto_include_dependent_dists(@_);
31 }
32
33 1;
0 #line 1
1 package Module::Install::Makefile;
2
3 use strict 'vars';
4 use Module::Install::Base;
5 use ExtUtils::MakeMaker ();
6
7 use vars qw{$VERSION $ISCORE @ISA};
8 BEGIN {
9 $VERSION = '0.67';
10 $ISCORE = 1;
11 @ISA = qw{Module::Install::Base};
12 }
13
14 sub Makefile { $_[0] }
15
16 my %seen = ();
17
18 sub prompt {
19 shift;
20
21 # Infinite loop protection
22 my @c = caller();
23 if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
24 die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
25 }
26
27 # In automated testing, always use defaults
28 if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
29 local $ENV{PERL_MM_USE_DEFAULT} = 1;
30 goto &ExtUtils::MakeMaker::prompt;
31 } else {
32 goto &ExtUtils::MakeMaker::prompt;
33 }
34 }
35
36 sub makemaker_args {
37 my $self = shift;
38 my $args = ($self->{makemaker_args} ||= {});
39 %$args = ( %$args, @_ ) if @_;
40 $args;
41 }
42
43 # For mm args that take multiple space-seperated args,
44 # append an argument to the current list.
45 sub makemaker_append {
46 my $self = sShift;
47 my $name = shift;
48 my $args = $self->makemaker_args;
49 $args->{name} = defined $args->{$name}
50 ? join( ' ', $args->{name}, @_ )
51 : join( ' ', @_ );
52 }
53
54 sub build_subdirs {
55 my $self = shift;
56 my $subdirs = $self->makemaker_args->{DIR} ||= [];
57 for my $subdir (@_) {
58 push @$subdirs, $subdir;
59 }
60 }
61
62 sub clean_files {
63 my $self = shift;
64 my $clean = $self->makemaker_args->{clean} ||= {};
65 %$clean = (
66 %$clean,
67 FILES => join(' ', grep length, $clean->{FILES}, @_),
68 );
69 }
70
71 sub realclean_files {
72 my $self = shift;
73 my $realclean = $self->makemaker_args->{realclean} ||= {};
74 %$realclean = (
75 %$realclean,
76 FILES => join(' ', grep length, $realclean->{FILES}, @_),
77 );
78 }
79
80 sub libs {
81 my $self = shift;
82 my $libs = ref $_[0] ? shift : [ shift ];
83 $self->makemaker_args( LIBS => $libs );
84 }
85
86 sub inc {
87 my $self = shift;
88 $self->makemaker_args( INC => shift );
89 }
90
91 my %test_dir = ();
92
93 sub _wanted_t {
94 /\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1;
95 }
96
97 sub tests_recursive {
98 my $self = shift;
99 if ( $self->tests ) {
100 die "tests_recursive will not work if tests are already defined";
101 }
102 my $dir = shift || 't';
103 unless ( -d $dir ) {
104 die "tests_recursive dir '$dir' does not exist";
105 }
106 require File::Find;
107 %test_dir = ();
108 File::Find::find( \&_wanted_t, $dir );
109 $self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir );
110 }
111
112 sub write {
113 my $self = shift;
114 die "&Makefile->write() takes no arguments\n" if @_;
115
116 my $args = $self->makemaker_args;
117 $args->{DISTNAME} = $self->name;
118 $args->{NAME} = $self->module_name || $self->name || $self->determine_NAME($args);
119 $args->{VERSION} = $self->version || $self->determine_VERSION($args);
120 $args->{NAME} =~ s/-/::/g;
121 if ( $self->tests ) {
122 $args->{test} = { TESTS => $self->tests };
123 }
124 if ($] >= 5.005) {
125 $args->{ABSTRACT} = $self->abstract;
126 $args->{AUTHOR} = $self->author;
127 }
128 if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) {
129 $args->{NO_META} = 1;
130 }
131 if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 and $self->sign ) {
132 $args->{SIGN} = 1;
133 }
134 unless ( $self->is_admin ) {
135 delete $args->{SIGN};
136 }
137
138 # merge both kinds of requires into prereq_pm
139 my $prereq = ($args->{PREREQ_PM} ||= {});
140 %$prereq = ( %$prereq,
141 map { @$_ }
142 map { @$_ }
143 grep $_,
144 ($self->build_requires, $self->requires)
145 );
146
147 # merge both kinds of requires into prereq_pm
148 my $subdirs = ($args->{DIR} ||= []);
149 if ($self->bundles) {
150 foreach my $bundle (@{ $self->bundles }) {
151 my ($file, $dir) = @$bundle;
152 push @$subdirs, $dir if -d $dir;
153 delete $prereq->{$file};
154 }
155 }
156
157 if ( my $perl_version = $self->perl_version ) {
158 eval "use $perl_version; 1"
159 or die "ERROR: perl: Version $] is installed, "
160 . "but we need version >= $perl_version";
161 }
162
163 $args->{INSTALLDIRS} = $self->installdirs;
164
165 my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_})} keys %$args;
166
167 my $user_preop = delete $args{dist}->{PREOP};
168 if (my $preop = $self->admin->preop($user_preop)) {
169 $args{dist} = $preop;
170 }
171
172 my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
173 $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
174 }
175
176 sub fix_up_makefile {
177 my $self = shift;
178 my $makefile_name = shift;
179 my $top_class = ref($self->_top) || '';
180 my $top_version = $self->_top->VERSION || '';
181
182 my $preamble = $self->preamble
183 ? "# Preamble by $top_class $top_version\n"
184 . $self->preamble
185 : '';
186 my $postamble = "# Postamble by $top_class $top_version\n"
187 . ($self->postamble || '');
188
189 local *MAKEFILE;
190 open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
191 my $makefile = do { local $/; <MAKEFILE> };
192 close MAKEFILE or die $!;
193
194 $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
195 $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
196 $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
197 $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
198 $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;
199
200 # Module::Install will never be used to build the Core Perl
201 # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
202 # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
203 $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
204 #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;
205
206 # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
207 $makefile =~ s/("?)-I\$\(PERL_LIB\)\1//g;
208
209 # XXX - This is currently unused; not sure if it breaks other MM-users
210 # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
211
212 open MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
213 print MAKEFILE "$preamble$makefile$postamble" or die $!;
214 close MAKEFILE or die $!;
215
216 1;
217 }
218
219 sub preamble {
220 my ($self, $text) = @_;
221 $self->{preamble} = $text . $self->{preamble} if defined $text;
222 $self->{preamble};
223 }
224
225 sub postamble {
226 my ($self, $text) = @_;
227 $self->{postamble} ||= $self->admin->postamble;
228 $self->{postamble} .= $text if defined $text;
229 $self->{postamble}
230 }
231
232 1;
233
234 __END__
235
236 #line 363
0 #line 1
1 package Module::Install::Metadata;
2
3 use strict 'vars';
4 use Module::Install::Base;
5
6 use vars qw{$VERSION $ISCORE @ISA};
7 BEGIN {
8 $VERSION = '0.67';
9 $ISCORE = 1;
10 @ISA = qw{Module::Install::Base};
11 }
12
13 my @scalar_keys = qw{
14 name module_name abstract author version license
15 distribution_type perl_version tests installdirs
16 };
17
18 my @tuple_keys = qw{
19 build_requires requires recommends bundles
20 };
21
22 sub Meta { shift }
23 sub Meta_ScalarKeys { @scalar_keys }
24 sub Meta_TupleKeys { @tuple_keys }
25
26 foreach my $key (@scalar_keys) {
27 *$key = sub {
28 my $self = shift;
29 return $self->{values}{$key} if defined wantarray and !@_;
30 $self->{values}{$key} = shift;
31 return $self;
32 };
33 }
34
35 foreach my $key (@tuple_keys) {
36 *$key = sub {
37 my $self = shift;
38 return $self->{values}{$key} unless @_;
39
40 my @rv;
41 while (@_) {
42 my $module = shift or last;
43 my $version = shift || 0;
44 if ( $module eq 'perl' ) {
45 $version =~ s{^(\d+)\.(\d+)\.(\d+)}
46 {$1 + $2/1_000 + $3/1_000_000}e;
47 $self->perl_version($version);
48 next;
49 }
50 my $rv = [ $module, $version ];
51 push @rv, $rv;
52 }
53 push @{ $self->{values}{$key} }, @rv;
54 @rv;
55 };
56 }
57
58 # configure_requires is currently a null-op
59 sub configure_requires { 1 }
60
61 # Aliases for build_requires that will have alternative
62 # meanings in some future version of META.yml.
63 sub test_requires { shift->build_requires(@_) }
64 sub install_requires { shift->build_requires(@_) }
65
66 # Aliases for installdirs options
67 sub install_as_core { $_[0]->installdirs('perl') }
68 sub install_as_cpan { $_[0]->installdirs('site') }
69 sub install_as_site { $_[0]->installdirs('site') }
70 sub install_as_vendor { $_[0]->installdirs('vendor') }
71
72 sub sign {
73 my $self = shift;
74 return $self->{'values'}{'sign'} if defined wantarray and ! @_;
75 $self->{'values'}{'sign'} = ( @_ ? $_[0] : 1 );
76 return $self;
77 }
78
79 sub dynamic_config {
80 my $self = shift;
81 unless ( @_ ) {
82 warn "You MUST provide an explicit true/false value to dynamic_config, skipping\n";
83 return $self;
84 }
85 $self->{'values'}{'dynamic_config'} = $_[0] ? 1 : 0;
86 return $self;
87 }
88
89 sub all_from {
90 my ( $self, $file ) = @_;
91
92 unless ( defined($file) ) {
93 my $name = $self->name
94 or die "all_from called with no args without setting name() first";
95 $file = join('/', 'lib', split(/-/, $name)) . '.pm';
96 $file =~ s{.*/}{} unless -e $file;
97 die "all_from: cannot find $file from $name" unless -e $file;
98 }
99
100 $self->version_from($file) unless $self->version;
101 $self->perl_version_from($file) unless $self->perl_version;
102
103 # The remaining probes read from POD sections; if the file
104 # has an accompanying .pod, use that instead
105 my $pod = $file;
106 if ( $pod =~ s/\.pm$/.pod/i and -e $pod ) {
107 $file = $pod;
108 }
109
110 $self->author_from($file) unless $self->author;
111 $self->license_from($file) unless $self->license;
112 $self->abstract_from($file) unless $self->abstract;
113 }
114
115 sub provides {
116 my $self = shift;
117 my $provides = ( $self->{values}{provides} ||= {} );
118 %$provides = (%$provides, @_) if @_;
119 return $provides;
120 }
121
122 sub auto_provides {
123 my $self = shift;
124 return $self unless $self->is_admin;
125
126 unless (-e 'MANIFEST') {
127 warn "Cannot deduce auto_provides without a MANIFEST, skipping\n";
128 return $self;
129 }
130
131 # Avoid spurious warnings as we are not checking manifest here.
132
133 local $SIG{__WARN__} = sub {1};
134 require ExtUtils::Manifest;
135 local *ExtUtils::Manifest::manicheck = sub { return };
136
137 require Module::Build;
138 my $build = Module::Build->new(
139 dist_name => $self->name,
140 dist_version => $self->version,
141 license => $self->license,
142 );
143 $self->provides(%{ $build->find_dist_packages || {} });
144 }
145
146 sub feature {
147 my $self = shift;
148 my $name = shift;
149 my $features = ( $self->{values}{features} ||= [] );
150
151 my $mods;
152
153 if ( @_ == 1 and ref( $_[0] ) ) {
154 # The user used ->feature like ->features by passing in the second
155 # argument as a reference. Accomodate for that.
156 $mods = $_[0];
157 } else {
158 $mods = \@_;
159 }
160
161 my $count = 0;
162 push @$features, (
163 $name => [
164 map {
165 ref($_) ? ( ref($_) eq 'HASH' ) ? %$_
166 : @$_
167 : $_
168 } @$mods
169 ]
170 );
171
172 return @$features;
173 }
174
175 sub features {
176 my $self = shift;
177 while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) {
178 $self->feature( $name, @$mods );
179 }
180 return $self->{values}->{features}
181 ? @{ $self->{values}->{features} }
182 : ();
183 }
184
185 sub no_index {
186 my $self = shift;
187 my $type = shift;
188 push @{ $self->{values}{no_index}{$type} }, @_ if $type;
189 return $self->{values}{no_index};
190 }
191
192 sub read {
193 my $self = shift;
194 $self->include_deps( 'YAML', 0 );
195
196 require YAML;
197 my $data = YAML::LoadFile('META.yml');
198
199 # Call methods explicitly in case user has already set some values.
200 while ( my ( $key, $value ) = each %$data ) {
201 next unless $self->can($key);
202 if ( ref $value eq 'HASH' ) {
203 while ( my ( $module, $version ) = each %$value ) {
204 $self->can($key)->($self, $module => $version );
205 }
206 }
207 else {
208 $self->can($key)->($self, $value);
209 }
210 }
211 return $self;
212 }
213
214 sub write {
215 my $self = shift;
216 return $self unless $self->is_admin;
217 $self->admin->write_meta;
218 return $self;
219 }
220
221 sub version_from {
222 my ( $self, $file ) = @_;
223 require ExtUtils::MM_Unix;
224 $self->version( ExtUtils::MM_Unix->parse_version($file) );
225 }
226
227 sub abstract_from {
228 my ( $self, $file ) = @_;
229 require ExtUtils::MM_Unix;
230 $self->abstract(
231 bless(
232 { DISTNAME => $self->name },
233 'ExtUtils::MM_Unix'
234 )->parse_abstract($file)
235 );
236 }
237
238 sub _slurp {
239 my ( $self, $file ) = @_;
240
241 local *FH;
242 open FH, "< $file" or die "Cannot open $file.pod: $!";
243 do { local $/; <FH> };
244 }
245
246 sub perl_version_from {
247 my ( $self, $file ) = @_;
248
249 if (
250 $self->_slurp($file) =~ m/
251 ^
252 use \s*
253 v?
254 ([\d_\.]+)
255 \s* ;
256 /ixms
257 )
258 {
259 my $v = $1;
260 $v =~ s{_}{}g;
261 $self->perl_version($1);
262 }
263 else {
264 warn "Cannot determine perl version info from $file\n";
265 return;
266 }
267 }
268
269 sub author_from {
270 my ( $self, $file ) = @_;
271 my $content = $self->_slurp($file);
272 if ($content =~ m/
273 =head \d \s+ (?:authors?)\b \s*
274 ([^\n]*)
275 |
276 =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s*
277 .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s*
278 ([^\n]*)
279 /ixms) {
280 my $author = $1 || $2;
281 $author =~ s{E<lt>}{<}g;
282 $author =~ s{E<gt>}{>}g;
283 $self->author($author);
284 }
285 else {
286 warn "Cannot determine author info from $file\n";
287 }
288 }
289
290 sub license_from {
291 my ( $self, $file ) = @_;
292
293 if (
294 $self->_slurp($file) =~ m/
295 (
296 =head \d \s+
297 (?:licen[cs]e|licensing|copyright|legal)\b
298 .*?
299 )
300 (=head\\d.*|=cut.*|)
301 \z
302 /ixms
303 )
304 {
305 my $license_text = $1;
306 my @phrases = (
307 'under the same (?:terms|license) as perl itself' => 'perl', 1,
308 'GNU public license' => 'gpl', 1,
309 'GNU lesser public license' => 'gpl', 1,
310 'BSD license' => 'bsd', 1,
311 'Artistic license' => 'artistic', 1,
312 'GPL' => 'gpl', 1,
313 'LGPL' => 'lgpl', 1,
314 'BSD' => 'bsd', 1,
315 'Artistic' => 'artistic', 1,
316 'MIT' => 'mit', 1,
317 'proprietary' => 'proprietary', 0,
318 );
319 while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
320 $pattern =~ s{\s+}{\\s+}g;
321 if ( $license_text =~ /\b$pattern\b/i ) {
322 if ( $osi and $license_text =~ /All rights reserved/i ) {
323 warn "LEGAL WARNING: 'All rights reserved' may invalidate Open Source licenses. Consider removing it.";
324 }
325 $self->license($license);
326 return 1;
327 }
328 }
329 }
330
331 warn "Cannot determine license info from $file\n";
332 return 'unknown';
333 }
334
335 1;
0 #line 1
1 package Module::Install::Win32;
2
3 use strict;
4 use Module::Install::Base;
5
6 use vars qw{$VERSION $ISCORE @ISA};
7 BEGIN {
8 $VERSION = '0.67';
9 $ISCORE = 1;
10 @ISA = qw{Module::Install::Base};
11 }
12
13 # determine if the user needs nmake, and download it if needed
14 sub check_nmake {
15 my $self = shift;
16 $self->load('can_run');
17 $self->load('get_file');
18
19 require Config;
20 return unless (
21 $^O eq 'MSWin32' and
22 $Config::Config{make} and
23 $Config::Config{make} =~ /^nmake\b/i and
24 ! $self->can_run('nmake')
25 );
26
27 print "The required 'nmake' executable not found, fetching it...\n";
28
29 require File::Basename;
30 my $rv = $self->get_file(
31 url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe',
32 ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe',
33 local_dir => File::Basename::dirname($^X),
34 size => 51928,
35 run => 'Nmake15.exe /o > nul',
36 check_for => 'Nmake.exe',
37 remove => 1,
38 );
39
40 if (!$rv) {
41 die <<'END_MESSAGE';
42
43 -------------------------------------------------------------------------------
44
45 Since you are using Microsoft Windows, you will need the 'nmake' utility
46 before installation. It's available at:
47
48 http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe
49 or
50 ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe
51
52 Please download the file manually, save it to a directory in %PATH% (e.g.
53 C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to
54 that directory, and run "Nmake15.exe" from there; that will create the
55 'nmake.exe' file needed by this module.
56
57 You may then resume the installation process described in README.
58
59 -------------------------------------------------------------------------------
60 END_MESSAGE
61 }
62 }
63
64 1;
0 #line 1
1 package Module::Install::WriteAll;
2
3 use strict;
4 use Module::Install::Base;
5
6 use vars qw{$VERSION $ISCORE @ISA};
7 BEGIN {
8 $VERSION = '0.67';
9 $ISCORE = 1;
10 @ISA = qw{Module::Install::Base};
11 }
12
13 sub WriteAll {
14 my $self = shift;
15 my %args = (
16 meta => 1,
17 sign => 0,
18 inline => 0,
19 check_nmake => 1,
20 @_
21 );
22
23 $self->sign(1) if $args{sign};
24 $self->Meta->write if $args{meta};
25 $self->admin->WriteAll(%args) if $self->is_admin;
26
27 if ( $0 =~ /Build.PL$/i ) {
28 $self->Build->write;
29 } else {
30 $self->check_nmake if $args{check_nmake};
31 unless ( $self->makemaker_args->{'PL_FILES'} ) {
32 $self->makemaker_args( PL_FILES => {} );
33 }
34 if ($args{inline}) {
35 $self->Inline->write;
36 } else {
37 $self->Makefile->write;
38 }
39 }
40 }
41
42 1;
0 #line 1
1 package Module::Install;
2
3 # For any maintainers:
4 # The load order for Module::Install is a bit magic.
5 # It goes something like this...
6 #
7 # IF ( host has Module::Install installed, creating author mode ) {
8 # 1. Makefile.PL calls "use inc::Module::Install"
9 # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
10 # 3. The installed version of inc::Module::Install loads
11 # 4. inc::Module::Install calls "require Module::Install"
12 # 5. The ./inc/ version of Module::Install loads
13 # } ELSE {
14 # 1. Makefile.PL calls "use inc::Module::Install"
15 # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
16 # 3. The ./inc/ version of Module::Install loads
17 # }
18
19 use 5.004;
20 use strict 'vars';
21
22 use vars qw{$VERSION};
23 BEGIN {
24 # All Module::Install core packages now require synchronised versions.
25 # This will be used to ensure we don't accidentally load old or
26 # different versions of modules.
27 # This is not enforced yet, but will be some time in the next few
28 # releases once we can make sure it won't clash with custom
29 # Module::Install extensions.
30 $VERSION = '0.67';
31 }
32
33 # Whether or not inc::Module::Install is actually loaded, the
34 # $INC{inc/Module/Install.pm} is what will still get set as long as
35 # the caller loaded module this in the documented manner.
36 # If not set, the caller may NOT have loaded the bundled version, and thus
37 # they may not have a MI version that works with the Makefile.PL. This would
38 # result in false errors or unexpected behaviour. And we don't want that.
39 my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
40 unless ( $INC{$file} ) {
41 die <<"END_DIE";
42 Please invoke ${\__PACKAGE__} with:
43
44 use inc::${\__PACKAGE__};
45
46 not:
47
48 use ${\__PACKAGE__};
49
50 END_DIE
51 }
52
53 # If the script that is loading Module::Install is from the future,
54 # then make will detect this and cause it to re-run over and over
55 # again. This is bad. Rather than taking action to touch it (which
56 # is unreliable on some platforms and requires write permissions)
57 # for now we should catch this and refuse to run.
58 if ( -f $0 and (stat($0))[9] > time ) {
59 die << "END_DIE";
60 Your installer $0 has a modification time in the future.
61
62 This is known to create infinite loops in make.
63
64 Please correct this, then run $0 again.
65
66 END_DIE
67 }
68
69 use Cwd ();
70 use File::Find ();
71 use File::Path ();
72 use FindBin;
73
74 *inc::Module::Install::VERSION = *VERSION;
75 @inc::Module::Install::ISA = __PACKAGE__;
76
77 sub autoload {
78 my $self = shift;
79 my $who = $self->_caller;
80 my $cwd = Cwd::cwd();
81 my $sym = "${who}::AUTOLOAD";
82 $sym->{$cwd} = sub {
83 my $pwd = Cwd::cwd();
84 if ( my $code = $sym->{$pwd} ) {
85 # delegate back to parent dirs
86 goto &$code unless $cwd eq $pwd;
87 }
88 $$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
89 unshift @_, ($self, $1);
90 goto &{$self->can('call')} unless uc($1) eq $1;
91 };
92 }
93
94 sub import {
95 my $class = shift;
96 my $self = $class->new(@_);
97 my $who = $self->_caller;
98
99 unless ( -f $self->{file} ) {
100 require "$self->{path}/$self->{dispatch}.pm";
101 File::Path::mkpath("$self->{prefix}/$self->{author}");
102 $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
103 $self->{admin}->init;
104 @_ = ($class, _self => $self);
105 goto &{"$self->{name}::import"};
106 }
107
108 *{"${who}::AUTOLOAD"} = $self->autoload;
109 $self->preload;
110
111 # Unregister loader and worker packages so subdirs can use them again
112 delete $INC{"$self->{file}"};
113 delete $INC{"$self->{path}.pm"};
114 }
115
116 sub preload {
117 my ($self) = @_;
118
119 unless ( $self->{extensions} ) {
120 $self->load_extensions(
121 "$self->{prefix}/$self->{path}", $self
122 );
123 }
124
125 my @exts = @{$self->{extensions}};
126 unless ( @exts ) {
127 my $admin = $self->{admin};
128 @exts = $admin->load_all_extensions;
129 }
130
131 my %seen;
132 foreach my $obj ( @exts ) {
133 while (my ($method, $glob) = each %{ref($obj) . '::'}) {
134 next unless $obj->can($method);
135 next if $method =~ /^_/;
136 next if $method eq uc($method);
137 $seen{$method}++;
138 }
139 }
140
141 my $who = $self->_caller;
142 foreach my $name ( sort keys %seen ) {
143 *{"${who}::$name"} = sub {
144 ${"${who}::AUTOLOAD"} = "${who}::$name";
145 goto &{"${who}::AUTOLOAD"};
146 };
147 }
148 }
149
150 sub new {
151 my ($class, %args) = @_;
152
153 # ignore the prefix on extension modules built from top level.
154 my $base_path = Cwd::abs_path($FindBin::Bin);
155 unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
156 delete $args{prefix};
157 }
158
159 return $args{_self} if $args{_self};
160
161 $args{dispatch} ||= 'Admin';
162 $args{prefix} ||= 'inc';
163 $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author');
164 $args{bundle} ||= 'inc/BUNDLES';
165 $args{base} ||= $base_path;
166 $class =~ s/^\Q$args{prefix}\E:://;
167 $args{name} ||= $class;
168 $args{version} ||= $class->VERSION;
169 unless ( $args{path} ) {
170 $args{path} = $args{name};
171 $args{path} =~ s!::!/!g;
172 }
173 $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm";
174
175 bless( \%args, $class );
176 }
177
178 sub call {
179 my ($self, $method) = @_;
180 my $obj = $self->load($method) or return;
181 splice(@_, 0, 2, $obj);
182 goto &{$obj->can($method)};
183 }
184
185 sub load {
186 my ($self, $method) = @_;
187
188 $self->load_extensions(
189 "$self->{prefix}/$self->{path}", $self
190 ) unless $self->{extensions};
191
192 foreach my $obj (@{$self->{extensions}}) {
193 return $obj if $obj->can($method);
194 }
195
196 my $admin = $self->{admin} or die <<"END_DIE";
197 The '$method' method does not exist in the '$self->{prefix}' path!
198 Please remove the '$self->{prefix}' directory and run $0 again to load it.
199 END_DIE
200
201 my $obj = $admin->load($method, 1);
202 push @{$self->{extensions}}, $obj;
203
204 $obj;
205 }
206
207 sub load_extensions {
208 my ($self, $path, $top) = @_;
209
210 unless ( grep { lc $_ eq lc $self->{prefix} } @INC ) {
211 unshift @INC, $self->{prefix};
212 }
213
214 foreach my $rv ( $self->find_extensions($path) ) {
215 my ($file, $pkg) = @{$rv};
216 next if $self->{pathnames}{$pkg};
217
218 local $@;
219 my $new = eval { require $file; $pkg->can('new') };
220 unless ( $new ) {
221 warn $@ if $@;
222 next;
223 }
224 $self->{pathnames}{$pkg} = delete $INC{$file};
225 push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
226 }
227
228 $self->{extensions} ||= [];
229 }
230
231 sub find_extensions {
232 my ($self, $path) = @_;
233
234 my @found;
235 File::Find::find( sub {
236 my $file = $File::Find::name;
237 return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
238 my $subpath = $1;
239 return if lc($subpath) eq lc($self->{dispatch});
240
241 $file = "$self->{path}/$subpath.pm";
242 my $pkg = "$self->{name}::$subpath";
243 $pkg =~ s!/!::!g;
244
245 # If we have a mixed-case package name, assume case has been preserved
246 # correctly. Otherwise, root through the file to locate the case-preserved
247 # version of the package name.
248 if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
249 open PKGFILE, "<$subpath.pm" or die "find_extensions: Can't open $subpath.pm: $!";
250 my $in_pod = 0;
251 while ( <PKGFILE> ) {
252 $in_pod = 1 if /^=\w/;
253 $in_pod = 0 if /^=cut/;
254 next if ($in_pod || /^=cut/); # skip pod text
255 next if /^\s*#/; # and comments
256 if ( m/^\s*package\s+($pkg)\s*;/i ) {
257 $pkg = $1;
258 last;
259 }
260 }
261 close PKGFILE;
262 }
263
264 push @found, [ $file, $pkg ];
265 }, $path ) if -d $path;
266
267 @found;
268 }
269
270 sub _caller {
271 my $depth = 0;
272 my $call = caller($depth);
273 while ( $call eq __PACKAGE__ ) {
274 $depth++;
275 $call = caller($depth);
276 }
277 return $call;
278 }
279
280 1;
0 package DBIx::Class::InflateColumn::IP;
1
2 use warnings;
3 use strict;
4
5 our $VERSION = '0.02001';
6
7 use base qw/DBIx::Class/;
8 __PACKAGE__->mk_classdata(ip_format => 'addr');
9 __PACKAGE__->mk_classdata(ip_class => 'NetAddr::IP');
10
11 =head1 NAME
12
13 DBIx::Class::InflateColumn::IP - Auto-create NetAddr::IP objects from columns.
14
15 =head1 SYNOPSIS
16
17 Load this component and declare columns as IP addresses with the
18 appropriate format.
19
20 package Host;
21 __PACKAGE__->load_components(qw/InflateColumn::IP Core/);
22 __PACKAGE__->add_columns(
23 ip_address => {
24 data_type => 'integer',
25 is_nullable => 0,
26 is_ip => 1,
27 ip_format => 'numeric',
28 }
29 );
30
31 package Network;
32 __PACKAGE__->load_components(qw/InflateColumn::IP Core/);
33 __PACKAGE__->add_columns(
34 address => {
35 data_type => 'varchar',
36 size => 18
37 is_nullable => 0,
38 is_ip => 1,
39 ip_format => 'cidr',
40 }
41 );
42
43 Then you can treat the specified column as a NetAddr::IP object.
44
45 print 'IP address: ', $host->ip_address->addr;
46 print 'Address type: ', $host->ip_address->iptype;
47
48 DBIx::Class::InflateColumn::IP supports a limited amount of
49 auto-detection of the format based on the column type. If the type
50 begins with C<int>, it's assumed to be numeric, while C<inet> and
51 C<cidr> (as used by e.g. PostgreSQL) are assumed to be C<cidr> format.
52
53 =head1 METHODS
54
55 =head2 ip_class
56
57 =over
58
59 =item Arguments: $class
60
61 =back
62
63 Gets/sets the address class that the columns should be inflated into.
64 The default class is NetAddr::IP.
65
66 =head2 ip_format
67
68 =over
69
70 =item Arguments: $format
71
72 =back
73
74 Gets/sets the name of the method used to deflate the address for the
75 database. This must return a value suitable for C<$ip_class->new(); The
76 default format is C<addr>, which returns the address in dotted-quad
77 notation. See L<NetAddr::IP/Methods> for suitable values.
78
79 =head2 register_column
80
81 Chains with L<DBIx::Class::Row/register_column>, and sets up IP address
82 columns appropriately. This would not normally be called directly by end
83 users.
84
85 =cut
86
87 sub register_column {
88 my ($self, $column, $info, @rest) = @_;
89 $self->next::method($column, $info, @rest);
90
91 return unless defined $info->{'is_ip'};
92
93 my $ip_format = $info->{ip_format} || _default_format($info->{data_type})
94 || $self->ip_format || 'addr';
95 my $ip_class = $info->{ip_class} || $self->ip_class || 'NetAddr::IP';
96
97 eval "use $ip_class";
98 $self->throw_exception("Error loading $ip_class: $@") if $@;
99 $self->throw_exception("Format '$ip_format' not supported by $ip_class")
100 unless $ip_class->can($ip_format);
101
102 $self->inflate_column(
103 $column => {
104 inflate => sub { return $ip_class->new(shift); },
105 deflate => sub { return scalar shift->$ip_format; },
106 }
107 );
108 }
109
110 my @format_map = (
111 { type => qr/^int/i, format => 'numeric' },
112 { type => qr{^(?:inet|cidr)$}i, format => 'cidr' },
113 );
114
115 sub _default_format {
116 my ($type) = @_;
117
118 for my $match (@format_map) {
119 return $match->{format} if $type =~ $match->{type};
120 }
121 }
122
123 =head1 AUTHOR
124
125 Dagfinn Ilmari Mannsåker, C<< <ilmari at ilmari.org> >>
126
127 =head1 BUGS
128
129 Please report any bugs or feature requests to
130 C<bug-dbix-class-inflatecolumn-ip at rt.cpan.org>, or through the web interface at
131 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBIx-Class-InflateColumn-IP>.
132 I will be notified, and then you'll automatically be notified of progress on
133 your bug as I make changes.
134
135 =head1 SUPPORT
136
137 You can find documentation for this module with the perldoc command.
138
139 perldoc DBIx::Class::InflateColumn::IP
140
141 You can also look for information at:
142
143 =over 4
144
145 =item * AnnoCPAN: Annotated CPAN documentation
146
147 L<http://annocpan.org/dist/DBIx-Class-InflateColumn-IP>
148
149 =item * CPAN Ratings
150
151 L<http://cpanratings.perl.org/d/DBIx-Class-InflateColumn-IP>
152
153 =item * RT: CPAN's request tracker
154
155 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBIx-Class-InflateColumn-IP>
156
157 =item * Search CPAN
158
159 L<http://search.cpan.org/dist/DBIx-Class-InflateColumn-IP>
160
161 =back
162
163 =head1 SEE ALSO
164
165 L<DBIx::Class>, L<NetAddr::IP>
166
167 =head1 COPYRIGHT & LICENSE
168
169 Copyright 2007 Dagfinn Ilmari Mannsåker, all rights reserved.
170
171 This program is free software; you can redistribute it and/or modify it
172 under the same terms as Perl itself.
173
174 =cut
175
176 1; # End of DBIx::Class::InflateColumn::IP
0 #!perl -T
1
2 use Test::More tests => 1;
3
4 BEGIN {
5 use_ok( 'DBIx::Class::InflateColumn::IP' );
6 }
7
8 diag( "Testing DBIx::Class::InflateColumn::IP $DBIx::Class::InflateColumn::IP::VERSION, Perl $], $^X" );
0 #!perl -T
1 use lib qw(t/lib);
2 use DBICTest;
3 use Test::More tests => 10;
4 use NetAddr::IP;
5
6 my $schema = DBICTest->init_schema();
7
8 my $host_rs = $schema->resultset('Host');
9
10 my $localhost = $host_rs->find('localhost');
11
12 isa_ok($localhost->address, 'NetAddr::IP', 'numeric address inflated to right class');
13 is($localhost->address, '127.0.0.1/32', 'numeric address correctly inflated');
14
15 TODO: {
16 local $TODO = "DBIx::Class doesn't support find by object yet";
17
18 $localhost = $host_rs->find(NetAddr::IP->new('127.0.0.1'), { key => 'address' });
19
20 ok($localhost, 'find by object returned a row');
21 }
22
23 SKIP: {
24 skip 'no object to check' => 1 unless $localhost;
25
26 is($localhost->hostname, 'localhost', 'find by object returned the right row');
27 }
28
29 my $ip = NetAddr::IP->new('192.168.0.1');
30 my $host = $host_rs->create({ hostname => 'foo', address => $ip });
31
32 isa_ok($host, 'DBICTest::Schema::Host', 'create with object');
33 is($host->get_column('address'), $ip->numeric, 'numeric address correctly deflated');
34
35 my $net_rs = $schema->resultset('Network');
36
37 my $localnet = $net_rs->find('localnet');
38
39 isa_ok($localnet->address, 'NetAddr::IP', 'CIDR address inflated to right class');
40 is($localnet->address, '127.0.0.0/8', 'CIDR address correctly inflated');
41
42 my $net_ip = NetAddr::IP->new('192.168.0.42/24');
43 my $net = $net_rs->create({ netname => 'foo', address => $net_ip });
44
45 isa_ok($net, 'DBICTest::Schema::Network', 'create with object');
46 is($net->get_column('address'), '192.168.0.42/24', 'CIDR address correctly deflated');
0 #!perl -T
1
2 use strict;
3 use warnings;
4 use Test::More tests => 3;
5
6 sub not_in_file_ok {
7 my ($filename, %regex) = @_;
8 open my $fh, "<", $filename
9 or die "couldn't open $filename for reading: $!";
10
11 my %violated;
12
13 while (my $line = <$fh>) {
14 while (my ($desc, $regex) = each %regex) {
15 if ($line =~ $regex) {
16 push @{$violated{$desc}||=[]}, $.;
17 }
18 }
19 }
20
21 if (%violated) {
22 fail("$filename contains boilerplate text");
23 diag "$_ appears on lines @{$violated{$_}}" for keys %violated;
24 } else {
25 pass("$filename contains no boilerplate text");
26 }
27 }
28
29 not_in_file_ok(README =>
30 "The README is used..." => qr/The README is used/,
31 "'version information here'" => qr/to provide version information/,
32 );
33
34 not_in_file_ok(Changes =>
35 "placeholder date/time" => qr(Date/time)
36 );
37
38 sub module_boilerplate_ok {
39 my ($module) = @_;
40 not_in_file_ok($module =>
41 'the great new $MODULENAME' => qr/ - The great new /,
42 'boilerplate description' => qr/Quick summary of what the module/,
43 'stub function definition' => qr/function[12]/,
44 );
45 }
46
47 module_boilerplate_ok('lib/DBIx/Class/InflateColumn/IP.pm');
0 package # hide from PAUSE
1 DBICTest::Schema::Host;
2
3 use base qw/DBIx::Class/;
4
5 __PACKAGE__->load_components(qw/InflateColumn::IP Core/);
6 __PACKAGE__->table('host');
7
8 __PACKAGE__->add_columns(
9 hostname => {
10 data_type => 'text',
11 is_nullable => 0,
12 },
13 address => {
14 data_type => 'integer',
15 is_nullable => 0,
16 is_ip => 1,
17 }
18 );
19
20 __PACKAGE__->set_primary_key('hostname');
21 __PACKAGE__->add_unique_constraint(address => [ qw/address/ ]);
22
23 1;
0 package # hide from PAUSE
1 DBICTest::Schema::Network;
2
3 use base qw/DBIx::Class/;
4
5 __PACKAGE__->load_components(qw/InflateColumn::IP Core/);
6 __PACKAGE__->table('network');
7
8 __PACKAGE__->add_columns(
9 netname => {
10 data_type => 'text',
11 is_nullable => 0,
12 },
13 address => {
14 data_type => 'varchar',
15 size => '18',
16 is_nullable => 0,
17 is_ip => 1,
18 ip_format => 'cidr',
19 }
20 );
21
22 __PACKAGE__->set_primary_key('netname');
23 __PACKAGE__->add_unique_constraint(address => [ qw/address/ ]);
24
25 1;
0 package # hide from PAUSE
1 DBICTest::Schema;
2
3 use base qw/DBIx::Class::Schema/;
4
5 __PACKAGE__->load_classes();
6
7 1;
0 package # hide from PAUSE
1 DBICTest;
2
3 use strict;
4 use warnings;
5 use DBICTest::Schema;
6
7 =head1 NAME
8
9 DBICTest - Library to be used by DBIx::Class test scripts.
10
11 =head1 SYNOPSIS
12
13 use lib qw(t/lib);
14 use DBICTest;
15 use Test::More;
16
17 my $schema = DBICTest->init_schema();
18
19 =head1 DESCRIPTION
20
21 This module provides the basic utilities to write tests against
22 DBIx::Class.
23
24 =head1 METHODS
25
26 =head2 init_schema
27
28 my $schema = DBICTest->init_schema(
29 no_deploy=>1,
30 no_populate=>1,
31 );
32
33 This method removes the test SQLite database in t/var/DBIxClass.db
34 and then creates a new, empty database.
35
36 This method will call deploy_schema() by default, unless the
37 no_deploy flag is set.
38
39 Also, by default, this method will call populate_schema() by
40 default, unless the no_deploy or no_populate flags are set.
41
42 =cut
43
44 sub init_schema {
45 my $self = shift;
46 my %args = @_;
47 my $db_file = "t/var/DBIxClass.db";
48
49 unlink($db_file) if -e $db_file;
50 unlink($db_file . "-journal") if -e $db_file . "-journal";
51 mkdir("t/var") unless -d "t/var";
52
53 my $dsn = $ENV{"DBICTEST_DSN"} || "dbi:SQLite:${db_file}";
54 my $dbuser = $ENV{"DBICTEST_DBUSER"} || '';
55 my $dbpass = $ENV{"DBICTEST_DBPASS"} || '';
56
57 my $schema = DBICTest::Schema->compose_namespace('DBICTest')
58 ->connect($dsn, $dbuser, $dbpass);
59 $schema->storage->on_connect_do(['PRAGMA synchronous = OFF']);
60 if ( !$args{no_deploy} ) {
61 __PACKAGE__->deploy_schema( $schema );
62 __PACKAGE__->populate_schema( $schema ) if( !$args{no_populate} );
63 }
64 return $schema;
65 }
66
67 =head2 deploy_schema
68
69 DBICTest->deploy_schema( $schema );
70
71 This method does one of two things to the schema. It can either call
72 the experimental $schema->deploy() if the DBICTEST_SQLT_DEPLOY environment
73 variable is set, otherwise the default is to read in the t/lib/sqlite.sql
74 file and execute the SQL within. Either way you end up with a fresh set
75 of tables for testing.
76
77 =cut
78
79 sub deploy_schema {
80 my $self = shift;
81 my $schema = shift;
82
83 if ($ENV{"DBICTEST_SQLT_DEPLOY"}) {
84 return $schema->deploy();
85 } else {
86 open IN, "t/lib/sqlite.sql";
87 my $sql;
88 { local $/ = undef; $sql = <IN>; }
89 close IN;
90 ($schema->storage->dbh->do($_) || print "Error on SQL: $_\n") for split(/;\n/, $sql);
91 }
92 }
93
94 =head2 populate_schema
95
96 DBICTest->populate_schema( $schema );
97
98 After you deploy your schema you can use this method to populate
99 the tables with test data.
100
101 =cut
102
103 sub populate_schema {
104 my $self = shift;
105 my $schema = shift;
106
107 $schema->populate('Host', [
108 [ qw/hostname address/ ],
109 [ 'localhost', 2130706433 ],
110 ]);
111
112 $schema->populate('Network', [
113 [ qw/netname address/ ],
114 [ qw{localnet 127.0.0.0/8} ],
115 ]);
116 }
117
118 1;
0 CREATE TABLE host (
1 hostname TEXT NOT NULL PRIMARY KEY,
2 address INTEGER NOT NULL UNIQUE
3 );
4
5 CREATE TABLE network (
6 netname TEXT NOT NULL PRIMARY KEY,
7 address VARCHAR(18) NOT NULL UNIQUE
8 );
0 #!perl -T
1
2 use Test::More;
3 eval "use Test::Pod::Coverage 1.04";
4 plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@;
5 all_pod_coverage_ok();
0 #!perl -T
1
2 use Test::More;
3 eval "use Test::Pod 1.14";
4 plan skip_all => "Test::Pod 1.14 required for testing POD" if $@;
5 all_pod_files_ok();
0 #!perl -T
1 use strict;
2 use warnings;
3
4 use Test::More;
5
6 if (not $ENV{TEST_AUTHOR}) {
7 plan skip_all => 'set TEST_AUTHOR to enable this test';
8 }
9 else {
10 eval 'use Test::NoTabs 0.03';
11 if ($@) {
12 plan skip_all => 'Test::NoTabs 0.03 not installed';
13 }
14 else {
15 plan tests => 1;
16 }
17 }
18
19 all_perl_files_ok('lib');