Codebase list libconvert-pem-perl / 3edd91f
New upstream release Jose Luis Rivas Contreras 13 years ago
39 changed file(s) with 6677 addition(s) and 1399 deletion(s). Raw diff Collapse all Expand all
0 $Id: Changes 1832 2005-05-25 22:39:55Z btrott $
0 Revision history for Convert::PEM
11
2 Revision history for Convert::PEM
2 0.08 2010.12.06
3 - Altered explode() to canonicalize line endings to \n, handling
4 DOS (\r\n) and older mac (\r) line breaks cleanly. Thanks to Matt
5 Gramlich for the patch.
6 - Removed sign() and auto_install() from Makefile.PL.
7 - Removed magic svn keywords.
8 - Converted test suite to Test::More.
9 - Added author tests (xt/) and modified SYNOPSIS for all modules to
10 make them pass the compilation test.
311
412 0.07 2005.05.25
513 - Allow passing in Name and Macro parameters on encode and decode,
00 Changes
1 inc/ExtUtils/AutoInstall.pm
21 inc/Module/Install.pm
3 inc/Module/Install/AutoInstall.pm
2 inc/Module/Install/AuthorTests.pm
43 inc/Module/Install/Base.pm
54 inc/Module/Install/Can.pm
65 inc/Module/Install/Fetch.pm
76 inc/Module/Install/Include.pm
87 inc/Module/Install/Makefile.pm
98 inc/Module/Install/Metadata.pm
9 inc/Module/Install/ReadmeFromPod.pm
10 inc/Module/Install/Repository.pm
11 inc/Module/Install/TestBase.pm
1012 inc/Module/Install/Win32.pm
1113 inc/Module/Install/WriteAll.pm
14 inc/Spiffy.pm
15 inc/Sub/Uplevel.pm
16 inc/Test/Base.pm
17 inc/Test/Base/Filter.pm
18 inc/Test/Builder.pm
19 inc/Test/Builder/Module.pm
20 inc/Test/Exception.pm
21 inc/Test/More.pm
1222 lib/Convert/PEM.pm
1323 lib/Convert/PEM/CBC.pm
1424 Makefile.PL
1929 t/01-readwrite.t
2030 t/02-encode.t
2131 t/03-ede3.t
22 ToDo
32 t/04-explode.t
33 xt/pod.t
34 xt/synopsis.t
0 ---
1 abstract: 'Read/write encrypted ASN.1 PEM files'
2 author:
3 - '& COPYRIGHTS'
4 build_requires:
5 ExtUtils::MakeMaker: 6.42
6 configure_requires:
7 ExtUtils::MakeMaker: 6.42
8 distribution_type: module
9 generated_by: 'Module::Install version 1.00'
10 license: perl
11 meta-spec:
12 url: http://module-build.sourceforge.net/META-spec-v1.4.html
13 version: 1.4
014 name: Convert-PEM
1 version: 0.07
2 abstract: Read/write encrypted ASN.1 PEM files
3 author: Benjamin Trott <ben+cpan@stupidfool.org>
4 license: perl
5 distribution_type: module
15 no_index:
16 directory:
17 - inc
18 - t
19 - xt
620 requires:
721 Class::ErrorHandler: 0
22 Convert::ASN1: 0.10
23 Crypt::DES_EDE3: 0
24 Digest::MD5: 0
25 Filter::Util::Call: 0
826 MIME::Base64: 0
9 Convert::ASN1: 0.10
10 Digest::MD5: 0
11 Crypt::DES_EDE3: 0
12 no_index:
13 directory:
14 - t
15 - inc
16 generated_by: Module::Install version 0.36
27 perl: 5.8.1
28 resources:
29 license: http://dev.perl.org/licenses/
30 repository: git://github.com/btrott/Convert-PEM.git
31 version: 0.08
0 # $Id: Makefile.PL 1829 2005-05-25 21:51:40Z btrott $
0 use inc::Module::Install;
1 name 'Convert-PEM';
2 all_from 'lib/Convert/PEM.pm';
3 readme_from 'lib/Convert/PEM.pm';
14
2 use inc::Module::Install;
5 requires 'Class::ErrorHandler';
6 requires 'MIME::Base64';
7 requires 'Convert::ASN1' => '0.10';
8 requires 'Digest::MD5';
9 requires 'Crypt::DES_EDE3';
310
4 name('Convert-PEM');
5 abstract('Read/write encrypted ASN.1 PEM files');
6 author('Benjamin Trott <ben+cpan@stupidfool.org>');
7 version_from('lib/Convert/PEM.pm');
8 license('perl');
9 no_index(directory => 't');
10 sign(1);
11 test_requires 'Test::More';
12 test_requires 'Test::Exception';
1113
12 include('ExtUtils::AutoInstall');
13
14 requires('Class::ErrorHandler');
15 requires('MIME::Base64');
16 requires('Convert::ASN1' => '0.10');
17 requires('Digest::MD5');
18 requires('Crypt::DES_EDE3');
19
20 auto_include();
21 auto_install();
22
23 &WriteAll;
14 use_test_base;
15 auto_include_deps;
16 author_tests('xt');
17 auto_set_repository;
18 WriteAll;
+231
-35
README less more
0 $Id: README 1829 2005-05-25 21:51:40Z btrott $
1
2 This is Convert::PEM, a module implementing read/write access
3 to ASN.1-encoded PEM files (with optional encryption).
4
5 PREREQUISITES
6
7 * Crypt::ErrorHandler
8 * MIME::Base64
9 * Convert::ASN1 (0.10 or greater)
10 * Digest::MD5
11 * Crypt::DES_EDE3
12
13 INSTALLATION
14
15 Convert::PEM installation is straightforward. If your cpan shell
16 is set up, you should just be able to do
17
18 % perl -MCPAN -e 'install Convert::PEM'
19
20 If you don't like that, you can download the distribution; the
21 latest version on CPAN can be found in
22
23 ftp://ftp.cpan.org/pub/CPAN/authors/id/B/BT/BTROTT/
24
25 Download it, unpack it, then build it as per the usual:
26
27 % perl Makefile.PL
28 % make && make test
29
30 Then install it:
31
32 % make install
33
34 Benjamin Trott / ben@rhumba.pair.com
0 NAME
1 Convert::PEM - Read/write encrypted ASN.1 PEM files
2
3 SYNOPSIS
4 use Convert::PEM;
5 my $pem = Convert::PEM->new(
6 Name => "DSA PRIVATE KEY",
7 ASN => qq(
8 DSAPrivateKey SEQUENCE {
9 version INTEGER,
10 p INTEGER,
11 q INTEGER,
12 g INTEGER,
13 pub_key INTEGER,
14 priv_key INTEGER
15 }
16 ));
17
18 my $keyfile = 'private-key.pem';
19 my $pwd = 'foobar';
20
21 my $pkey = $pem->read(
22 Filename => $keyfile,
23 Password => $pwd
24 );
25
26 $pem->write(
27 Content => $pkey,
28 Password => $pwd,
29 Filename => $keyfile
30 );
31
32 DESCRIPTION
33 *Convert::PEM* reads and writes PEM files containing ASN.1-encoded
34 objects. The files can optionally be encrypted using a symmetric cipher
35 algorithm, such as 3DES. An unencrypted PEM file might look something
36 like this:
37
38 -----BEGIN DH PARAMETERS-----
39 MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM=
40 -----END DH PARAMETERS-----
41
42 The string beginning "MB4C..." is the Base64-encoded, ASN.1-encoded
43 "object."
44
45 An encrypted file would have headers describing the type of encryption
46 used, and the initialization vector:
47
48 -----BEGIN DH PARAMETERS-----
49 Proc-Type: 4,ENCRYPTED
50 DEK-Info: DES-EDE3-CBC,C814158661DC1449
51
52 AFAZFbnQNrGjZJ/ZemdVSoZa3HWujxZuvBHzHNoesxeyqqidFvnydA==
53 -----END DH PARAMETERS-----
54
55 The two headers ("Proc-Type" and "DEK-Info") indicate information about
56 the type of encryption used, and the string starting with "AFAZ..." is
57 the Base64-encoded, encrypted, ASN.1-encoded contents of this "object."
58
59 The initialization vector ("C814158661DC1449") is chosen randomly.
60
61 USAGE
62 $pem = Convert::PEM->new( %arg )
63 Constructs a new *Convert::PEM* object designed to read/write an object
64 of a specific type (given in *%arg*, see below). Returns the new object
65 on success, "undef" on failure (see *ERROR HANDLING* for details).
66
67 *%arg* can contain:
68
69 * Name
70
71 The name of the object; when decoding a PEM-encoded stream, the name
72 in the encoding will be checked against the value of *Name*.
73 Similarly, when encoding an object, the value of *Name* will be used
74 as the name of the object in the PEM-encoded content. For example,
75 given the string "FOO BAR", the output from *encode* will start with
76 a header like:
77
78 -----BEGIN FOO BAR-----
79
80 *Name* is a required argument.
81
82 * ASN
83
84 An ASN.1 description of the content to be either encoded or decoded.
85
86 *ASN* is a required argument.
87
88 * Macro
89
90 If your ASN.1 description (in the *ASN* parameter) includes more
91 than one ASN.1 macro definition, you will want to use the *Macro*
92 parameter to specify which definition to use when encoding/decoding
93 objects. For example, if your ASN.1 description looks like this:
94
95 Foo ::= SEQUENCE {
96 x INTEGER,
97 bar Bar
98 }
99
100 Bar ::= INTEGER
101
102 If you want to encode/decode a "Foo" object, you will need to tell
103 *Convert::PEM* to use the "Foo" macro definition by using the
104 *Macro* parameter and setting the value to "Foo".
105
106 *Macro* is an optional argument.
107
108 $obj = $pem->decode(%args)
109 Decodes, and, optionally, decrypts a PEM file, returning the object as
110 decoded by *Convert::ASN1*. The difference between this method and
111 *read* is that *read* reads the contents of a PEM file on disk; this
112 method expects you to pass the PEM contents as an argument.
113
114 If an error occurs while reading the file or decrypting/decoding the
115 contents, the function returns *undef*, and you should check the error
116 message using the *errstr* method (below).
117
118 *%args* can contain:
119
120 * Content
121
122 The PEM contents.
123
124 * Password
125
126 The password with which the file contents were encrypted.
127
128 If the file is encrypted, this is a mandatory argument (well, it's
129 not strictly mandatory, but decryption isn't going to work without
130 it). Otherwise it's not necessary.
131
132 $blob = $pem->encode(%args)
133 Constructs the contents for the PEM file from an object: ASN.1-encodes
134 the object, optionally encrypts those contents.
135
136 Returns *undef* on failure (encryption failure, file-writing failure,
137 etc.); in this case you should check the error message using the
138 *errstr* method (below). On success returns the constructed PEM string.
139
140 *%args* can contain:
141
142 * Content
143
144 A hash reference that will be passed to *Convert::ASN1::encode*, and
145 which should correspond to the ASN.1 description you gave to the
146 *new* method. The hash reference should have the exact same format
147 as that returned from the *read* method.
148
149 This argument is mandatory.
150
151 * Password
152
153 A password used to encrypt the contents of the PEM file. This is an
154 optional argument; if not provided the contents will be unencrypted.
155
156 $obj = $pem->read(%args)
157 Reads, decodes, and, optionally, decrypts a PEM file, returning the
158 object as decoded by *Convert::ASN1*. This is implemented as a wrapper
159 around *decode*, with the bonus of reading the PEM file from disk for
160 you.
161
162 If an error occurs while reading the file or decrypting/decoding the
163 contents, the function returns *undef*, and you should check the error
164 message using the *errstr* method (below).
165
166 In addition to the arguments that can be passed to the *decode* method
167 (minus the *Content* method), *%args* can contain:
168
169 * Filename
170
171 The location of the PEM file that you wish to read.
172
173 $pem->write(%args)
174 Constructs the contents for the PEM file from an object: ASN.1-encodes
175 the object, optionally encrypts those contents; then writes the file to
176 disk. This is implemented as a wrapper around *encode*, with the bonus
177 of writing the file to disk for you.
178
179 Returns *undef* on failure (encryption failure, file-writing failure,
180 etc.); in this case you should check the error message using the
181 *errstr* method (below). On success returns the constructed PEM string.
182
183 In addition to the arguments for *encode*, *%args* can contain:
184
185 * Filename
186
187 The location on disk where you'd like the PEM file written.
188
189 $pem->errstr
190 Returns the value of the last error that occurred. This should only be
191 considered meaningful when you've received *undef* from one of the
192 functions above; in all other cases its relevance is undefined.
193
194 $pem->asn
195 Returns the *Convert::ASN1* object used internally to decode and encode
196 ASN.1 representations. This is useful when you wish to interact directly
197 with that object; for example, if you need to call *configure* on that
198 object to set the type of big-integer class to be used when
199 decoding/encoding big integers:
200
201 $pem->asn->configure( decode => { bigint => 'Math::Pari' },
202 encode => { bigint => 'Math::Pari' } );
203
204 ERROR HANDLING
205 If an error occurs in any of the above methods, the method will return
206 "undef". You should then call the method *errstr* to determine the
207 source of the error:
208
209 $pem->errstr
210
211 In the case that you do not yet have a *Convert::PEM* object (that is,
212 if an error occurs while creating a *Convert::PEM* object), the error
213 can be obtained as a class method:
214
215 Convert::PEM->errstr
216
217 For example, if you try to decode an encrypted object, and you do not
218 give a passphrase to decrypt the object:
219
220 my $obj = $pem->read( Filename => "encrypted.pem" )
221 or die "Decryption failed: ", $pem->errstr;
222
223 LICENSE
224 Convert::PEM is free software; you may redistribute it and/or modify it
225 under the same terms as Perl itself.
226
227 AUTHOR & COPYRIGHTS
228 Except where otherwise noted, Convert::PEM is Copyright Benjamin Trott,
229 cpan@stupidfool.org. All rights reserved.
230
+0
-1
ToDo less more
0 $Id: ToDo 87 2001-04-22 07:31:42Z btrott $
0 libconvert-pem-perl (0.07-3) UNRELEASED; urgency=low
0 libconvert-pem-perl (0.08-1) UNRELEASED; urgency=low
11
22 [ gregor herrmann ]
33 * debian/control: Changed: Switched Vcs-Browser field to ViewSVN
99 [ gregor herrmann ]
1010 * Change my email address.
1111
12 -- gregor herrmann <gregoa@debian.org> Sun, 16 Nov 2008 20:40:56 +0100
12 [ Jose Luis Rivas ]
13 * New upstream release
14
15 -- Jose Luis Rivas <ghostbar@debian.org> Sat, 25 Dec 2010 13:00:46 -0430
1316
1417 libconvert-pem-perl (0.07-2) unstable; urgency=low
1518
+0
-631
inc/ExtUtils/AutoInstall.pm less more
0 #line 1 "inc/ExtUtils/AutoInstall.pm - /Library/Perl/5.8.1/ExtUtils/AutoInstall.pm"
1 # $File: //member/autrijus/ExtUtils-AutoInstall/lib/ExtUtils/AutoInstall.pm $
2 # $Revision: #9 $ $Change: 9532 $ $DateTime: 2004/01/01 06:47:30 $ vim: expandtab shiftwidth=4
3
4 package ExtUtils::AutoInstall;
5 $ExtUtils::AutoInstall::VERSION = '0.56';
6
7 use strict;
8 use Cwd ();
9 use ExtUtils::MakeMaker ();
10
11 #line 282
12
13 # special map on pre-defined feature sets
14 my %FeatureMap = (
15 '' => 'Core Features', # XXX: deprecated
16 '-core' => 'Core Features',
17 );
18
19 # various lexical flags
20 my (@Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS);
21 my ($Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly);
22 my ($PostambleActions, $PostambleUsed);
23
24 $AcceptDefault = 1 unless -t STDIN; # non-interactive session
25 _init();
26
27 sub missing_modules {
28 return @Missing;
29 }
30
31 sub do_install {
32 __PACKAGE__->install(
33 [ UNIVERSAL::isa($Config, 'HASH') ? %{$Config} : @{$Config}],
34 @Missing,
35 );
36 }
37
38 # initialize various flags, and/or perform install
39 sub _init {
40 foreach my $arg (@ARGV, split(/[\s\t]+/, $ENV{PERL_EXTUTILS_AUTOINSTALL} || '')) {
41 if ($arg =~ /^--config=(.*)$/) {
42 $Config = [ split(',', $1) ];
43 }
44 elsif ($arg =~ /^--installdeps=(.*)$/) {
45 __PACKAGE__->install($Config, @Missing = split(/,/, $1));
46 exit 0;
47 }
48 elsif ($arg =~ /^--default(?:deps)?$/) {
49 $AcceptDefault = 1;
50 }
51 elsif ($arg =~ /^--check(?:deps)?$/) {
52 $CheckOnly = 1;
53 }
54 elsif ($arg =~ /^--skip(?:deps)?$/) {
55 $SkipInstall = 1;
56 }
57 elsif ($arg =~ /^--test(?:only)?$/) {
58 $TestOnly = 1;
59 }
60 }
61 }
62
63 # overrides MakeMaker's prompt() to automatically accept the default choice
64 sub _prompt {
65 goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault;
66
67 my ($prompt, $default) = @_;
68 my $y = ($default =~ /^[Yy]/);
69
70 print $prompt, ' [', ($y ? 'Y' : 'y'), '/', ($y ? 'n' : 'N'), '] ';
71 print "$default\n";
72 return $default;
73 }
74
75 # the workhorse
76 sub import {
77 my $class = shift;
78 my @args = @_ or return;
79 my $core_all;
80
81 print "*** $class version ".$class->VERSION."\n";
82 print "*** Checking for dependencies...\n";
83
84 my $cwd = Cwd::cwd();
85
86 $Config = [];
87
88 my $maxlen = length((sort { length($b) <=> length($a) }
89 grep { /^[^\-]/ }
90 map { ref($_) ? keys %{ref($_) eq 'HASH' ? $_ : +{@{$_}}} : '' }
91 map { +{@args}->{$_} }
92 grep { /^[^\-]/ or /^-core$/i } keys %{+{@args}})[0]);
93
94 while (my ($feature, $modules) = splice(@args, 0, 2)) {
95 my (@required, @tests, @skiptests);
96 my $default = 1;
97 my $conflict = 0;
98
99 if ($feature =~ m/^-(\w+)$/) {
100 my $option = lc($1);
101
102 # check for a newer version of myself
103 _update_to($modules, @_) and return if $option eq 'version';
104
105 # sets CPAN configuration options
106 $Config = $modules if $option eq 'config';
107
108 # promote every features to core status
109 $core_all = ($modules =~ /^all$/i) and next
110 if $option eq 'core';
111
112 next unless $option eq 'core';
113 }
114
115 print "[".($FeatureMap{lc($feature)} || $feature)."]\n";
116
117 $modules = [ %{$modules} ] if UNIVERSAL::isa($modules, 'HASH');
118
119 unshift @$modules, -default => &{shift(@$modules)}
120 if (ref($modules->[0]) eq 'CODE'); # XXX: bugward combatability
121
122 while (my ($mod, $arg) = splice(@$modules, 0, 2)) {
123 if ($mod =~ m/^-(\w+)$/) {
124 my $option = lc($1);
125
126 $default = $arg if ($option eq 'default');
127 $conflict = $arg if ($option eq 'conflict');
128 @tests = @{$arg} if ($option eq 'tests');
129 @skiptests = @{$arg} if ($option eq 'skiptests');
130
131 next;
132 }
133
134 printf("- %-${maxlen}s ...", $mod);
135
136 # XXX: check for conflicts and uninstalls(!) them.
137 if (defined(my $cur = _version_check(_load($mod), $arg ||= 0))) {
138 print "loaded. ($cur".($arg ? " >= $arg" : '').")\n";
139 push @Existing, $mod => $arg;
140 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
141 }
142 else {
143 print "missing." . ($arg ? " (would need $arg)" : '') . "\n";
144 push @required, $mod => $arg;
145 }
146 }
147
148 next unless @required;
149
150 my $mandatory = ($feature eq '-core' or $core_all);
151
152 if (!$SkipInstall and ($CheckOnly or _prompt(
153 qq{==> Auto-install the }. (@required / 2).
154 ($mandatory ? ' mandatory' : ' optional').
155 qq{ module(s) from CPAN?}, $default ? 'y' : 'n',
156 ) =~ /^[Yy]/)) {
157 push (@Missing, @required);
158 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
159 }
160
161 elsif (!$SkipInstall and $default and $mandatory and _prompt(
162 qq{==> The module(s) are mandatory! Really skip?}, 'n',
163 ) =~ /^[Nn]/) {
164 push (@Missing, @required);
165 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
166 }
167
168 else {
169 $DisabledTests{$_} = 1 for map { glob($_) } @tests;
170 }
171 }
172
173 _check_lock(); # check for $UnderCPAN
174
175 if (@Missing and not ($CheckOnly or $UnderCPAN)) {
176 require Config;
177 print "*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n";
178 # make an educated guess of whether we'll need root permission.
179 print " (You may need to do that as the 'root' user.)\n" if eval '$>';
180 }
181 print "*** $class configuration finished.\n";
182
183 chdir $cwd;
184
185 # import to main::
186 no strict 'refs';
187 *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main';
188 }
189
190 # CPAN.pm is non-reentrant, so check if we're under it and have no CPANPLUS
191 sub _check_lock {
192 return unless @Missing;
193 return if _has_cpanplus();
194
195 require CPAN; CPAN::Config->load;
196 my $lock = MM->catfile($CPAN::Config->{cpan_home}, ".lock");
197
198 if (-f $lock and open(LOCK, $lock)
199 and ($^O eq 'MSWin32' ? _under_cpan() : <LOCK> == getppid())
200 and ($CPAN::Config->{prerequisites_policy} || '') ne 'ignore'
201 ) {
202 print << '.';
203
204 *** Since we're running under CPAN, I'll just let it take care
205 of the dependency's installation later.
206 .
207 $UnderCPAN = 1;
208 }
209
210 close LOCK;
211 }
212
213 sub install {
214 my $class = shift;
215
216 my $i; # used below to strip leading '-' from config keys
217 my @config = (map { s/^-// if ++$i; $_ } @{+shift});
218
219 my (@modules, @installed);
220 while (my ($pkg, $ver) = splice(@_, 0, 2)) {
221 # grep out those already installed
222 if (defined(_version_check(_load($pkg), $ver))) {
223 push @installed, $pkg;
224 }
225 else {
226 push @modules, $pkg, $ver;
227 }
228 }
229
230 return @installed unless @modules; # nothing to do
231
232 print "*** Installing dependencies...\n";
233
234 return unless _connected_to('cpan.org');
235
236 my %args = @config;
237 my %failed;
238 local *FAILED;
239 if ($args{do_once} and open(FAILED, '.#autoinstall.failed')) {
240 while (<FAILED>) { chomp; $failed{$_}++ }
241 close FAILED;
242
243 my @newmod;
244 while (my ($k, $v) = splice(@modules, 0, 2)) {
245 push @newmod, ($k => $v) unless $failed{$k};
246 }
247 @modules = @newmod;
248 }
249
250 if (_has_cpanplus()) {
251 _install_cpanplus(\@modules, \@config);
252 }
253 else {
254 _install_cpan(\@modules, \@config);
255 }
256
257 print "*** $class installation finished.\n";
258
259 # see if we have successfully installed them
260 while (my ($pkg, $ver) = splice(@modules, 0, 2)) {
261 if (defined(_version_check(_load($pkg), $ver))) {
262 push @installed, $pkg;
263 }
264 elsif ($args{do_once} and open(FAILED, '>> .#autoinstall.failed')) {
265 print FAILED "$pkg\n";
266 }
267 }
268
269 close FAILED if $args{do_once};
270
271 return @installed;
272 }
273
274 sub _install_cpanplus {
275 my @modules = @{+shift};
276 my @config = @{+shift};
277 my $installed = 0;
278
279 require CPANPLUS::Backend;
280 my $cp = CPANPLUS::Backend->new;
281 my $conf = $cp->configure_object;
282
283 return unless _can_write($conf->_get_build('base'));
284
285 # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
286 my $makeflags = $conf->get_conf('makeflags') || '';
287 if (UNIVERSAL::isa($makeflags, 'HASH')) {
288 # 0.03+ uses a hashref here
289 $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST};
290 }
291 else {
292 # 0.02 and below uses a scalar
293 $makeflags = join(' ', split(' ', $makeflags), 'UNINST=1')
294 if ($makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' });
295 }
296 $conf->set_conf(makeflags => $makeflags);
297
298 while (my ($key, $val) = splice(@config, 0, 2)) {
299 eval { $conf->set_conf($key, $val) };
300 }
301
302 my $modtree = $cp->module_tree;
303 while (my ($pkg, $ver) = splice(@modules, 0, 2)) {
304 print "*** Installing $pkg...\n";
305
306 MY::preinstall($pkg, $ver) or next if defined &MY::preinstall;
307
308 my $success;
309 my $obj = $modtree->{$pkg};
310
311 if ($obj and defined(_version_check($obj->{version}, $ver))) {
312 my $pathname = $pkg; $pathname =~ s/::/\\W/;
313
314 foreach my $inc (grep { m/$pathname.pm/i } keys(%INC)) {
315 delete $INC{$inc};
316 }
317
318 my $rv = $cp->install( modules => [ $obj->{module} ]);
319
320 if ($rv and ($rv->{$obj->{module}} or $rv->{ok})) {
321 print "*** $pkg successfully installed.\n";
322 $success = 1;
323 }
324 else {
325 print "*** $pkg installation cancelled.\n";
326 $success = 0;
327 }
328
329 $installed += $success;
330 }
331 else {
332 print << ".";
333 *** Could not find a version $ver or above for $pkg; skipping.
334 .
335 }
336
337 MY::postinstall($pkg, $ver, $success) if defined &MY::postinstall;
338 }
339
340 return $installed;
341 }
342
343 sub _install_cpan {
344 my @modules = @{+shift};
345 my @config = @{+shift};
346 my $installed = 0;
347 my %args;
348
349 require CPAN; CPAN::Config->load;
350
351 return unless _can_write(MM->catfile($CPAN::Config->{cpan_home}, 'sources'));
352
353 # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
354 my $makeflags = $CPAN::Config->{make_install_arg} || '';
355 $CPAN::Config->{make_install_arg} = join(' ', split(' ', $makeflags), 'UNINST=1')
356 if ($makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' });
357
358 # don't show start-up info
359 $CPAN::Config->{inhibit_startup_message} = 1;
360
361 # set additional options
362 while (my ($opt, $arg) = splice(@config, 0, 2)) {
363 ($args{$opt} = $arg, next)
364 if $opt =~ /^force$/; # pseudo-option
365 $CPAN::Config->{$opt} = $arg;
366 }
367
368 while (my ($pkg, $ver) = splice(@modules, 0, 2)) {
369 MY::preinstall($pkg, $ver) or next if defined &MY::preinstall;
370
371 print "*** Installing $pkg...\n";
372
373 my $obj = CPAN::Shell->expand(Module => $pkg);
374 my $success = 0;
375
376 if ($obj and defined(_version_check($obj->cpan_version, $ver))) {
377 my $pathname = $pkg; $pathname =~ s/::/\\W/;
378
379 foreach my $inc (grep { m/$pathname.pm/i } keys(%INC)) {
380 delete $INC{$inc};
381 }
382
383 $obj->force('install') if $args{force};
384
385 if ($obj->install eq 'YES') {
386 print "*** $pkg successfully installed.\n";
387 $success = 1;
388 }
389 else {
390 print "*** $pkg installation failed.\n";
391 $success = 0;
392 }
393
394 $installed += $success;
395 }
396 else {
397 print << ".";
398 *** Could not find a version $ver or above for $pkg; skipping.
399 .
400 }
401
402 MY::postinstall($pkg, $ver, $success) if defined &MY::postinstall;
403 }
404
405 return $installed;
406 }
407
408 sub _has_cpanplus {
409 return (
410 $HasCPANPLUS = (
411 $INC{'CPANPLUS/Config.pm'} or
412 _load('CPANPLUS::Shell::Default')
413 )
414 );
415 }
416
417 # make guesses on whether we're under the CPAN installation directory
418 sub _under_cpan {
419 require Cwd;
420 require File::Spec;
421
422 my $cwd = File::Spec->canonpath(Cwd::cwd());
423 my $cpan = File::Spec->canonpath($CPAN::Config->{cpan_home});
424
425 return (index($cwd, $cpan) > -1);
426 }
427
428 sub _update_to {
429 my $class = __PACKAGE__;
430 my $ver = shift;
431
432 return if defined(_version_check(_load($class), $ver)); # no need to upgrade
433
434 if (_prompt(
435 "==> A newer version of $class ($ver) is required. Install?", 'y'
436 ) =~ /^[Nn]/) {
437 die "*** Please install $class $ver manually.\n";
438 }
439
440 print << ".";
441 *** Trying to fetch it from CPAN...
442 .
443
444 # install ourselves
445 _load($class) and return $class->import(@_)
446 if $class->install([], $class, $ver);
447
448 print << '.'; exit 1;
449
450 *** Cannot bootstrap myself. :-( Installation terminated.
451 .
452 }
453
454 # check if we're connected to some host, using inet_aton
455 sub _connected_to {
456 my $site = shift;
457
458 return (
459 ( _load('Socket') and Socket::inet_aton($site) ) or _prompt(qq(
460 *** Your host cannot resolve the domain name '$site', which
461 probably means the Internet connections are unavailable.
462 ==> Should we try to install the required module(s) anyway?), 'n'
463 ) =~ /^[Yy]/
464 );
465 }
466
467 # check if a directory is writable; may create it on demand
468 sub _can_write {
469 my $path = shift;
470 mkdir ($path, 0755) unless -e $path;
471
472 require Config;
473 return 1 if -w $path and -w $Config::Config{sitelib};
474
475 print << ".";
476 *** You are not allowed to write to the directory '$path';
477 the installation may fail due to insufficient permissions.
478 .
479
480 if (eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt(qq(
481 ==> Should we try to re-execute the autoinstall process with 'sudo'?), 'y'
482 ) =~ /^[Yy]/) {
483 # try to bootstrap ourselves from sudo
484 print << ".";
485 *** Trying to re-execute the autoinstall process with 'sudo'...
486 .
487 my $missing = join(',', @Missing);
488 my $config = join(',',
489 UNIVERSAL::isa($Config, 'HASH') ? %{$Config} : @{$Config}
490 ) if $Config;
491
492 return unless system('sudo', $^X, $0, "--config=$config", "--installdeps=$missing");
493
494 print << ".";
495 *** The 'sudo' command exited with error! Resuming...
496 .
497 }
498
499 return _prompt(qq(
500 ==> Should we try to install the required module(s) anyway?), 'n'
501 ) =~ /^[Yy]/
502 }
503
504 # load a module and return the version it reports
505 sub _load {
506 my $mod = pop; # class/instance doesn't matter
507 my $file = $mod;
508
509 $file =~ s|::|/|g;
510 $file .= '.pm';
511
512 local $@;
513 return eval { require $file; $mod->VERSION } || ($@ ? undef : 0);
514 }
515
516 # compare two versions, either use Sort::Versions or plain comparison
517 sub _version_check {
518 my ($cur, $min) = @_;
519 return unless defined $cur;
520
521 $cur =~ s/\s+$//;
522
523 # check for version numbers that are not in decimal format
524 if (ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./) {
525 if ($version::VERSION or defined(_load('version'))) {
526 # use version.pm if it is installed.
527 return ((version->new($cur) >= version->new($min)) ? $cur : undef);
528 }
529 elsif ($Sort::Versions::VERSION or defined(_load('Sort::Versions'))) {
530 # use Sort::Versions as the sorting algorithm for a.b.c versions
531 return ((Sort::Versions::versioncmp($cur, $min) != -1) ? $cur : undef);
532 }
533
534 warn "Cannot reliably compare non-decimal formatted versions.\n".
535 "Please install version.pm or Sort::Versions.\n";
536 }
537
538 # plain comparison
539 local $^W = 0; # shuts off 'not numeric' bugs
540 return ($cur >= $min ? $cur : undef);
541 }
542
543 # nothing; this usage is deprecated.
544 sub main::PREREQ_PM { return {}; }
545
546 sub _make_args {
547 my %args = @_;
548
549 $args{PREREQ_PM} = { %{$args{PREREQ_PM} || {} }, @Existing, @Missing }
550 if $UnderCPAN or $TestOnly;
551
552 if ($args{EXE_FILES}) {
553 require ExtUtils::Manifest;
554 my $manifest = ExtUtils::Manifest::maniread('MANIFEST');
555
556 $args{EXE_FILES} = [
557 grep { exists $manifest->{$_} } @{$args{EXE_FILES}}
558 ];
559 }
560
561 $args{test}{TESTS} ||= 't/*.t';
562 $args{test}{TESTS} = join(' ', grep {
563 !exists($DisabledTests{$_})
564 } map { glob($_) } split(/\s+/, $args{test}{TESTS}));
565
566 my $missing = join(',', @Missing);
567 my $config = join(',',
568 UNIVERSAL::isa($Config, 'HASH') ? %{$Config} : @{$Config}
569 ) if $Config;
570
571 $PostambleActions = (
572 $missing ? "\$(PERL) $0 --config=$config --installdeps=$missing"
573 : "\@\$(NOOP)"
574 );
575
576 return %args;
577 }
578
579 # a wrapper to ExtUtils::MakeMaker::WriteMakefile
580 sub Write {
581 require Carp;
582 Carp::croak "WriteMakefile: Need even number of args" if @_ % 2;
583
584 if ($CheckOnly) {
585 print << ".";
586 *** Makefile not written in check-only mode.
587 .
588 return;
589 }
590
591 my %args = _make_args(@_);
592
593 no strict 'refs';
594
595 $PostambleUsed = 0;
596 local *MY::postamble = \&postamble unless defined &MY::postamble;
597 ExtUtils::MakeMaker::WriteMakefile(%args);
598
599 print << "." unless $PostambleUsed;
600 *** WARNING: Makefile written with customized MY::postamble() without
601 including contents from ExtUtils::AutoInstall::postamble() --
602 auto installation features disabled. Please contact the author.
603 .
604
605 return 1;
606 }
607
608 sub postamble {
609 $PostambleUsed = 1;
610
611 return << ".";
612
613 config :: installdeps
614 \t\@\$(NOOP)
615
616 checkdeps ::
617 \t\$(PERL) $0 --checkdeps
618
619 installdeps ::
620 \t$PostambleActions
621
622 .
623
624 }
625
626 1;
627
628 __END__
629
630 #line 929
0 #line 1
1 package Module::Install::AuthorTests;
2
3 use 5.005;
4 use strict;
5 use Module::Install::Base;
6 use Carp ();
7
8 #line 16
9
10 use vars qw{$VERSION $ISCORE @ISA};
11 BEGIN {
12 $VERSION = '0.002';
13 $ISCORE = 1;
14 @ISA = qw{Module::Install::Base};
15 }
16
17 #line 42
18
19 sub author_tests {
20 my ($self, @dirs) = @_;
21 _add_author_tests($self, \@dirs, 0);
22 }
23
24 #line 56
25
26 sub recursive_author_tests {
27 my ($self, @dirs) = @_;
28 _add_author_tests($self, \@dirs, 1);
29 }
30
31 sub _wanted {
32 my $href = shift;
33 sub { /\.t$/ and -f $_ and $href->{$File::Find::dir} = 1 }
34 }
35
36 sub _add_author_tests {
37 my ($self, $dirs, $recurse) = @_;
38 return unless $Module::Install::AUTHOR;
39
40 my @tests = $self->tests ? (split / /, $self->tests) : 't/*.t';
41
42 # XXX: pick a default, later -- rjbs, 2008-02-24
43 my @dirs = @$dirs ? @$dirs : Carp::confess "no dirs given to author_tests";
44 @dirs = grep { -d } @dirs;
45
46 if ($recurse) {
47 require File::Find;
48 my %test_dir;
49 File::Find::find(_wanted(\%test_dir), @dirs);
50 $self->tests( join ' ', @tests, map { "$_/*.t" } sort keys %test_dir );
51 } else {
52 $self->tests( join ' ', @tests, map { "$_/*.t" } sort @dirs );
53 }
54 }
55
56 #line 107
57
58 1;
+0
-62
inc/Module/Install/AutoInstall.pm less more
0 #line 1 "inc/Module/Install/AutoInstall.pm - /Library/Perl/5.8.1/Module/Install/AutoInstall.pm"
1 package Module::Install::AutoInstall;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
3
4 sub AutoInstall { $_[0] }
5
6 sub run {
7 my $self = shift;
8 $self->auto_install_now(@_);
9 }
10
11 sub write {
12 my $self = shift;
13 $self->auto_install(@_);
14 }
15
16 sub auto_install {
17 my $self = shift;
18 return if $self->{done}++;
19
20 # ExtUtils::AutoInstall Bootstrap Code, version 7.
21 AUTO:{my$p='ExtUtils::AutoInstall';my$v=0.49;$p->VERSION||0>=$v
22 or+eval"use $p $v;1"or+do{my$e=$ENV{PERL_EXTUTILS_AUTOINSTALL};
23 (!defined($e)||$e!~m/--(?:default|skip|testonly)/and-t STDIN or
24 eval"use ExtUtils::MakeMaker;WriteMakefile(PREREQ_PM=>{'$p',$v}
25 );1"and exit)and print"==> $p $v required. Install it from CP".
26 "AN? [Y/n] "and<STDIN>!~/^n/i and print"*** Installing $p\n"and
27 do{if (eval '$>' and lc(`sudo -V`) =~ /version/){system('sudo',
28 $^X,"-MCPANPLUS","-e","CPANPLUS::install $p");eval"use $p $v;1"
29 ||system('sudo', $^X, "-MCPAN", "-e", "CPAN::install $p")}eval{
30 require CPANPLUS;CPANPLUS::install$p};eval"use $p $v;1"or eval{
31 require CPAN;CPAN::install$p};eval"use $p $v;1"||die"*** Please
32 manually install $p $v from cpan.org first...\n"}}}
33
34 # Flatten array of arrays into a single array
35 my @core = map @$_, map @$_, grep ref,
36 $self->build_requires, $self->requires;
37
38 while ( @core and @_ > 1 and $_[0] =~ /^-\w+$/ ) {
39 push @core, splice(@_, 0, 2);
40 }
41
42 ExtUtils::AutoInstall->import(
43 (@core ? (-core => \@core) : ()), @_, $self->features
44 );
45
46 $self->makemaker_args( ExtUtils::AutoInstall::_make_args() );
47
48 my $class = ref($self);
49 $self->postamble(
50 "# --- $class section:\n" .
51 ExtUtils::AutoInstall::postamble()
52 );
53 }
54
55 sub auto_install_now {
56 my $self = shift;
57 $self->auto_install;
58 ExtUtils::AutoInstall::do_install();
59 }
60
61 1;
0 #line 1 "inc/Module/Install/Base.pm - /Library/Perl/5.8.1/Module/Install/Base.pm"
0 #line 1
11 package Module::Install::Base;
22
3 #line 28
3 use strict 'vars';
4 use vars qw{$VERSION};
5 BEGIN {
6 $VERSION = '1.00';
7 }
8
9 # Suspend handler for "redefined" warnings
10 BEGIN {
11 my $w = $SIG{__WARN__};
12 $SIG{__WARN__} = sub { $w };
13 }
14
15 #line 42
416
517 sub new {
6 my ($class, %args) = @_;
7
8 foreach my $method (qw(call load)) {
9 *{"$class\::$method"} = sub {
10 +shift->_top->$method(@_);
11 } unless defined &{"$class\::$method"};
12 }
13
14 bless(\%args, $class);
18 my $class = shift;
19 unless ( defined &{"${class}::call"} ) {
20 *{"${class}::call"} = sub { shift->_top->call(@_) };
21 }
22 unless ( defined &{"${class}::load"} ) {
23 *{"${class}::load"} = sub { shift->_top->load(@_) };
24 }
25 bless { @_ }, $class;
1526 }
1627
17 #line 46
28 #line 61
1829
1930 sub AUTOLOAD {
20 my $self = shift;
21 goto &{$self->_top->autoload};
31 local $@;
32 my $func = eval { shift->_top->autoload } or return;
33 goto &$func;
2234 }
2335
24 #line 57
36 #line 75
2537
26 sub _top { $_[0]->{_top} }
38 sub _top {
39 $_[0]->{_top};
40 }
2741
28 #line 68
42 #line 90
2943
3044 sub admin {
31 my $self = shift;
32 $self->_top->{admin} or Module::Install::Base::FakeAdmin->new;
45 $_[0]->_top->{admin}
46 or
47 Module::Install::Base::FakeAdmin->new;
3348 }
3449
50 #line 106
51
3552 sub is_admin {
36 my $self = shift;
37 $self->admin->VERSION;
53 ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin');
3854 }
3955
4056 sub DESTROY {}
4157
4258 package Module::Install::Base::FakeAdmin;
4359
44 my $Fake;
45 sub new { $Fake ||= bless(\@_, $_[0]) }
60 use vars qw{$VERSION};
61 BEGIN {
62 $VERSION = $Module::Install::Base::VERSION;
63 }
64
65 my $fake;
66
67 sub new {
68 $fake ||= bless(\@_, $_[0]);
69 }
70
4671 sub AUTOLOAD {}
72
4773 sub DESTROY {}
74
75 # Restore warning handler
76 BEGIN {
77 $SIG{__WARN__} = $SIG{__WARN__}->();
78 }
4879
4980 1;
5081
51 __END__
52
53 #line 112
82 #line 159
0 #line 1 "inc/Module/Install/Can.pm - /Library/Perl/5.8.1/Module/Install/Can.pm"
0 #line 1
11 package Module::Install::Can;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
3 $VERSION = '0.01';
42
53 use strict;
6 use Config ();
7 use File::Spec ();
8 use ExtUtils::MakeMaker ();
4 use Config ();
5 use File::Spec ();
6 use ExtUtils::MakeMaker ();
7 use Module::Install::Base ();
8
9 use vars qw{$VERSION @ISA $ISCORE};
10 BEGIN {
11 $VERSION = '1.00';
12 @ISA = 'Module::Install::Base';
13 $ISCORE = 1;
14 }
15
16 # check if we can load some module
17 ### Upgrade this to not have to load the module if possible
18 sub can_use {
19 my ($self, $mod, $ver) = @_;
20 $mod =~ s{::|\\}{/}g;
21 $mod .= '.pm' unless $mod =~ /\.pm$/i;
22
23 my $pkg = $mod;
24 $pkg =~ s{/}{::}g;
25 $pkg =~ s{\.pm$}{}i;
26
27 local $@;
28 eval { require $mod; $pkg->VERSION($ver || 0); 1 };
29 }
930
1031 # check if we can run some command
1132 sub can_run {
12 my ($self, $cmd) = @_;
33 my ($self, $cmd) = @_;
1334
14 my $_cmd = $cmd;
15 return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));
35 my $_cmd = $cmd;
36 return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));
1637
17 for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') {
18 my $abs = File::Spec->catfile($dir, $_[1]);
19 return $abs if (-x $abs or $abs = MM->maybe_command($abs));
20 }
38 for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') {
39 next if $dir eq '';
40 my $abs = File::Spec->catfile($dir, $_[1]);
41 return $abs if (-x $abs or $abs = MM->maybe_command($abs));
42 }
2143
22 return;
44 return;
2345 }
2446
47 # can we locate a (the) C compiler
2548 sub can_cc {
26 my $self = shift;
27 my @chunks = split(/ /, $Config::Config{cc}) or return;
49 my $self = shift;
50 my @chunks = split(/ /, $Config::Config{cc}) or return;
2851
29 # $Config{cc} may contain args; try to find out the program part
30 while (@chunks) {
31 return $self->can_run("@chunks") || (pop(@chunks), next);
32 }
52 # $Config{cc} may contain args; try to find out the program part
53 while (@chunks) {
54 return $self->can_run("@chunks") || (pop(@chunks), next);
55 }
3356
34 return;
57 return;
58 }
59
60 # Fix Cygwin bug on maybe_command();
61 if ( $^O eq 'cygwin' ) {
62 require ExtUtils::MM_Cygwin;
63 require ExtUtils::MM_Win32;
64 if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) {
65 *ExtUtils::MM_Cygwin::maybe_command = sub {
66 my ($self, $file) = @_;
67 if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) {
68 ExtUtils::MM_Win32->maybe_command($file);
69 } else {
70 ExtUtils::MM_Unix->maybe_command($file);
71 }
72 }
73 }
3574 }
3675
3776 1;
77
78 __END__
79
80 #line 156
0 #line 1 "inc/Module/Install/Fetch.pm - /Library/Perl/5.8.1/Module/Install/Fetch.pm"
0 #line 1
11 package Module::Install::Fetch;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
32
4 $VERSION = '0.01';
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.00';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
11 }
512
613 sub get_file {
714 my ($self, %args) = @_;
8 my ($scheme, $host, $path, $file) =
15 my ($scheme, $host, $path, $file) =
916 $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
1017
11 if ($scheme eq 'http' and !eval { require LWP::Simple; 1 }) {
18 if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) {
1219 $args{url} = $args{ftp_url}
1320 or (warn("LWP support unavailable!\n"), return);
14 ($scheme, $host, $path, $file) =
21 ($scheme, $host, $path, $file) =
1522 $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
1623 }
1724
5259 chdir $dir; return;
5360 }
5461
55 my @dialog = split(/\n/, << ".");
62 my @dialog = split(/\n/, <<"END_FTP");
5663 open $host
5764 user anonymous anonymous\@example.com
5865 cd $path
5966 binary
6067 get $file $file
6168 quit
62 .
69 END_FTP
6370 foreach (@dialog) { $fh->print("$_\n") }
6471 $fh->close;
6572 } }
0 #line 1 "inc/Module/Install/Include.pm - /Library/Perl/5.8.1/Module/Install/Include.pm"
0 #line 1
11 package Module::Install::Include;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
32
4 sub include { +shift->admin->include(@_) };
5 sub include_deps { +shift->admin->include_deps(@_) };
6 sub auto_include { +shift->admin->auto_include(@_) };
7 sub auto_include_deps { +shift->admin->auto_include_deps(@_) };
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.00';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
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 }
832
933 1;
0 #line 1 "inc/Module/Install/Makefile.pm - /Library/Perl/5.8.1/Module/Install/Makefile.pm"
0 #line 1
11 package Module::Install::Makefile;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
3
4 $VERSION = '0.01';
52
63 use strict 'vars';
7 use vars '$VERSION';
8
9 use ExtUtils::MakeMaker ();
4 use ExtUtils::MakeMaker ();
5 use Module::Install::Base ();
6 use Fcntl qw/:flock :seek/;
7
8 use vars qw{$VERSION @ISA $ISCORE};
9 BEGIN {
10 $VERSION = '1.00';
11 @ISA = 'Module::Install::Base';
12 $ISCORE = 1;
13 }
1014
1115 sub Makefile { $_[0] }
1216
13 sub prompt {
14 shift;
15 goto &ExtUtils::MakeMaker::prompt;
16 }
17 my %seen = ();
18
19 sub prompt {
20 shift;
21
22 # Infinite loop protection
23 my @c = caller();
24 if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
25 die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
26 }
27
28 # In automated testing or non-interactive session, always use defaults
29 if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) {
30 local $ENV{PERL_MM_USE_DEFAULT} = 1;
31 goto &ExtUtils::MakeMaker::prompt;
32 } else {
33 goto &ExtUtils::MakeMaker::prompt;
34 }
35 }
36
37 # Store a cleaned up version of the MakeMaker version,
38 # since we need to behave differently in a variety of
39 # ways based on the MM version.
40 my $makemaker = eval $ExtUtils::MakeMaker::VERSION;
41
42 # If we are passed a param, do a "newer than" comparison.
43 # Otherwise, just return the MakeMaker version.
44 sub makemaker {
45 ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0
46 }
47
48 # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified
49 # as we only need to know here whether the attribute is an array
50 # or a hash or something else (which may or may not be appendable).
51 my %makemaker_argtype = (
52 C => 'ARRAY',
53 CONFIG => 'ARRAY',
54 # CONFIGURE => 'CODE', # ignore
55 DIR => 'ARRAY',
56 DL_FUNCS => 'HASH',
57 DL_VARS => 'ARRAY',
58 EXCLUDE_EXT => 'ARRAY',
59 EXE_FILES => 'ARRAY',
60 FUNCLIST => 'ARRAY',
61 H => 'ARRAY',
62 IMPORTS => 'HASH',
63 INCLUDE_EXT => 'ARRAY',
64 LIBS => 'ARRAY', # ignore ''
65 MAN1PODS => 'HASH',
66 MAN3PODS => 'HASH',
67 META_ADD => 'HASH',
68 META_MERGE => 'HASH',
69 PL_FILES => 'HASH',
70 PM => 'HASH',
71 PMLIBDIRS => 'ARRAY',
72 PMLIBPARENTDIRS => 'ARRAY',
73 PREREQ_PM => 'HASH',
74 CONFIGURE_REQUIRES => 'HASH',
75 SKIP => 'ARRAY',
76 TYPEMAPS => 'ARRAY',
77 XS => 'HASH',
78 # VERSION => ['version',''], # ignore
79 # _KEEP_AFTER_FLUSH => '',
80
81 clean => 'HASH',
82 depend => 'HASH',
83 dist => 'HASH',
84 dynamic_lib=> 'HASH',
85 linkext => 'HASH',
86 macro => 'HASH',
87 postamble => 'HASH',
88 realclean => 'HASH',
89 test => 'HASH',
90 tool_autosplit => 'HASH',
91
92 # special cases where you can use makemaker_append
93 CCFLAGS => 'APPENDABLE',
94 DEFINE => 'APPENDABLE',
95 INC => 'APPENDABLE',
96 LDDLFLAGS => 'APPENDABLE',
97 LDFROM => 'APPENDABLE',
98 );
1799
18100 sub makemaker_args {
19 my $self = shift;
20 my $args = ($self->{makemaker_args} ||= {});
21 %$args = ( %$args, @_ ) if @_;
22 $args;
101 my ($self, %new_args) = @_;
102 my $args = ( $self->{makemaker_args} ||= {} );
103 foreach my $key (keys %new_args) {
104 if ($makemaker_argtype{$key}) {
105 if ($makemaker_argtype{$key} eq 'ARRAY') {
106 $args->{$key} = [] unless defined $args->{$key};
107 unless (ref $args->{$key} eq 'ARRAY') {
108 $args->{$key} = [$args->{$key}]
109 }
110 push @{$args->{$key}},
111 ref $new_args{$key} eq 'ARRAY'
112 ? @{$new_args{$key}}
113 : $new_args{$key};
114 }
115 elsif ($makemaker_argtype{$key} eq 'HASH') {
116 $args->{$key} = {} unless defined $args->{$key};
117 foreach my $skey (keys %{ $new_args{$key} }) {
118 $args->{$key}{$skey} = $new_args{$key}{$skey};
119 }
120 }
121 elsif ($makemaker_argtype{$key} eq 'APPENDABLE') {
122 $self->makemaker_append($key => $new_args{$key});
123 }
124 }
125 else {
126 if (defined $args->{$key}) {
127 warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n};
128 }
129 $args->{$key} = $new_args{$key};
130 }
131 }
132 return $args;
133 }
134
135 # For mm args that take multiple space-seperated args,
136 # append an argument to the current list.
137 sub makemaker_append {
138 my $self = shift;
139 my $name = shift;
140 my $args = $self->makemaker_args;
141 $args->{$name} = defined $args->{$name}
142 ? join( ' ', $args->{$name}, @_ )
143 : join( ' ', @_ );
144 }
145
146 sub build_subdirs {
147 my $self = shift;
148 my $subdirs = $self->makemaker_args->{DIR} ||= [];
149 for my $subdir (@_) {
150 push @$subdirs, $subdir;
151 }
23152 }
24153
25154 sub clean_files {
26 my $self = shift;
27 my $clean = $self->makemaker_args->{clean} ||= {};
28 %$clean = (
29 %$clean,
30 FILES => join(" ", grep length, $clean->{FILES}, @_),
155 my $self = shift;
156 my $clean = $self->makemaker_args->{clean} ||= {};
157 %$clean = (
158 %$clean,
159 FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_),
160 );
161 }
162
163 sub realclean_files {
164 my $self = shift;
165 my $realclean = $self->makemaker_args->{realclean} ||= {};
166 %$realclean = (
167 %$realclean,
168 FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_),
169 );
170 }
171
172 sub libs {
173 my $self = shift;
174 my $libs = ref $_[0] ? shift : [ shift ];
175 $self->makemaker_args( LIBS => $libs );
176 }
177
178 sub inc {
179 my $self = shift;
180 $self->makemaker_args( INC => shift );
181 }
182
183 sub _wanted_t {
184 }
185
186 sub tests_recursive {
187 my $self = shift;
188 my $dir = shift || 't';
189 unless ( -d $dir ) {
190 die "tests_recursive dir '$dir' does not exist";
191 }
192 my %tests = map { $_ => 1 } split / /, ($self->tests || '');
193 require File::Find;
194 File::Find::find(
195 sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 },
196 $dir
31197 );
32 }
33
34 sub libs {
35 my $self = shift;
36 my $libs = ref $_[0] ? shift : [shift];
37 $self->makemaker_args( LIBS => $libs );
38 }
39
40 sub inc {
41 my $self = shift;
42 $self->makemaker_args( INC => shift );
198 $self->tests( join ' ', sort keys %tests );
43199 }
44200
45201 sub write {
46 my $self = shift;
47 die "&Makefile->write() takes no arguments\n" if @_;
48
49 my $args = $self->makemaker_args;
50
51 $args->{DISTNAME} = $self->name;
52 $args->{NAME} = $self->module_name || $self->name || $self->determine_NAME($args);
53 $args->{VERSION} = $self->version || $self->determine_VERSION($args);
54 $args->{NAME} =~ s/-/::/g;
55
56 if ($] >= 5.005) {
57 $args->{ABSTRACT} = $self->abstract;
58 $args->{AUTHOR} = $self->author;
59 }
60 if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) {
61 $args->{NO_META} = 1;
62 }
63 if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 ) {
64 $args->{SIGN} = 1 if $self->sign;
65 }
66 delete $args->{SIGN} unless $self->is_admin;
67
68 # merge both kinds of requires into prereq_pm
69 my $prereq = ($args->{PREREQ_PM} ||= {});
70 %$prereq = ( %$prereq, map { @$_ } map { @$_ } grep $_,
71 ($self->build_requires, $self->requires) );
72
73 # merge both kinds of requires into prereq_pm
74 my $dir = ($args->{DIR} ||= []);
75 if ($self->bundles) {
76 push @$dir, map "$_->[1]", @{$self->bundles};
77 delete $prereq->{$_->[0]} for @{$self->bundles};
78 }
79
80 if (my $perl_version = $self->perl_version) {
81 eval "use $perl_version; 1"
82 or die "ERROR: perl: Version $] is installed, ".
83 "but we need version >= $perl_version";
84 }
85
86 my %args = map {($_ => $args->{$_})} grep {defined($args->{$_})} keys %$args;
87
88 if ($self->admin->preop) {
89 $args{dist} = $self->admin->preop;
90 }
91
92 ExtUtils::MakeMaker::WriteMakefile(%args);
93
94 $self->fix_up_makefile();
202 my $self = shift;
203 die "&Makefile->write() takes no arguments\n" if @_;
204
205 # Check the current Perl version
206 my $perl_version = $self->perl_version;
207 if ( $perl_version ) {
208 eval "use $perl_version; 1"
209 or die "ERROR: perl: Version $] is installed, "
210 . "but we need version >= $perl_version";
211 }
212
213 # Make sure we have a new enough MakeMaker
214 require ExtUtils::MakeMaker;
215
216 if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) {
217 # MakeMaker can complain about module versions that include
218 # an underscore, even though its own version may contain one!
219 # Hence the funny regexp to get rid of it. See RT #35800
220 # for details.
221 my $v = $ExtUtils::MakeMaker::VERSION =~ /^(\d+\.\d+)/;
222 $self->build_requires( 'ExtUtils::MakeMaker' => $v );
223 $self->configure_requires( 'ExtUtils::MakeMaker' => $v );
224 } else {
225 # Allow legacy-compatibility with 5.005 by depending on the
226 # most recent EU:MM that supported 5.005.
227 $self->build_requires( 'ExtUtils::MakeMaker' => 6.42 );
228 $self->configure_requires( 'ExtUtils::MakeMaker' => 6.42 );
229 }
230
231 # Generate the MakeMaker params
232 my $args = $self->makemaker_args;
233 $args->{DISTNAME} = $self->name;
234 $args->{NAME} = $self->module_name || $self->name;
235 $args->{NAME} =~ s/-/::/g;
236 $args->{VERSION} = $self->version or die <<'EOT';
237 ERROR: Can't determine distribution version. Please specify it
238 explicitly via 'version' in Makefile.PL, or set a valid $VERSION
239 in a module, and provide its file path via 'version_from' (or
240 'all_from' if you prefer) in Makefile.PL.
241 EOT
242
243 $DB::single = 1;
244 if ( $self->tests ) {
245 my @tests = split ' ', $self->tests;
246 my %seen;
247 $args->{test} = {
248 TESTS => (join ' ', grep {!$seen{$_}++} @tests),
249 };
250 } elsif ( $Module::Install::ExtraTests::use_extratests ) {
251 # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness.
252 # So, just ignore our xt tests here.
253 } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) {
254 $args->{test} = {
255 TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ),
256 };
257 }
258 if ( $] >= 5.005 ) {
259 $args->{ABSTRACT} = $self->abstract;
260 $args->{AUTHOR} = join ', ', @{$self->author || []};
261 }
262 if ( $self->makemaker(6.10) ) {
263 $args->{NO_META} = 1;
264 #$args->{NO_MYMETA} = 1;
265 }
266 if ( $self->makemaker(6.17) and $self->sign ) {
267 $args->{SIGN} = 1;
268 }
269 unless ( $self->is_admin ) {
270 delete $args->{SIGN};
271 }
272 if ( $self->makemaker(6.31) and $self->license ) {
273 $args->{LICENSE} = $self->license;
274 }
275
276 my $prereq = ($args->{PREREQ_PM} ||= {});
277 %$prereq = ( %$prereq,
278 map { @$_ } # flatten [module => version]
279 map { @$_ }
280 grep $_,
281 ($self->requires)
282 );
283
284 # Remove any reference to perl, PREREQ_PM doesn't support it
285 delete $args->{PREREQ_PM}->{perl};
286
287 # Merge both kinds of requires into BUILD_REQUIRES
288 my $build_prereq = ($args->{BUILD_REQUIRES} ||= {});
289 %$build_prereq = ( %$build_prereq,
290 map { @$_ } # flatten [module => version]
291 map { @$_ }
292 grep $_,
293 ($self->configure_requires, $self->build_requires)
294 );
295
296 # Remove any reference to perl, BUILD_REQUIRES doesn't support it
297 delete $args->{BUILD_REQUIRES}->{perl};
298
299 # Delete bundled dists from prereq_pm, add it to Makefile DIR
300 my $subdirs = ($args->{DIR} || []);
301 if ($self->bundles) {
302 my %processed;
303 foreach my $bundle (@{ $self->bundles }) {
304 my ($mod_name, $dist_dir) = @$bundle;
305 delete $prereq->{$mod_name};
306 $dist_dir = File::Basename::basename($dist_dir); # dir for building this module
307 if (not exists $processed{$dist_dir}) {
308 if (-d $dist_dir) {
309 # List as sub-directory to be processed by make
310 push @$subdirs, $dist_dir;
311 }
312 # Else do nothing: the module is already present on the system
313 $processed{$dist_dir} = undef;
314 }
315 }
316 }
317
318 unless ( $self->makemaker('6.55_03') ) {
319 %$prereq = (%$prereq,%$build_prereq);
320 delete $args->{BUILD_REQUIRES};
321 }
322
323 if ( my $perl_version = $self->perl_version ) {
324 eval "use $perl_version; 1"
325 or die "ERROR: perl: Version $] is installed, "
326 . "but we need version >= $perl_version";
327
328 if ( $self->makemaker(6.48) ) {
329 $args->{MIN_PERL_VERSION} = $perl_version;
330 }
331 }
332
333 if ($self->installdirs) {
334 warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS};
335 $args->{INSTALLDIRS} = $self->installdirs;
336 }
337
338 my %args = map {
339 ( $_ => $args->{$_} ) } grep {defined($args->{$_} )
340 } keys %$args;
341
342 my $user_preop = delete $args{dist}->{PREOP};
343 if ( my $preop = $self->admin->preop($user_preop) ) {
344 foreach my $key ( keys %$preop ) {
345 $args{dist}->{$key} = $preop->{$key};
346 }
347 }
348
349 my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
350 $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
95351 }
96352
97353 sub fix_up_makefile {
98 my $self = shift;
99 my $top_class = ref($self->_top) || '';
100 my $top_version = $self->_top->VERSION || '';
101
102 my $preamble = $self->preamble
103 ? "# Preamble by $top_class $top_version\n" . $self->preamble
104 : '';
105 my $postamble = "# Postamble by $top_class $top_version\n" .
106 ($self->postamble || '');
107
108 open MAKEFILE, '< Makefile' or die $!;
109 my $makefile = do { local $/; <MAKEFILE> };
110 close MAKEFILE;
111
112 $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
113 $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
114 $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
115
116 $makefile =~ s/^(FULLPERL = .*)/$1 -Iinc/m;
117 $makefile =~ s/^(PERL = .*)/$1 -Iinc/m;
118
119 open MAKEFILE, '> Makefile' or die $!;
120 print MAKEFILE "$preamble$makefile$postamble";
121 close MAKEFILE;
354 my $self = shift;
355 my $makefile_name = shift;
356 my $top_class = ref($self->_top) || '';
357 my $top_version = $self->_top->VERSION || '';
358
359 my $preamble = $self->preamble
360 ? "# Preamble by $top_class $top_version\n"
361 . $self->preamble
362 : '';
363 my $postamble = "# Postamble by $top_class $top_version\n"
364 . ($self->postamble || '');
365
366 local *MAKEFILE;
367 open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
368 eval { flock MAKEFILE, LOCK_EX };
369 my $makefile = do { local $/; <MAKEFILE> };
370
371 $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
372 $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
373 $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
374 $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
375 $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;
376
377 # Module::Install will never be used to build the Core Perl
378 # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
379 # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
380 $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
381 #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;
382
383 # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
384 $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g;
385
386 # XXX - This is currently unused; not sure if it breaks other MM-users
387 # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
388
389 seek MAKEFILE, 0, SEEK_SET;
390 truncate MAKEFILE, 0;
391 print MAKEFILE "$preamble$makefile$postamble" or die $!;
392 close MAKEFILE or die $!;
393
394 1;
122395 }
123396
124397 sub preamble {
125 my ($self, $text) = @_;
126 $self->{preamble} = $text . $self->{preamble} if defined $text;
127 $self->{preamble};
398 my ($self, $text) = @_;
399 $self->{preamble} = $text . $self->{preamble} if defined $text;
400 $self->{preamble};
128401 }
129402
130403 sub postamble {
131 my ($self, $text) = @_;
132
133 $self->{postamble} ||= $self->admin->postamble;
134 $self->{postamble} .= $text if defined $text;
135 $self->{postamble}
404 my ($self, $text) = @_;
405 $self->{postamble} ||= $self->admin->postamble;
406 $self->{postamble} .= $text if defined $text;
407 $self->{postamble}
136408 }
137409
138410 1;
139411
140412 __END__
141413
142 #line 273
414 #line 541
0 #line 1 "inc/Module/Install/Metadata.pm - /Library/Perl/5.8.1/Module/Install/Metadata.pm"
0 #line 1
11 package Module::Install::Metadata;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
3
4 $VERSION = '0.04';
52
63 use strict 'vars';
7 use vars qw($VERSION);
8
9 sub Meta { shift }
10
11 my @scalar_keys = qw(
12 name module_name version abstract author license
13 distribution_type sign perl_version
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.00';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
11 }
12
13 my @boolean_keys = qw{
14 sign
15 };
16
17 my @scalar_keys = qw{
18 name
19 module_name
20 abstract
21 version
22 distribution_type
23 tests
24 installdirs
25 };
26
27 my @tuple_keys = qw{
28 configure_requires
29 build_requires
30 requires
31 recommends
32 bundles
33 resources
34 };
35
36 my @resource_keys = qw{
37 homepage
38 bugtracker
39 repository
40 };
41
42 my @array_keys = qw{
43 keywords
44 author
45 };
46
47 *authors = \&author;
48
49 sub Meta { shift }
50 sub Meta_BooleanKeys { @boolean_keys }
51 sub Meta_ScalarKeys { @scalar_keys }
52 sub Meta_TupleKeys { @tuple_keys }
53 sub Meta_ResourceKeys { @resource_keys }
54 sub Meta_ArrayKeys { @array_keys }
55
56 foreach my $key ( @boolean_keys ) {
57 *$key = sub {
58 my $self = shift;
59 if ( defined wantarray and not @_ ) {
60 return $self->{values}->{$key};
61 }
62 $self->{values}->{$key} = ( @_ ? $_[0] : 1 );
63 return $self;
64 };
65 }
66
67 foreach my $key ( @scalar_keys ) {
68 *$key = sub {
69 my $self = shift;
70 return $self->{values}->{$key} if defined wantarray and !@_;
71 $self->{values}->{$key} = shift;
72 return $self;
73 };
74 }
75
76 foreach my $key ( @array_keys ) {
77 *$key = sub {
78 my $self = shift;
79 return $self->{values}->{$key} if defined wantarray and !@_;
80 $self->{values}->{$key} ||= [];
81 push @{$self->{values}->{$key}}, @_;
82 return $self;
83 };
84 }
85
86 foreach my $key ( @resource_keys ) {
87 *$key = sub {
88 my $self = shift;
89 unless ( @_ ) {
90 return () unless $self->{values}->{resources};
91 return map { $_->[1] }
92 grep { $_->[0] eq $key }
93 @{ $self->{values}->{resources} };
94 }
95 return $self->{values}->{resources}->{$key} unless @_;
96 my $uri = shift or die(
97 "Did not provide a value to $key()"
98 );
99 $self->resources( $key => $uri );
100 return 1;
101 };
102 }
103
104 foreach my $key ( grep { $_ ne "resources" } @tuple_keys) {
105 *$key = sub {
106 my $self = shift;
107 return $self->{values}->{$key} unless @_;
108 my @added;
109 while ( @_ ) {
110 my $module = shift or last;
111 my $version = shift || 0;
112 push @added, [ $module, $version ];
113 }
114 push @{ $self->{values}->{$key} }, @added;
115 return map {@$_} @added;
116 };
117 }
118
119 # Resource handling
120 my %lc_resource = map { $_ => 1 } qw{
121 homepage
122 license
123 bugtracker
124 repository
125 };
126
127 sub resources {
128 my $self = shift;
129 while ( @_ ) {
130 my $name = shift or last;
131 my $value = shift or next;
132 if ( $name eq lc $name and ! $lc_resource{$name} ) {
133 die("Unsupported reserved lowercase resource '$name'");
134 }
135 $self->{values}->{resources} ||= [];
136 push @{ $self->{values}->{resources} }, [ $name, $value ];
137 }
138 $self->{values}->{resources};
139 }
140
141 # Aliases for build_requires that will have alternative
142 # meanings in some future version of META.yml.
143 sub test_requires { shift->build_requires(@_) }
144 sub install_requires { shift->build_requires(@_) }
145
146 # Aliases for installdirs options
147 sub install_as_core { $_[0]->installdirs('perl') }
148 sub install_as_cpan { $_[0]->installdirs('site') }
149 sub install_as_site { $_[0]->installdirs('site') }
150 sub install_as_vendor { $_[0]->installdirs('vendor') }
151
152 sub dynamic_config {
153 my $self = shift;
154 unless ( @_ ) {
155 warn "You MUST provide an explicit true/false value to dynamic_config\n";
156 return $self;
157 }
158 $self->{values}->{dynamic_config} = $_[0] ? 1 : 0;
159 return 1;
160 }
161
162 sub perl_version {
163 my $self = shift;
164 return $self->{values}->{perl_version} unless @_;
165 my $version = shift or die(
166 "Did not provide a value to perl_version()"
167 );
168
169 # Normalize the version
170 $version = $self->_perl_version($version);
171
172 # We don't support the reall old versions
173 unless ( $version >= 5.005 ) {
174 die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n";
175 }
176
177 $self->{values}->{perl_version} = $version;
178 }
179
180 sub all_from {
181 my ( $self, $file ) = @_;
182
183 unless ( defined($file) ) {
184 my $name = $self->name or die(
185 "all_from called with no args without setting name() first"
186 );
187 $file = join('/', 'lib', split(/-/, $name)) . '.pm';
188 $file =~ s{.*/}{} unless -e $file;
189 unless ( -e $file ) {
190 die("all_from cannot find $file from $name");
191 }
192 }
193 unless ( -f $file ) {
194 die("The path '$file' does not exist, or is not a file");
195 }
196
197 $self->{values}{all_from} = $file;
198
199 # Some methods pull from POD instead of code.
200 # If there is a matching .pod, use that instead
201 my $pod = $file;
202 $pod =~ s/\.pm$/.pod/i;
203 $pod = $file unless -e $pod;
204
205 # Pull the different values
206 $self->name_from($file) unless $self->name;
207 $self->version_from($file) unless $self->version;
208 $self->perl_version_from($file) unless $self->perl_version;
209 $self->author_from($pod) unless @{$self->author || []};
210 $self->license_from($pod) unless $self->license;
211 $self->abstract_from($pod) unless $self->abstract;
212
213 return 1;
214 }
215
216 sub provides {
217 my $self = shift;
218 my $provides = ( $self->{values}->{provides} ||= {} );
219 %$provides = (%$provides, @_) if @_;
220 return $provides;
221 }
222
223 sub auto_provides {
224 my $self = shift;
225 return $self unless $self->is_admin;
226 unless (-e 'MANIFEST') {
227 warn "Cannot deduce auto_provides without a MANIFEST, skipping\n";
228 return $self;
229 }
230 # Avoid spurious warnings as we are not checking manifest here.
231 local $SIG{__WARN__} = sub {1};
232 require ExtUtils::Manifest;
233 local *ExtUtils::Manifest::manicheck = sub { return };
234
235 require Module::Build;
236 my $build = Module::Build->new(
237 dist_name => $self->name,
238 dist_version => $self->version,
239 license => $self->license,
240 );
241 $self->provides( %{ $build->find_dist_packages || {} } );
242 }
243
244 sub feature {
245 my $self = shift;
246 my $name = shift;
247 my $features = ( $self->{values}->{features} ||= [] );
248 my $mods;
249
250 if ( @_ == 1 and ref( $_[0] ) ) {
251 # The user used ->feature like ->features by passing in the second
252 # argument as a reference. Accomodate for that.
253 $mods = $_[0];
254 } else {
255 $mods = \@_;
256 }
257
258 my $count = 0;
259 push @$features, (
260 $name => [
261 map {
262 ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_
263 } @$mods
264 ]
265 );
266
267 return @$features;
268 }
269
270 sub features {
271 my $self = shift;
272 while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) {
273 $self->feature( $name, @$mods );
274 }
275 return $self->{values}->{features}
276 ? @{ $self->{values}->{features} }
277 : ();
278 }
279
280 sub no_index {
281 my $self = shift;
282 my $type = shift;
283 push @{ $self->{values}->{no_index}->{$type} }, @_ if $type;
284 return $self->{values}->{no_index};
285 }
286
287 sub read {
288 my $self = shift;
289 $self->include_deps( 'YAML::Tiny', 0 );
290
291 require YAML::Tiny;
292 my $data = YAML::Tiny::LoadFile('META.yml');
293
294 # Call methods explicitly in case user has already set some values.
295 while ( my ( $key, $value ) = each %$data ) {
296 next unless $self->can($key);
297 if ( ref $value eq 'HASH' ) {
298 while ( my ( $module, $version ) = each %$value ) {
299 $self->can($key)->($self, $module => $version );
300 }
301 } else {
302 $self->can($key)->($self, $value);
303 }
304 }
305 return $self;
306 }
307
308 sub write {
309 my $self = shift;
310 return $self unless $self->is_admin;
311 $self->admin->write_meta;
312 return $self;
313 }
314
315 sub version_from {
316 require ExtUtils::MM_Unix;
317 my ( $self, $file ) = @_;
318 $self->version( ExtUtils::MM_Unix->parse_version($file) );
319
320 # for version integrity check
321 $self->makemaker_args( VERSION_FROM => $file );
322 }
323
324 sub abstract_from {
325 require ExtUtils::MM_Unix;
326 my ( $self, $file ) = @_;
327 $self->abstract(
328 bless(
329 { DISTNAME => $self->name },
330 'ExtUtils::MM_Unix'
331 )->parse_abstract($file)
332 );
333 }
334
335 # Add both distribution and module name
336 sub name_from {
337 my ($self, $file) = @_;
338 if (
339 Module::Install::_read($file) =~ m/
340 ^ \s*
341 package \s*
342 ([\w:]+)
343 \s* ;
344 /ixms
345 ) {
346 my ($name, $module_name) = ($1, $1);
347 $name =~ s{::}{-}g;
348 $self->name($name);
349 unless ( $self->module_name ) {
350 $self->module_name($module_name);
351 }
352 } else {
353 die("Cannot determine name from $file\n");
354 }
355 }
356
357 sub _extract_perl_version {
358 if (
359 $_[0] =~ m/
360 ^\s*
361 (?:use|require) \s*
362 v?
363 ([\d_\.]+)
364 \s* ;
365 /ixms
366 ) {
367 my $perl_version = $1;
368 $perl_version =~ s{_}{}g;
369 return $perl_version;
370 } else {
371 return;
372 }
373 }
374
375 sub perl_version_from {
376 my $self = shift;
377 my $perl_version=_extract_perl_version(Module::Install::_read($_[0]));
378 if ($perl_version) {
379 $self->perl_version($perl_version);
380 } else {
381 warn "Cannot determine perl version info from $_[0]\n";
382 return;
383 }
384 }
385
386 sub author_from {
387 my $self = shift;
388 my $content = Module::Install::_read($_[0]);
389 if ($content =~ m/
390 =head \d \s+ (?:authors?)\b \s*
391 ([^\n]*)
392 |
393 =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s*
394 .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s*
395 ([^\n]*)
396 /ixms) {
397 my $author = $1 || $2;
398
399 # XXX: ugly but should work anyway...
400 if (eval "require Pod::Escapes; 1") {
401 # Pod::Escapes has a mapping table.
402 # It's in core of perl >= 5.9.3, and should be installed
403 # as one of the Pod::Simple's prereqs, which is a prereq
404 # of Pod::Text 3.x (see also below).
405 $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> }
406 {
407 defined $2
408 ? chr($2)
409 : defined $Pod::Escapes::Name2character_number{$1}
410 ? chr($Pod::Escapes::Name2character_number{$1})
411 : do {
412 warn "Unknown escape: E<$1>";
413 "E<$1>";
414 };
415 }gex;
416 }
417 elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) {
418 # Pod::Text < 3.0 has yet another mapping table,
419 # though the table name of 2.x and 1.x are different.
420 # (1.x is in core of Perl < 5.6, 2.x is in core of
421 # Perl < 5.9.3)
422 my $mapping = ($Pod::Text::VERSION < 2)
423 ? \%Pod::Text::HTML_Escapes
424 : \%Pod::Text::ESCAPES;
425 $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> }
426 {
427 defined $2
428 ? chr($2)
429 : defined $mapping->{$1}
430 ? $mapping->{$1}
431 : do {
432 warn "Unknown escape: E<$1>";
433 "E<$1>";
434 };
435 }gex;
436 }
437 else {
438 $author =~ s{E<lt>}{<}g;
439 $author =~ s{E<gt>}{>}g;
440 }
441 $self->author($author);
442 } else {
443 warn "Cannot determine author info from $_[0]\n";
444 }
445 }
446
447 #Stolen from M::B
448 my %license_urls = (
449 perl => 'http://dev.perl.org/licenses/',
450 apache => 'http://apache.org/licenses/LICENSE-2.0',
451 apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1',
452 artistic => 'http://opensource.org/licenses/artistic-license.php',
453 artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php',
454 lgpl => 'http://opensource.org/licenses/lgpl-license.php',
455 lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php',
456 lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html',
457 bsd => 'http://opensource.org/licenses/bsd-license.php',
458 gpl => 'http://opensource.org/licenses/gpl-license.php',
459 gpl2 => 'http://opensource.org/licenses/gpl-2.0.php',
460 gpl3 => 'http://opensource.org/licenses/gpl-3.0.html',
461 mit => 'http://opensource.org/licenses/mit-license.php',
462 mozilla => 'http://opensource.org/licenses/mozilla1.1.php',
463 open_source => undef,
464 unrestricted => undef,
465 restrictive => undef,
466 unknown => undef,
14467 );
15 my @tuple_keys = qw(build_requires requires recommends bundles);
16
17 foreach my $key (@scalar_keys) {
18 *$key = sub {
19 my $self = shift;
20 return $self->{'values'}{$key} unless @_;
21 $self->{'values'}{$key} = shift;
22 return $self;
23 };
24 }
25
26 foreach my $key (@tuple_keys) {
27 *$key = sub {
28 my $self = shift;
29 return $self->{'values'}{$key} unless @_;
30 my @rv;
31 while (@_) {
32 my $module = shift or last;
33 my $version = shift || 0;
34 if ($module eq 'perl') {
35 $version =~ s{^(\d+)\.(\d+)\.(\d+)}
36 {$1 + $2/1_000 + $3/1_000_000}e;
37 $self->perl_version($version);
38 next;
39 }
40 my $rv = [$module, $version];
41 push @{$self->{'values'}{$key}}, $rv;
42 push @rv, $rv;
43 }
44 return @rv;
45 };
46 }
47
48 sub features {
468
469 sub license {
470 my $self = shift;
471 return $self->{values}->{license} unless @_;
472 my $license = shift or die(
473 'Did not provide a value to license()'
474 );
475 $license = __extract_license($license) || lc $license;
476 $self->{values}->{license} = $license;
477
478 # Automatically fill in license URLs
479 if ( $license_urls{$license} ) {
480 $self->resources( license => $license_urls{$license} );
481 }
482
483 return 1;
484 }
485
486 sub _extract_license {
487 my $pod = shift;
488 my $matched;
489 return __extract_license(
490 ($matched) = $pod =~ m/
491 (=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?)
492 (=head \d.*|=cut.*|)\z
493 /xms
494 ) || __extract_license(
495 ($matched) = $pod =~ m/
496 (=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?)
497 (=head \d.*|=cut.*|)\z
498 /xms
499 );
500 }
501
502 sub __extract_license {
503 my $license_text = shift or return;
504 my @phrases = (
505 '(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1,
506 '(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1,
507 'Artistic and GPL' => 'perl', 1,
508 'GNU general public license' => 'gpl', 1,
509 'GNU public license' => 'gpl', 1,
510 'GNU lesser general public license' => 'lgpl', 1,
511 'GNU lesser public license' => 'lgpl', 1,
512 'GNU library general public license' => 'lgpl', 1,
513 'GNU library public license' => 'lgpl', 1,
514 'GNU Free Documentation license' => 'unrestricted', 1,
515 'GNU Affero General Public License' => 'open_source', 1,
516 '(?:Free)?BSD license' => 'bsd', 1,
517 'Artistic license' => 'artistic', 1,
518 'Apache (?:Software )?license' => 'apache', 1,
519 'GPL' => 'gpl', 1,
520 'LGPL' => 'lgpl', 1,
521 'BSD' => 'bsd', 1,
522 'Artistic' => 'artistic', 1,
523 'MIT' => 'mit', 1,
524 'Mozilla Public License' => 'mozilla', 1,
525 'Q Public License' => 'open_source', 1,
526 'OpenSSL License' => 'unrestricted', 1,
527 'SSLeay License' => 'unrestricted', 1,
528 'zlib License' => 'open_source', 1,
529 'proprietary' => 'proprietary', 0,
530 );
531 while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
532 $pattern =~ s#\s+#\\s+#gs;
533 if ( $license_text =~ /\b$pattern\b/i ) {
534 return $license;
535 }
536 }
537 return '';
538 }
539
540 sub license_from {
541 my $self = shift;
542 if (my $license=_extract_license(Module::Install::_read($_[0]))) {
543 $self->license($license);
544 } else {
545 warn "Cannot determine license info from $_[0]\n";
546 return 'unknown';
547 }
548 }
549
550 sub _extract_bugtracker {
551 my @links = $_[0] =~ m#L<(
552 \Qhttp://rt.cpan.org/\E[^>]+|
553 \Qhttp://github.com/\E[\w_]+/[\w_]+/issues|
554 \Qhttp://code.google.com/p/\E[\w_\-]+/issues/list
555 )>#gx;
556 my %links;
557 @links{@links}=();
558 @links=keys %links;
559 return @links;
560 }
561
562 sub bugtracker_from {
563 my $self = shift;
564 my $content = Module::Install::_read($_[0]);
565 my @links = _extract_bugtracker($content);
566 unless ( @links ) {
567 warn "Cannot determine bugtracker info from $_[0]\n";
568 return 0;
569 }
570 if ( @links > 1 ) {
571 warn "Found more than one bugtracker link in $_[0]\n";
572 return 0;
573 }
574
575 # Set the bugtracker
576 bugtracker( $links[0] );
577 return 1;
578 }
579
580 sub requires_from {
581 my $self = shift;
582 my $content = Module::Install::_readperl($_[0]);
583 my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg;
584 while ( @requires ) {
585 my $module = shift @requires;
586 my $version = shift @requires;
587 $self->requires( $module => $version );
588 }
589 }
590
591 sub test_requires_from {
592 my $self = shift;
593 my $content = Module::Install::_readperl($_[0]);
594 my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg;
595 while ( @requires ) {
596 my $module = shift @requires;
597 my $version = shift @requires;
598 $self->test_requires( $module => $version );
599 }
600 }
601
602 # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to
603 # numbers (eg, 5.006001 or 5.008009).
604 # Also, convert double-part versions (eg, 5.8)
605 sub _perl_version {
606 my $v = $_[-1];
607 $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e;
608 $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e;
609 $v =~ s/(\.\d\d\d)000$/$1/;
610 $v =~ s/_.+$//;
611 if ( ref($v) ) {
612 # Numify
613 $v = $v + 0;
614 }
615 return $v;
616 }
617
618 sub add_metadata {
49619 my $self = shift;
50 while (my ($name, $mods) = splice(@_, 0, 2)) {
51 my $count = 0;
52 push @{$self->{'values'}{'features'}}, ($name => [
53 map { (++$count % 2 and ref($_) and ($count += $#$_)) ? @$_ : $_ } @$mods
54 ] );
620 my %hash = @_;
621 for my $key (keys %hash) {
622 warn "add_metadata: $key is not prefixed with 'x_'.\n" .
623 "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/;
624 $self->{values}->{$key} = $hash{$key};
55625 }
56 return @{$self->{'values'}{'features'}};
57 }
58
59 sub no_index {
60 my $self = shift;
61 my $type = shift;
62 push @{$self->{'values'}{'no_index'}{$type}}, @_ if $type;
63 return $self->{'values'}{'no_index'};
64 }
65
66 sub _dump {
67 my $self = shift;
68 my $package = ref($self->_top);
69 my $version = $self->_top->VERSION;
70 my %values = %{$self->{'values'}};
71
72 delete $values{sign};
73 if (my $perl_version = delete $values{perl_version}) {
74 # Always canonical to three-dot version
75 $perl_version =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2), int($3))}e
76 if $perl_version >= 5.006;
77 $values{requires} = [
78 [perl => $perl_version],
79 @{$values{requires}||[]},
80 ];
81 }
82
83 warn "No license specified, setting license = 'unknown'\n"
84 unless $values{license};
85
86 $values{license} ||= 'unknown';
87 $values{distribution_type} ||= 'module';
88 $values{name} ||= do {
89 my $name = $values{module_name};
90 $name =~ s/::/-/g;
91 $name;
92 } if $values{module_name};
93
94 if ($values{name} =~ /::/) {
95 my $name = $values{name};
96 $name =~ s/::/-/g;
97 die "Error in name(): '$values{name}' should be '$name'!\n";
98 }
99
100 my $dump = '';
101 foreach my $key (@scalar_keys) {
102 $dump .= "$key: $values{$key}\n" if exists $values{$key};
103 }
104 foreach my $key (@tuple_keys) {
105 next unless exists $values{$key};
106 $dump .= "$key:\n";
107 foreach (@{$values{$key}}) {
108 $dump .= " $_->[0]: $_->[1]\n";
109 }
110 }
111
112 if (my $no_index = $values{no_index}) {
113 push @{$no_index->{'directory'}}, 'inc';
114 require YAML;
115 local $YAML::UseHeader = 0;
116 $dump .= YAML::Dump({ no_index => $no_index});
117 }
118 else {
119 $dump .= << "META";
120 no_index:
121 directory:
122 - inc
123 META
124 }
125
126 $dump .= "generated_by: $package version $version\n";
127 return $dump;
128 }
129
130 sub read {
131 my $self = shift;
132 $self->include_deps( 'YAML', 0 );
133 require YAML;
134 my $data = YAML::LoadFile( 'META.yml' );
135 # Call methods explicitly in case user has already set some values.
136 while ( my ($key, $value) = each %$data ) {
137 next unless $self->can( $key );
138 if (ref $value eq 'HASH') {
139 while (my ($module, $version) = each %$value) {
140 $self->$key( $module => $version );
141 }
142 }
143 else {
144 $self->$key( $value );
145 }
146 }
147 return $self;
148 }
149
150 sub write {
151 my $self = shift;
152 return $self unless $self->is_admin;
153
154 META_NOT_OURS: {
155 local *FH;
156 if (open FH, "META.yml") {
157 while (<FH>) {
158 last META_NOT_OURS if /^generated_by: Module::Install\b/;
159 }
160 return $self if -s FH;
161 }
162 }
163
164 warn "Writing META.yml\n";
165 open META, "> META.yml" or warn "Cannot write to META.yml: $!";
166 print META $self->_dump;
167 close META;
168 return $self;
169 }
170
171 sub version_from {
172 my ($self, $version_from) = @_;
173 require ExtUtils::MM_Unix;
174 $self->version(ExtUtils::MM_Unix->parse_version($version_from));
175 }
176
177 sub abstract_from {
178 my ($self, $abstract_from) = @_;
179 require ExtUtils::MM_Unix;
180 $self->abstract(
181 bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix')
182 ->parse_abstract($abstract_from)
183 );
626 }
627
628
629 ######################################################################
630 # MYMETA Support
631
632 sub WriteMyMeta {
633 die "WriteMyMeta has been deprecated";
634 }
635
636 sub write_mymeta_yaml {
637 my $self = shift;
638
639 # We need YAML::Tiny to write the MYMETA.yml file
640 unless ( eval { require YAML::Tiny; 1; } ) {
641 return 1;
642 }
643
644 # Generate the data
645 my $meta = $self->_write_mymeta_data or return 1;
646
647 # Save as the MYMETA.yml file
648 print "Writing MYMETA.yml\n";
649 YAML::Tiny::DumpFile('MYMETA.yml', $meta);
650 }
651
652 sub write_mymeta_json {
653 my $self = shift;
654
655 # We need JSON to write the MYMETA.json file
656 unless ( eval { require JSON; 1; } ) {
657 return 1;
658 }
659
660 # Generate the data
661 my $meta = $self->_write_mymeta_data or return 1;
662
663 # Save as the MYMETA.yml file
664 print "Writing MYMETA.json\n";
665 Module::Install::_write(
666 'MYMETA.json',
667 JSON->new->pretty(1)->canonical->encode($meta),
668 );
669 }
670
671 sub _write_mymeta_data {
672 my $self = shift;
673
674 # If there's no existing META.yml there is nothing we can do
675 return undef unless -f 'META.yml';
676
677 # We need Parse::CPAN::Meta to load the file
678 unless ( eval { require Parse::CPAN::Meta; 1; } ) {
679 return undef;
680 }
681
682 # Merge the perl version into the dependencies
683 my $val = $self->Meta->{values};
684 my $perl = delete $val->{perl_version};
685 if ( $perl ) {
686 $val->{requires} ||= [];
687 my $requires = $val->{requires};
688
689 # Canonize to three-dot version after Perl 5.6
690 if ( $perl >= 5.006 ) {
691 $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e
692 }
693 unshift @$requires, [ perl => $perl ];
694 }
695
696 # Load the advisory META.yml file
697 my @yaml = Parse::CPAN::Meta::LoadFile('META.yml');
698 my $meta = $yaml[0];
699
700 # Overwrite the non-configure dependency hashs
701 delete $meta->{requires};
702 delete $meta->{build_requires};
703 delete $meta->{recommends};
704 if ( exists $val->{requires} ) {
705 $meta->{requires} = { map { @$_ } @{ $val->{requires} } };
706 }
707 if ( exists $val->{build_requires} ) {
708 $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } };
709 }
710
711 return $meta;
184712 }
185713
186714 1;
0 #line 1
1 package Module::Install::ReadmeFromPod;
2
3 use strict;
4 use warnings;
5 use base qw(Module::Install::Base);
6 use vars qw($VERSION);
7
8 $VERSION = '0.10';
9
10 sub readme_from {
11 my $self = shift;
12 return unless $Module::Install::AUTHOR;
13 my $file = shift || return;
14 my $clean = shift;
15 require Pod::Text;
16 my $parser = Pod::Text->new();
17 open README, '> README' or die "$!\n";
18 $parser->output_fh( *README );
19 $parser->parse_file( $file );
20 return 1 unless $clean;
21 $self->postamble(<<"END");
22 distclean :: license_clean
23
24 license_clean:
25 \t\$(RM_F) README
26 END
27 return 1;
28 }
29
30 'Readme!';
31
32 __END__
33
34 #line 94
35
0 #line 1
1 package Module::Install::Repository;
2
3 use strict;
4 use 5.005;
5 use vars qw($VERSION);
6 $VERSION = '0.06';
7
8 use base qw(Module::Install::Base);
9
10 sub _execute {
11 my ($command) = @_;
12 `$command`;
13 }
14
15 sub auto_set_repository {
16 my $self = shift;
17
18 return unless $Module::Install::AUTHOR;
19
20 my $repo = _find_repo(\&_execute);
21 if ($repo) {
22 $self->repository($repo);
23 } else {
24 warn "Cannot determine repository URL\n";
25 }
26 }
27
28 sub _find_repo {
29 my ($execute) = @_;
30
31 if (-e ".git") {
32 # TODO support remote besides 'origin'?
33 if ($execute->('git remote show -n origin') =~ /URL: (.*)$/m) {
34 # XXX Make it public clone URL, but this only works with github
35 my $git_url = $1;
36 $git_url =~ s![\w\-]+\@([^:]+):!git://$1/!;
37 return $git_url;
38 } elsif ($execute->('git svn info') =~ /URL: (.*)$/m) {
39 return $1;
40 }
41 } elsif (-e ".svn") {
42 if (`svn info` =~ /URL: (.*)$/m) {
43 return $1;
44 }
45 } elsif (-e "_darcs") {
46 # defaultrepo is better, but that is more likely to be ssh, not http
47 if (my $query_repo = `darcs query repo`) {
48 if ($query_repo =~ m!Default Remote: (http://.+)!) {
49 return $1;
50 }
51 }
52
53 open my $handle, '<', '_darcs/prefs/repos' or return;
54 while (<$handle>) {
55 chomp;
56 return $_ if m!^http://!;
57 }
58 } elsif (-e ".hg") {
59 if ($execute->('hg paths') =~ /default = (.*)$/m) {
60 my $mercurial_url = $1;
61 $mercurial_url =~ s!^ssh://hg\@(bitbucket\.org/)!https://$1!;
62 return $mercurial_url;
63 }
64 } elsif (-e "$ENV{HOME}/.svk") {
65 # Is there an explicit way to check if it's an svk checkout?
66 my $svk_info = `svk info` or return;
67 SVK_INFO: {
68 if ($svk_info =~ /Mirrored From: (.*), Rev\./) {
69 return $1;
70 }
71
72 if ($svk_info =~ m!Merged From: (/mirror/.*), Rev\.!) {
73 $svk_info = `svk info /$1` or return;
74 redo SVK_INFO;
75 }
76 }
77
78 return;
79 }
80 }
81
82 1;
83 __END__
84
85 =encoding utf-8
86
87 #line 128
0 #line 1
1 package Module::Install::TestBase;
2 use strict;
3 use warnings;
4
5 use Module::Install::Base;
6
7 use vars qw($VERSION @ISA);
8 BEGIN {
9 $VERSION = '0.11';
10 @ISA = 'Module::Install::Base';
11 }
12
13 sub use_test_base {
14 my $self = shift;
15 $self->include('Test::Base');
16 $self->include('Test::Base::Filter');
17 $self->include('Spiffy');
18 $self->include('Test::More');
19 $self->include('Test::Builder');
20 $self->include('Test::Builder::Module');
21 $self->requires('Filter::Util::Call');
22 }
23
24 1;
25
26 =encoding utf8
27
28 #line 70
0 #line 1 "inc/Module/Install/Win32.pm - /Library/Perl/5.8.1/Module/Install/Win32.pm"
0 #line 1
11 package Module::Install::Win32;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
3
4 $VERSION = '0.02';
52
63 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.00';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
11 }
712
813 # determine if the user needs nmake, and download it if needed
914 sub check_nmake {
10 my $self = shift;
11 $self->load('can_run');
12 $self->load('get_file');
15 my $self = shift;
16 $self->load('can_run');
17 $self->load('get_file');
1318
14 require Config;
15 return unless (
16 $Config::Config{make} and
17 $Config::Config{make} =~ /^nmake\b/i and
18 $^O eq 'MSWin32' and
19 !$self->can_run('nmake')
20 );
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 );
2126
22 print "The required 'nmake' executable not found, fetching it...\n";
27 print "The required 'nmake' executable not found, fetching it...\n";
2328
24 require File::Basename;
25 my $rv = $self->get_file(
26 url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe',
27 ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe',
28 local_dir => File::Basename::dirname($^X),
29 size => 51928,
30 run => 'Nmake15.exe /o > nul',
31 check_for => 'Nmake.exe',
32 remove => 1,
33 );
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 );
3439
35 if (!$rv) {
36 die << '.';
40 die <<'END_MESSAGE' unless $rv;
3741
3842 -------------------------------------------------------------------------------
3943
5256 You may then resume the installation process described in README.
5357
5458 -------------------------------------------------------------------------------
55 .
56 }
59 END_MESSAGE
60
5761 }
5862
5963 1;
60
61 __END__
62
0 #line 1 "inc/Module/Install/WriteAll.pm - /Library/Perl/5.8.1/Module/Install/WriteAll.pm"
0 #line 1
11 package Module::Install::WriteAll;
2 use Module::Install::Base; @ISA = qw(Module::Install::Base);
2
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.00';
9 @ISA = qw{Module::Install::Base};
10 $ISCORE = 1;
11 }
312
413 sub WriteAll {
5 my $self = shift;
6 my %args = (
7 meta => 1,
8 sign => 0,
9 inline => 0,
10 check_nmake => 1,
11 @_
12 );
14 my $self = shift;
15 my %args = (
16 meta => 1,
17 sign => 0,
18 inline => 0,
19 check_nmake => 1,
20 @_,
21 );
1322
14 $self->sign(1) if $args{sign};
15 $self->Meta->write if $args{meta};
16 $self->admin->WriteAll(%args) if $self->is_admin;
23 $self->sign(1) if $args{sign};
24 $self->admin->WriteAll(%args) if $self->is_admin;
1725
18 if ($0 =~ /Build.PL$/i) {
19 $self->Build->write;
20 }
21 else {
2226 $self->check_nmake if $args{check_nmake};
23 $self->makemaker_args( PL_FILES => {} )
24 unless $self->makemaker_args->{'PL_FILES'};
27 unless ( $self->makemaker_args->{PL_FILES} ) {
28 # XXX: This still may be a bit over-defensive...
29 unless ($self->makemaker(6.25)) {
30 $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL';
31 }
32 }
2533
26 if ($args{inline}) {
27 $self->Inline->write;
28 }
29 else {
30 $self->Makefile->write;
31 }
32 }
34 # Until ExtUtils::MakeMaker support MYMETA.yml, make sure
35 # we clean it up properly ourself.
36 $self->realclean_files('MYMETA.yml');
37
38 if ( $args{inline} ) {
39 $self->Inline->write;
40 } else {
41 $self->Makefile->write;
42 }
43
44 # The Makefile write process adds a couple of dependencies,
45 # so write the META.yml files after the Makefile.
46 if ( $args{meta} ) {
47 $self->Meta->write;
48 }
49
50 # Experimental support for MYMETA
51 if ( $ENV{X_MYMETA} ) {
52 if ( $ENV{X_MYMETA} eq 'JSON' ) {
53 $self->Meta->write_mymeta_json;
54 } else {
55 $self->Meta->write_mymeta_yaml;
56 }
57 }
58
59 return 1;
3360 }
3461
3562 1;
0 #line 1 "inc/Module/Install.pm - /Library/Perl/5.8.1/Module/Install.pm"
0 #line 1
11 package Module::Install;
2 $VERSION = '0.36';
3
4 die << "." unless $INC{join('/', inc => split(/::/, __PACKAGE__)).'.pm'};
5 Please invoke ${\__PACKAGE__} with:
6
7 use inc::${\__PACKAGE__};
8
9 not:
10
11 use ${\__PACKAGE__};
12
13 .
14
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.005;
1520 use strict 'vars';
16 use Cwd ();
21 use Cwd ();
1722 use File::Find ();
1823 use File::Path ();
1924
20 @inc::Module::Install::ISA = 'Module::Install';
21 *inc::Module::Install::VERSION = *VERSION;
22
23 #line 129
25 use vars qw{$VERSION $MAIN};
26 BEGIN {
27 # All Module::Install core packages now require synchronised versions.
28 # This will be used to ensure we don't accidentally load old or
29 # different versions of modules.
30 # This is not enforced yet, but will be some time in the next few
31 # releases once we can make sure it won't clash with custom
32 # Module::Install extensions.
33 $VERSION = '1.00';
34
35 # Storage for the pseudo-singleton
36 $MAIN = undef;
37
38 *inc::Module::Install::VERSION = *VERSION;
39 @inc::Module::Install::ISA = __PACKAGE__;
40
41 }
2442
2543 sub import {
26 my $class = shift;
27 my $self = $class->new(@_);
28
29 if (not -f $self->{file}) {
30 require "$self->{path}/$self->{dispatch}.pm";
31 File::Path::mkpath("$self->{prefix}/$self->{author}");
32 $self->{admin} =
33 "$self->{name}::$self->{dispatch}"->new(_top => $self);
34 $self->{admin}->init;
35 @_ = ($class, _self => $self);
36 goto &{"$self->{name}::import"};
37 }
38
39 *{caller(0) . "::AUTOLOAD"} = $self->autoload;
40
41 # Unregister loader and worker packages so subdirs can use them again
42 delete $INC{"$self->{file}"};
43 delete $INC{"$self->{path}.pm"};
44 }
45
46 #line 156
44 my $class = shift;
45 my $self = $class->new(@_);
46 my $who = $self->_caller;
47
48 #-------------------------------------------------------------
49 # all of the following checks should be included in import(),
50 # to allow "eval 'require Module::Install; 1' to test
51 # installation of Module::Install. (RT #51267)
52 #-------------------------------------------------------------
53
54 # Whether or not inc::Module::Install is actually loaded, the
55 # $INC{inc/Module/Install.pm} is what will still get set as long as
56 # the caller loaded module this in the documented manner.
57 # If not set, the caller may NOT have loaded the bundled version, and thus
58 # they may not have a MI version that works with the Makefile.PL. This would
59 # result in false errors or unexpected behaviour. And we don't want that.
60 my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
61 unless ( $INC{$file} ) { die <<"END_DIE" }
62
63 Please invoke ${\__PACKAGE__} with:
64
65 use inc::${\__PACKAGE__};
66
67 not:
68
69 use ${\__PACKAGE__};
70
71 END_DIE
72
73 # This reportedly fixes a rare Win32 UTC file time issue, but
74 # as this is a non-cross-platform XS module not in the core,
75 # we shouldn't really depend on it. See RT #24194 for detail.
76 # (Also, this module only supports Perl 5.6 and above).
77 eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006;
78
79 # If the script that is loading Module::Install is from the future,
80 # then make will detect this and cause it to re-run over and over
81 # again. This is bad. Rather than taking action to touch it (which
82 # is unreliable on some platforms and requires write permissions)
83 # for now we should catch this and refuse to run.
84 if ( -f $0 ) {
85 my $s = (stat($0))[9];
86
87 # If the modification time is only slightly in the future,
88 # sleep briefly to remove the problem.
89 my $a = $s - time;
90 if ( $a > 0 and $a < 5 ) { sleep 5 }
91
92 # Too far in the future, throw an error.
93 my $t = time;
94 if ( $s > $t ) { die <<"END_DIE" }
95
96 Your installer $0 has a modification time in the future ($s > $t).
97
98 This is known to create infinite loops in make.
99
100 Please correct this, then run $0 again.
101
102 END_DIE
103 }
104
105
106 # Build.PL was formerly supported, but no longer is due to excessive
107 # difficulty in implementing every single feature twice.
108 if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" }
109
110 Module::Install no longer supports Build.PL.
111
112 It was impossible to maintain duel backends, and has been deprecated.
113
114 Please remove all Build.PL files and only use the Makefile.PL installer.
115
116 END_DIE
117
118 #-------------------------------------------------------------
119
120 # To save some more typing in Module::Install installers, every...
121 # use inc::Module::Install
122 # ...also acts as an implicit use strict.
123 $^H |= strict::bits(qw(refs subs vars));
124
125 #-------------------------------------------------------------
126
127 unless ( -f $self->{file} ) {
128 foreach my $key (keys %INC) {
129 delete $INC{$key} if $key =~ /Module\/Install/;
130 }
131
132 local $^W;
133 require "$self->{path}/$self->{dispatch}.pm";
134 File::Path::mkpath("$self->{prefix}/$self->{author}");
135 $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
136 $self->{admin}->init;
137 @_ = ($class, _self => $self);
138 goto &{"$self->{name}::import"};
139 }
140
141 local $^W;
142 *{"${who}::AUTOLOAD"} = $self->autoload;
143 $self->preload;
144
145 # Unregister loader and worker packages so subdirs can use them again
146 delete $INC{'inc/Module/Install.pm'};
147 delete $INC{'Module/Install.pm'};
148
149 # Save to the singleton
150 $MAIN = $self;
151
152 return 1;
153 }
47154
48155 sub autoload {
49 my $self = shift;
50 my $caller = caller;
51
52 my $cwd = Cwd::cwd();
53 my $sym = "$caller\::AUTOLOAD";
54
55 $sym->{$cwd} = sub {
56 my $pwd = Cwd::cwd();
57 if (my $code = $sym->{$pwd}) {
58 goto &$code unless $cwd eq $pwd; # delegate back to parent dirs
59 }
60 $$sym =~ /([^:]+)$/ or die "Cannot autoload $caller";
61 unshift @_, ($self, $1);
62 goto &{$self->can('call')} unless uc($1) eq $1;
63 };
64 }
65
66 #line 181
156 my $self = shift;
157 my $who = $self->_caller;
158 my $cwd = Cwd::cwd();
159 my $sym = "${who}::AUTOLOAD";
160 $sym->{$cwd} = sub {
161 my $pwd = Cwd::cwd();
162 if ( my $code = $sym->{$pwd} ) {
163 # Delegate back to parent dirs
164 goto &$code unless $cwd eq $pwd;
165 }
166 unless ($$sym =~ s/([^:]+)$//) {
167 # XXX: it looks like we can't retrieve the missing function
168 # via $$sym (usually $main::AUTOLOAD) in this case.
169 # I'm still wondering if we should slurp Makefile.PL to
170 # get some context or not ...
171 my ($package, $file, $line) = caller;
172 die <<"EOT";
173 Unknown function is found at $file line $line.
174 Execution of $file aborted due to runtime errors.
175
176 If you're a contributor to a project, you may need to install
177 some Module::Install extensions from CPAN (or other repository).
178 If you're a user of a module, please contact the author.
179 EOT
180 }
181 my $method = $1;
182 if ( uc($method) eq $method ) {
183 # Do nothing
184 return;
185 } elsif ( $method =~ /^_/ and $self->can($method) ) {
186 # Dispatch to the root M:I class
187 return $self->$method(@_);
188 }
189
190 # Dispatch to the appropriate plugin
191 unshift @_, ( $self, $1 );
192 goto &{$self->can('call')};
193 };
194 }
195
196 sub preload {
197 my $self = shift;
198 unless ( $self->{extensions} ) {
199 $self->load_extensions(
200 "$self->{prefix}/$self->{path}", $self
201 );
202 }
203
204 my @exts = @{$self->{extensions}};
205 unless ( @exts ) {
206 @exts = $self->{admin}->load_all_extensions;
207 }
208
209 my %seen;
210 foreach my $obj ( @exts ) {
211 while (my ($method, $glob) = each %{ref($obj) . '::'}) {
212 next unless $obj->can($method);
213 next if $method =~ /^_/;
214 next if $method eq uc($method);
215 $seen{$method}++;
216 }
217 }
218
219 my $who = $self->_caller;
220 foreach my $name ( sort keys %seen ) {
221 local $^W;
222 *{"${who}::$name"} = sub {
223 ${"${who}::AUTOLOAD"} = "${who}::$name";
224 goto &{"${who}::AUTOLOAD"};
225 };
226 }
227 }
67228
68229 sub new {
69 my ($class, %args) = @_;
70
71 return $args{_self} if $args{_self};
72
73 $args{dispatch} ||= 'Admin';
74 $args{prefix} ||= 'inc';
75 $args{author} ||= '.author';
76 $args{bundle} ||= 'inc/BUNDLES';
77
78 $class =~ s/^\Q$args{prefix}\E:://;
79 $args{name} ||= $class;
80 $args{version} ||= $class->VERSION;
81
82 unless ($args{path}) {
83 $args{path} = $args{name};
84 $args{path} =~ s!::!/!g;
85 }
86 $args{file} ||= "$args{prefix}/$args{path}.pm";
87
88 bless(\%args, $class);
89 }
90
91 #line 210
230 my ($class, %args) = @_;
231
232 delete $INC{'FindBin.pm'};
233 {
234 # to suppress the redefine warning
235 local $SIG{__WARN__} = sub {};
236 require FindBin;
237 }
238
239 # ignore the prefix on extension modules built from top level.
240 my $base_path = Cwd::abs_path($FindBin::Bin);
241 unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
242 delete $args{prefix};
243 }
244 return $args{_self} if $args{_self};
245
246 $args{dispatch} ||= 'Admin';
247 $args{prefix} ||= 'inc';
248 $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author');
249 $args{bundle} ||= 'inc/BUNDLES';
250 $args{base} ||= $base_path;
251 $class =~ s/^\Q$args{prefix}\E:://;
252 $args{name} ||= $class;
253 $args{version} ||= $class->VERSION;
254 unless ( $args{path} ) {
255 $args{path} = $args{name};
256 $args{path} =~ s!::!/!g;
257 }
258 $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm";
259 $args{wrote} = 0;
260
261 bless( \%args, $class );
262 }
92263
93264 sub call {
94 my $self = shift;
95 my $method = shift;
96 my $obj = $self->load($method) or return;
97
98 unshift @_, $obj;
99 goto &{$obj->can($method)};
100 }
101
102 #line 225
265 my ($self, $method) = @_;
266 my $obj = $self->load($method) or return;
267 splice(@_, 0, 2, $obj);
268 goto &{$obj->can($method)};
269 }
103270
104271 sub load {
105 my ($self, $method) = @_;
106
107 $self->load_extensions(
108 "$self->{prefix}/$self->{path}", $self
109 ) unless $self->{extensions};
110
111 foreach my $obj (@{$self->{extensions}}) {
112 return $obj if $obj->can($method);
113 }
114
115 my $admin = $self->{admin} or die << "END";
272 my ($self, $method) = @_;
273
274 $self->load_extensions(
275 "$self->{prefix}/$self->{path}", $self
276 ) unless $self->{extensions};
277
278 foreach my $obj (@{$self->{extensions}}) {
279 return $obj if $obj->can($method);
280 }
281
282 my $admin = $self->{admin} or die <<"END_DIE";
116283 The '$method' method does not exist in the '$self->{prefix}' path!
117284 Please remove the '$self->{prefix}' directory and run $0 again to load it.
118 END
119
120 my $obj = $admin->load($method, 1);
121 push @{$self->{extensions}}, $obj;
122
123 $obj;
124 }
125
126 #line 255
285 END_DIE
286
287 my $obj = $admin->load($method, 1);
288 push @{$self->{extensions}}, $obj;
289
290 $obj;
291 }
127292
128293 sub load_extensions {
129 my ($self, $path, $top_obj) = @_;
130
131 unshift @INC, $self->{prefix}
132 unless grep { $_ eq $self->{prefix} } @INC;
133
134 local @INC = ($path, @INC);
135 foreach my $rv ($self->find_extensions($path)) {
136 my ($file, $pkg) = @{$rv};
137 next if $self->{pathnames}{$pkg};
138
139 eval { require $file; 1 } or (warn($@), next);
140 $self->{pathnames}{$pkg} = delete $INC{$file};
141 push @{$self->{extensions}}, $pkg->new( _top => $top_obj );
142 }
143 }
144
145 #line 279
294 my ($self, $path, $top) = @_;
295
296 my $should_reload = 0;
297 unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) {
298 unshift @INC, $self->{prefix};
299 $should_reload = 1;
300 }
301
302 foreach my $rv ( $self->find_extensions($path) ) {
303 my ($file, $pkg) = @{$rv};
304 next if $self->{pathnames}{$pkg};
305
306 local $@;
307 my $new = eval { local $^W; require $file; $pkg->can('new') };
308 unless ( $new ) {
309 warn $@ if $@;
310 next;
311 }
312 $self->{pathnames}{$pkg} =
313 $should_reload ? delete $INC{$file} : $INC{$file};
314 push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
315 }
316
317 $self->{extensions} ||= [];
318 }
146319
147320 sub find_extensions {
148 my ($self, $path) = @_;
149 my @found;
150
151 File::Find::find(sub {
152 my $file = $File::Find::name;
153 return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
154 return if $1 eq $self->{dispatch};
155
156 $file = "$self->{path}/$1.pm";
157 my $pkg = "$self->{name}::$1"; $pkg =~ s!/!::!g;
158 push @found, [$file, $pkg];
159 }, $path) if -d $path;
160
161 @found;
321 my ($self, $path) = @_;
322
323 my @found;
324 File::Find::find( sub {
325 my $file = $File::Find::name;
326 return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
327 my $subpath = $1;
328 return if lc($subpath) eq lc($self->{dispatch});
329
330 $file = "$self->{path}/$subpath.pm";
331 my $pkg = "$self->{name}::$subpath";
332 $pkg =~ s!/!::!g;
333
334 # If we have a mixed-case package name, assume case has been preserved
335 # correctly. Otherwise, root through the file to locate the case-preserved
336 # version of the package name.
337 if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
338 my $content = Module::Install::_read($subpath . '.pm');
339 my $in_pod = 0;
340 foreach ( split //, $content ) {
341 $in_pod = 1 if /^=\w/;
342 $in_pod = 0 if /^=cut/;
343 next if ($in_pod || /^=cut/); # skip pod text
344 next if /^\s*#/; # and comments
345 if ( m/^\s*package\s+($pkg)\s*;/i ) {
346 $pkg = $1;
347 last;
348 }
349 }
350 }
351
352 push @found, [ $file, $pkg ];
353 }, $path ) if -d $path;
354
355 @found;
356 }
357
358
359
360
361
362 #####################################################################
363 # Common Utility Functions
364
365 sub _caller {
366 my $depth = 0;
367 my $call = caller($depth);
368 while ( $call eq __PACKAGE__ ) {
369 $depth++;
370 $call = caller($depth);
371 }
372 return $call;
373 }
374
375 # Done in evals to avoid confusing Perl::MinimumVersion
376 eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@;
377 sub _read {
378 local *FH;
379 open( FH, '<', $_[0] ) or die "open($_[0]): $!";
380 my $string = do { local $/; <FH> };
381 close FH or die "close($_[0]): $!";
382 return $string;
383 }
384 END_NEW
385 sub _read {
386 local *FH;
387 open( FH, "< $_[0]" ) or die "open($_[0]): $!";
388 my $string = do { local $/; <FH> };
389 close FH or die "close($_[0]): $!";
390 return $string;
391 }
392 END_OLD
393
394 sub _readperl {
395 my $string = Module::Install::_read($_[0]);
396 $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg;
397 $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s;
398 $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg;
399 return $string;
400 }
401
402 sub _readpod {
403 my $string = Module::Install::_read($_[0]);
404 $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg;
405 return $string if $_[0] =~ /\.pod\z/;
406 $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg;
407 $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg;
408 $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg;
409 $string =~ s/^\n+//s;
410 return $string;
411 }
412
413 # Done in evals to avoid confusing Perl::MinimumVersion
414 eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@;
415 sub _write {
416 local *FH;
417 open( FH, '>', $_[0] ) or die "open($_[0]): $!";
418 foreach ( 1 .. $#_ ) {
419 print FH $_[$_] or die "print($_[0]): $!";
420 }
421 close FH or die "close($_[0]): $!";
422 }
423 END_NEW
424 sub _write {
425 local *FH;
426 open( FH, "> $_[0]" ) or die "open($_[0]): $!";
427 foreach ( 1 .. $#_ ) {
428 print FH $_[$_] or die "print($_[0]): $!";
429 }
430 close FH or die "close($_[0]): $!";
431 }
432 END_OLD
433
434 # _version is for processing module versions (eg, 1.03_05) not
435 # Perl versions (eg, 5.8.1).
436 sub _version ($) {
437 my $s = shift || 0;
438 my $d =()= $s =~ /(\.)/g;
439 if ( $d >= 2 ) {
440 # Normalise multipart versions
441 $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg;
442 }
443 $s =~ s/^(\d+)\.?//;
444 my $l = $1 || 0;
445 my @v = map {
446 $_ . '0' x (3 - length $_)
447 } $s =~ /(\d{1,3})\D?/g;
448 $l = $l . '.' . join '', @v if @v;
449 return $l + 0;
450 }
451
452 sub _cmp ($$) {
453 _version($_[0]) <=> _version($_[1]);
454 }
455
456 # Cloned from Params::Util::_CLASS
457 sub _CLASS ($) {
458 (
459 defined $_[0]
460 and
461 ! ref $_[0]
462 and
463 $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s
464 ) ? $_[0] : undef;
162465 }
163466
164467 1;
165468
166 __END__
167
168 #line 617
469 # Copyright 2008 - 2010 Adam Kennedy.
0 #line 1
1 package Spiffy;
2 use strict;
3 use 5.006001;
4 use warnings;
5 use Carp;
6 require Exporter;
7 our $VERSION = '0.30';
8 our @EXPORT = ();
9 our @EXPORT_BASE = qw(field const stub super);
10 our @EXPORT_OK = (@EXPORT_BASE, qw(id WWW XXX YYY ZZZ));
11 our %EXPORT_TAGS = (XXX => [qw(WWW XXX YYY ZZZ)]);
12
13 my $stack_frame = 0;
14 my $dump = 'yaml';
15 my $bases_map = {};
16
17 sub WWW; sub XXX; sub YYY; sub ZZZ;
18
19 # This line is here to convince "autouse" into believing we are autousable.
20 sub can {
21 ($_[1] eq 'import' and caller()->isa('autouse'))
22 ? \&Exporter::import # pacify autouse's equality test
23 : $_[0]->SUPER::can($_[1]) # normal case
24 }
25
26 # TODO
27 #
28 # Exported functions like field and super should be hidden so as not to
29 # be confused with methods that can be inherited.
30 #
31
32 sub new {
33 my $class = shift;
34 $class = ref($class) || $class;
35 my $self = bless {}, $class;
36 while (@_) {
37 my $method = shift;
38 $self->$method(shift);
39 }
40 return $self;
41 }
42
43 my $filtered_files = {};
44 my $filter_dump = 0;
45 my $filter_save = 0;
46 our $filter_result = '';
47 sub import {
48 no strict 'refs';
49 no warnings;
50 my $self_package = shift;
51
52 # XXX Using parse_arguments here might cause confusion, because the
53 # subclass's boolean_arguments and paired_arguments can conflict, causing
54 # difficult debugging. Consider using something truly local.
55 my ($args, @export_list) = do {
56 local *boolean_arguments = sub {
57 qw(
58 -base -Base -mixin -selfless
59 -XXX -dumper -yaml
60 -filter_dump -filter_save
61 )
62 };
63 local *paired_arguments = sub { qw(-package) };
64 $self_package->parse_arguments(@_);
65 };
66 return spiffy_mixin_import(scalar(caller(0)), $self_package, @export_list)
67 if $args->{-mixin};
68
69 $filter_dump = 1 if $args->{-filter_dump};
70 $filter_save = 1 if $args->{-filter_save};
71 $dump = 'yaml' if $args->{-yaml};
72 $dump = 'dumper' if $args->{-dumper};
73
74 local @EXPORT_BASE = @EXPORT_BASE;
75
76 if ($args->{-XXX}) {
77 push @EXPORT_BASE, @{$EXPORT_TAGS{XXX}}
78 unless grep /^XXX$/, @EXPORT_BASE;
79 }
80
81 spiffy_filter()
82 if ($args->{-selfless} or $args->{-Base}) and
83 not $filtered_files->{(caller($stack_frame))[1]}++;
84
85 my $caller_package = $args->{-package} || caller($stack_frame);
86 push @{"$caller_package\::ISA"}, $self_package
87 if $args->{-Base} or $args->{-base};
88
89 for my $class (@{all_my_bases($self_package)}) {
90 next unless $class->isa('Spiffy');
91 my @export = grep {
92 not defined &{"$caller_package\::$_"};
93 } ( @{"$class\::EXPORT"},
94 ($args->{-Base} or $args->{-base})
95 ? @{"$class\::EXPORT_BASE"} : (),
96 );
97 my @export_ok = grep {
98 not defined &{"$caller_package\::$_"};
99 } @{"$class\::EXPORT_OK"};
100
101 # Avoid calling the expensive Exporter::export
102 # if there is nothing to do (optimization)
103 my %exportable = map { ($_, 1) } @export, @export_ok;
104 next unless keys %exportable;
105
106 my @export_save = @{"$class\::EXPORT"};
107 my @export_ok_save = @{"$class\::EXPORT_OK"};
108 @{"$class\::EXPORT"} = @export;
109 @{"$class\::EXPORT_OK"} = @export_ok;
110 my @list = grep {
111 (my $v = $_) =~ s/^[\!\:]//;
112 $exportable{$v} or ${"$class\::EXPORT_TAGS"}{$v};
113 } @export_list;
114 Exporter::export($class, $caller_package, @list);
115 @{"$class\::EXPORT"} = @export_save;
116 @{"$class\::EXPORT_OK"} = @export_ok_save;
117 }
118 }
119
120 sub spiffy_filter {
121 require Filter::Util::Call;
122 my $done = 0;
123 Filter::Util::Call::filter_add(
124 sub {
125 return 0 if $done;
126 my ($data, $end) = ('', '');
127 while (my $status = Filter::Util::Call::filter_read()) {
128 return $status if $status < 0;
129 if (/^__(?:END|DATA)__\r?$/) {
130 $end = $_;
131 last;
132 }
133 $data .= $_;
134 $_ = '';
135 }
136 $_ = $data;
137 my @my_subs;
138 s[^(sub\s+\w+\s+\{)(.*\n)]
139 [${1}my \$self = shift;$2]gm;
140 s[^(sub\s+\w+)\s*\(\s*\)(\s+\{.*\n)]
141 [${1}${2}]gm;
142 s[^my\s+sub\s+(\w+)(\s+\{)(.*)((?s:.*?\n))\}\n]
143 [push @my_subs, $1; "\$$1 = sub$2my \$self = shift;$3$4\};\n"]gem;
144 my $preclare = '';
145 if (@my_subs) {
146 $preclare = join ',', map "\$$_", @my_subs;
147 $preclare = "my($preclare);";
148 }
149 $_ = "use strict;use warnings;$preclare${_};1;\n$end";
150 if ($filter_dump) { print; exit }
151 if ($filter_save) { $filter_result = $_; $_ = $filter_result; }
152 $done = 1;
153 }
154 );
155 }
156
157 sub base {
158 push @_, -base;
159 goto &import;
160 }
161
162 sub all_my_bases {
163 my $class = shift;
164
165 return $bases_map->{$class}
166 if defined $bases_map->{$class};
167
168 my @bases = ($class);
169 no strict 'refs';
170 for my $base_class (@{"${class}::ISA"}) {
171 push @bases, @{all_my_bases($base_class)};
172 }
173 my $used = {};
174 $bases_map->{$class} = [grep {not $used->{$_}++} @bases];
175 }
176
177 my %code = (
178 sub_start =>
179 "sub {\n",
180 set_default =>
181 " \$_[0]->{%s} = %s\n unless exists \$_[0]->{%s};\n",
182 init =>
183 " return \$_[0]->{%s} = do { my \$self = \$_[0]; %s }\n" .
184 " unless \$#_ > 0 or defined \$_[0]->{%s};\n",
185 weak_init =>
186 " return do {\n" .
187 " \$_[0]->{%s} = do { my \$self = \$_[0]; %s };\n" .
188 " Scalar::Util::weaken(\$_[0]->{%s}) if ref \$_[0]->{%s};\n" .
189 " \$_[0]->{%s};\n" .
190 " } unless \$#_ > 0 or defined \$_[0]->{%s};\n",
191 return_if_get =>
192 " return \$_[0]->{%s} unless \$#_ > 0;\n",
193 set =>
194 " \$_[0]->{%s} = \$_[1];\n",
195 weaken =>
196 " Scalar::Util::weaken(\$_[0]->{%s}) if ref \$_[0]->{%s};\n",
197 sub_end =>
198 " return \$_[0]->{%s};\n}\n",
199 );
200
201 sub field {
202 my $package = caller;
203 my ($args, @values) = do {
204 no warnings;
205 local *boolean_arguments = sub { (qw(-weak)) };
206 local *paired_arguments = sub { (qw(-package -init)) };
207 Spiffy->parse_arguments(@_);
208 };
209 my ($field, $default) = @values;
210 $package = $args->{-package} if defined $args->{-package};
211 die "Cannot have a default for a weakened field ($field)"
212 if defined $default && $args->{-weak};
213 return if defined &{"${package}::$field"};
214 require Scalar::Util if $args->{-weak};
215 my $default_string =
216 ( ref($default) eq 'ARRAY' and not @$default )
217 ? '[]'
218 : (ref($default) eq 'HASH' and not keys %$default )
219 ? '{}'
220 : default_as_code($default);
221
222 my $code = $code{sub_start};
223 if ($args->{-init}) {
224 my $fragment = $args->{-weak} ? $code{weak_init} : $code{init};
225 $code .= sprintf $fragment, $field, $args->{-init}, ($field) x 4;
226 }
227 $code .= sprintf $code{set_default}, $field, $default_string, $field
228 if defined $default;
229 $code .= sprintf $code{return_if_get}, $field;
230 $code .= sprintf $code{set}, $field;
231 $code .= sprintf $code{weaken}, $field, $field
232 if $args->{-weak};
233 $code .= sprintf $code{sub_end}, $field;
234
235 my $sub = eval $code;
236 die $@ if $@;
237 no strict 'refs';
238 *{"${package}::$field"} = $sub;
239 return $code if defined wantarray;
240 }
241
242 sub default_as_code {
243 require Data::Dumper;
244 local $Data::Dumper::Sortkeys = 1;
245 my $code = Data::Dumper::Dumper(shift);
246 $code =~ s/^\$VAR1 = //;
247 $code =~ s/;$//;
248 return $code;
249 }
250
251 sub const {
252 my $package = caller;
253 my ($args, @values) = do {
254 no warnings;
255 local *paired_arguments = sub { (qw(-package)) };
256 Spiffy->parse_arguments(@_);
257 };
258 my ($field, $default) = @values;
259 $package = $args->{-package} if defined $args->{-package};
260 no strict 'refs';
261 return if defined &{"${package}::$field"};
262 *{"${package}::$field"} = sub { $default }
263 }
264
265 sub stub {
266 my $package = caller;
267 my ($args, @values) = do {
268 no warnings;
269 local *paired_arguments = sub { (qw(-package)) };
270 Spiffy->parse_arguments(@_);
271 };
272 my ($field, $default) = @values;
273 $package = $args->{-package} if defined $args->{-package};
274 no strict 'refs';
275 return if defined &{"${package}::$field"};
276 *{"${package}::$field"} =
277 sub {
278 require Carp;
279 Carp::confess
280 "Method $field in package $package must be subclassed";
281 }
282 }
283
284 sub parse_arguments {
285 my $class = shift;
286 my ($args, @values) = ({}, ());
287 my %booleans = map { ($_, 1) } $class->boolean_arguments;
288 my %pairs = map { ($_, 1) } $class->paired_arguments;
289 while (@_) {
290 my $elem = shift;
291 if (defined $elem and defined $booleans{$elem}) {
292 $args->{$elem} = (@_ and $_[0] =~ /^[01]$/)
293 ? shift
294 : 1;
295 }
296 elsif (defined $elem and defined $pairs{$elem} and @_) {
297 $args->{$elem} = shift;
298 }
299 else {
300 push @values, $elem;
301 }
302 }
303 return wantarray ? ($args, @values) : $args;
304 }
305
306 sub boolean_arguments { () }
307 sub paired_arguments { () }
308
309 # get a unique id for any node
310 sub id {
311 if (not ref $_[0]) {
312 return 'undef' if not defined $_[0];
313 \$_[0] =~ /\((\w+)\)$/o or die;
314 return "$1-S";
315 }
316 require overload;
317 overload::StrVal($_[0]) =~ /\((\w+)\)$/o or die;
318 return $1;
319 }
320
321 #===============================================================================
322 # It's super, man.
323 #===============================================================================
324 package DB;
325 {
326 no warnings 'redefine';
327 sub super_args {
328 my @dummy = caller(@_ ? $_[0] : 2);
329 return @DB::args;
330 }
331 }
332
333 package Spiffy;
334 sub super {
335 my $method;
336 my $frame = 1;
337 while ($method = (caller($frame++))[3]) {
338 $method =~ s/.*::// and last;
339 }
340 my @args = DB::super_args($frame);
341 @_ = @_ ? ($args[0], @_) : @args;
342 my $class = ref $_[0] ? ref $_[0] : $_[0];
343 my $caller_class = caller;
344 my $seen = 0;
345 my @super_classes = reverse grep {
346 ($seen or $seen = ($_ eq $caller_class)) ? 0 : 1;
347 } reverse @{all_my_bases($class)};
348 for my $super_class (@super_classes) {
349 no strict 'refs';
350 next if $super_class eq $class;
351 if (defined &{"${super_class}::$method"}) {
352 ${"$super_class\::AUTOLOAD"} = ${"$class\::AUTOLOAD"}
353 if $method eq 'AUTOLOAD';
354 return &{"${super_class}::$method"};
355 }
356 }
357 return;
358 }
359
360 #===============================================================================
361 # This code deserves a spanking, because it is being very naughty.
362 # It is exchanging base.pm's import() for its own, so that people
363 # can use base.pm with Spiffy modules, without being the wiser.
364 #===============================================================================
365 my $real_base_import;
366 my $real_mixin_import;
367
368 BEGIN {
369 require base unless defined $INC{'base.pm'};
370 $INC{'mixin.pm'} ||= 'Spiffy/mixin.pm';
371 $real_base_import = \&base::import;
372 $real_mixin_import = \&mixin::import;
373 no warnings;
374 *base::import = \&spiffy_base_import;
375 *mixin::import = \&spiffy_mixin_import;
376 }
377
378 # my $i = 0;
379 # while (my $caller = caller($i++)) {
380 # next unless $caller eq 'base' or $caller eq 'mixin';
381 # croak <<END;
382 # Spiffy.pm must be loaded before calling 'use base' or 'use mixin' with a
383 # Spiffy module. See the documentation of Spiffy.pm for details.
384 # END
385 # }
386
387 sub spiffy_base_import {
388 my @base_classes = @_;
389 shift @base_classes;
390 no strict 'refs';
391 goto &$real_base_import
392 unless grep {
393 eval "require $_" unless %{"$_\::"};
394 $_->isa('Spiffy');
395 } @base_classes;
396 my $inheritor = caller(0);
397 for my $base_class (@base_classes) {
398 next if $inheritor->isa($base_class);
399 croak "Can't mix Spiffy and non-Spiffy classes in 'use base'.\n",
400 "See the documentation of Spiffy.pm for details\n "
401 unless $base_class->isa('Spiffy');
402 $stack_frame = 1; # tell import to use different caller
403 import($base_class, '-base');
404 $stack_frame = 0;
405 }
406 }
407
408 sub mixin {
409 my $self = shift;
410 my $target_class = ref($self);
411 spiffy_mixin_import($target_class, @_)
412 }
413
414 sub spiffy_mixin_import {
415 my $target_class = shift;
416 $target_class = caller(0)
417 if $target_class eq 'mixin';
418 my $mixin_class = shift
419 or die "Nothing to mixin";
420 eval "require $mixin_class";
421 my @roles = @_;
422 my $pseudo_class = join '-', $target_class, $mixin_class, @roles;
423 my %methods = spiffy_mixin_methods($mixin_class, @roles);
424 no strict 'refs';
425 no warnings;
426 @{"$pseudo_class\::ISA"} = @{"$target_class\::ISA"};
427 @{"$target_class\::ISA"} = ($pseudo_class);
428 for (keys %methods) {
429 *{"$pseudo_class\::$_"} = $methods{$_};
430 }
431 }
432
433 sub spiffy_mixin_methods {
434 my $mixin_class = shift;
435 no strict 'refs';
436 my %methods = spiffy_all_methods($mixin_class);
437 map {
438 $methods{$_}
439 ? ($_, \ &{"$methods{$_}\::$_"})
440 : ($_, \ &{"$mixin_class\::$_"})
441 } @_
442 ? (get_roles($mixin_class, @_))
443 : (keys %methods);
444 }
445
446 sub get_roles {
447 my $mixin_class = shift;
448 my @roles = @_;
449 while (grep /^!*:/, @roles) {
450 @roles = map {
451 s/!!//g;
452 /^!:(.*)/ ? do {
453 my $m = "_role_$1";
454 map("!$_", $mixin_class->$m);
455 } :
456 /^:(.*)/ ? do {
457 my $m = "_role_$1";
458 ($mixin_class->$m);
459 } :
460 ($_)
461 } @roles;
462 }
463 if (@roles and $roles[0] =~ /^!/) {
464 my %methods = spiffy_all_methods($mixin_class);
465 unshift @roles, keys(%methods);
466 }
467 my %roles;
468 for (@roles) {
469 s/!!//g;
470 delete $roles{$1}, next
471 if /^!(.*)/;
472 $roles{$_} = 1;
473 }
474 keys %roles;
475 }
476
477 sub spiffy_all_methods {
478 no strict 'refs';
479 my $class = shift;
480 return if $class eq 'Spiffy';
481 my %methods = map {
482 ($_, $class)
483 } grep {
484 defined &{"$class\::$_"} and not /^_/
485 } keys %{"$class\::"};
486 my %super_methods;
487 %super_methods = spiffy_all_methods(${"$class\::ISA"}[0])
488 if @{"$class\::ISA"};
489 %{{%super_methods, %methods}};
490 }
491
492
493 # END of naughty code.
494 #===============================================================================
495 # Debugging support
496 #===============================================================================
497 sub spiffy_dump {
498 no warnings;
499 if ($dump eq 'dumper') {
500 require Data::Dumper;
501 $Data::Dumper::Sortkeys = 1;
502 $Data::Dumper::Indent = 1;
503 return Data::Dumper::Dumper(@_);
504 }
505 require YAML;
506 $YAML::UseVersion = 0;
507 return YAML::Dump(@_) . "...\n";
508 }
509
510 sub at_line_number {
511 my ($file_path, $line_number) = (caller(1))[1,2];
512 " at $file_path line $line_number\n";
513 }
514
515 sub WWW {
516 warn spiffy_dump(@_) . at_line_number;
517 return wantarray ? @_ : $_[0];
518 }
519
520 sub XXX {
521 die spiffy_dump(@_) . at_line_number;
522 }
523
524 sub YYY {
525 print spiffy_dump(@_) . at_line_number;
526 return wantarray ? @_ : $_[0];
527 }
528
529 sub ZZZ {
530 require Carp;
531 Carp::confess spiffy_dump(@_);
532 }
533
534 1;
535
536 __END__
537
538 #line 1066
0 #line 1
1 package Sub::Uplevel;
2
3 use 5.006;
4 use strict;
5 our $VERSION = '0.2002';
6 $VERSION = eval $VERSION;
7
8 sub import {
9 no strict 'refs';
10 my ($class, @args) = @_;
11 for my $fcn ( @args ) {
12 if ( $fcn ne 'uplevel' ) {
13 die qq{"$fcn" is not exported by the $class module\n}
14 }
15 }
16 my $caller = caller(0);
17 *{"$caller\::uplevel"} = \&uplevel;
18 return;
19 }
20
21 # We must override *CORE::GLOBAL::caller if it hasn't already been
22 # overridden or else Perl won't see our local override later.
23
24 if ( not defined *CORE::GLOBAL::caller{CODE} ) {
25 *CORE::GLOBAL::caller = \&_normal_caller;
26 }
27
28
29 #line 96
30
31 # @Up_Frames -- uplevel stack
32 # $Caller_Proxy -- whatever caller() override was in effect before uplevel
33 our (@Up_Frames, $Caller_Proxy);
34
35 sub _apparent_stack_height {
36 my $height = 1; # start above this function
37 while ( 1 ) {
38 last if ! defined scalar $Caller_Proxy->($height);
39 $height++;
40 }
41 return $height - 1; # subtract 1 for this function
42 }
43
44 sub uplevel {
45 my($num_frames, $func, @args) = @_;
46
47 # backwards compatible version of "no warnings 'redefine'"
48 my $old_W = $^W;
49 $^W = 0;
50
51 # Update the caller proxy if the uplevel override isn't in effect
52 local $Caller_Proxy = *CORE::GLOBAL::caller{CODE}
53 if *CORE::GLOBAL::caller{CODE} != \&_uplevel_caller;
54 local *CORE::GLOBAL::caller = \&_uplevel_caller;
55
56 # restore old warnings state
57 $^W = $old_W;
58
59 if ( $num_frames >= _apparent_stack_height() ) {
60 require Carp;
61 Carp::carp("uplevel $num_frames is more than the caller stack");
62 }
63
64 local @Up_Frames = ($num_frames, @Up_Frames );
65
66 return $func->(@args);
67 }
68
69 sub _normal_caller (;$) { ## no critic Prototypes
70 my $height = $_[0];
71 $height++;
72 if ( CORE::caller() eq 'DB' ) {
73 # passthrough the @DB::args trick
74 package DB;
75 if( wantarray and !@_ ) {
76 return (CORE::caller($height))[0..2];
77 }
78 else {
79 return CORE::caller($height);
80 }
81 }
82 else {
83 if( wantarray and !@_ ) {
84 return (CORE::caller($height))[0..2];
85 }
86 else {
87 return CORE::caller($height);
88 }
89 }
90 }
91
92 sub _uplevel_caller (;$) { ## no critic Prototypes
93 my $height = $_[0] || 0;
94
95 # shortcut if no uplevels have been called
96 # always add +1 to CORE::caller (proxy caller function)
97 # to skip this function's caller
98 return $Caller_Proxy->( $height + 1 ) if ! @Up_Frames;
99
100 #line 215
101
102 my $saw_uplevel = 0;
103 my $adjust = 0;
104
105 # walk up the call stack to fight the right package level to return;
106 # look one higher than requested for each call to uplevel found
107 # and adjust by the amount found in the Up_Frames stack for that call.
108 # We *must* use CORE::caller here since we need the real stack not what
109 # some other override says the stack looks like, just in case that other
110 # override breaks things in some horrible way
111
112 for ( my $up = 0; $up <= $height + $adjust; $up++ ) {
113 my @caller = CORE::caller($up + 1);
114 if( defined $caller[0] && $caller[0] eq __PACKAGE__ ) {
115 # add one for each uplevel call seen
116 # and look into the uplevel stack for the offset
117 $adjust += 1 + $Up_Frames[$saw_uplevel];
118 $saw_uplevel++;
119 }
120 }
121
122 # For returning values, we pass through the call to the proxy caller
123 # function, just at a higher stack level
124 my @caller;
125 if ( CORE::caller() eq 'DB' ) {
126 # passthrough the @DB::args trick
127 package DB;
128 @caller = $Sub::Uplevel::Caller_Proxy->($height + $adjust + 1);
129 }
130 else {
131 @caller = $Caller_Proxy->($height + $adjust + 1);
132 }
133
134 if( wantarray ) {
135 if( !@_ ) {
136 @caller = @caller[0..2];
137 }
138 return @caller;
139 }
140 else {
141 return $caller[0];
142 }
143 }
144
145 #line 327
146
147 1;
0 #line 1
1 #. TODO:
2 #.
3
4 #===============================================================================
5 # This is the default class for handling Test::Base data filtering.
6 #===============================================================================
7 package Test::Base::Filter;
8 use Spiffy -Base;
9 use Spiffy ':XXX';
10
11 field 'current_block';
12
13 our $arguments;
14 sub current_arguments {
15 return undef unless defined $arguments;
16 my $args = $arguments;
17 $args =~ s/(\\s)/ /g;
18 $args =~ s/(\\[a-z])/'"' . $1 . '"'/gee;
19 return $args;
20 }
21
22 sub assert_scalar {
23 return if @_ == 1;
24 require Carp;
25 my $filter = (caller(1))[3];
26 $filter =~ s/.*:://;
27 Carp::croak "Input to the '$filter' filter must be a scalar, not a list";
28 }
29
30 sub _apply_deepest {
31 my $method = shift;
32 return () unless @_;
33 if (ref $_[0] eq 'ARRAY') {
34 for my $aref (@_) {
35 @$aref = $self->_apply_deepest($method, @$aref);
36 }
37 return @_;
38 }
39 $self->$method(@_);
40 }
41
42 sub _split_array {
43 map {
44 [$self->split($_)];
45 } @_;
46 }
47
48 sub _peel_deepest {
49 return () unless @_;
50 if (ref $_[0] eq 'ARRAY') {
51 if (ref $_[0]->[0] eq 'ARRAY') {
52 for my $aref (@_) {
53 @$aref = $self->_peel_deepest(@$aref);
54 }
55 return @_;
56 }
57 return map { $_->[0] } @_;
58 }
59 return @_;
60 }
61
62 #===============================================================================
63 # these filters work on the leaves of nested arrays
64 #===============================================================================
65 sub Join { $self->_peel_deepest($self->_apply_deepest(join => @_)) }
66 sub Reverse { $self->_apply_deepest(reverse => @_) }
67 sub Split { $self->_apply_deepest(_split_array => @_) }
68 sub Sort { $self->_apply_deepest(sort => @_) }
69
70
71 sub append {
72 my $suffix = $self->current_arguments;
73 map { $_ . $suffix } @_;
74 }
75
76 sub array {
77 return [@_];
78 }
79
80 sub base64_decode {
81 $self->assert_scalar(@_);
82 require MIME::Base64;
83 MIME::Base64::decode_base64(shift);
84 }
85
86 sub base64_encode {
87 $self->assert_scalar(@_);
88 require MIME::Base64;
89 MIME::Base64::encode_base64(shift);
90 }
91
92 sub chomp {
93 map { CORE::chomp; $_ } @_;
94 }
95
96 sub chop {
97 map { CORE::chop; $_ } @_;
98 }
99
100 sub dumper {
101 no warnings 'once';
102 require Data::Dumper;
103 local $Data::Dumper::Sortkeys = 1;
104 local $Data::Dumper::Indent = 1;
105 local $Data::Dumper::Terse = 1;
106 Data::Dumper::Dumper(@_);
107 }
108
109 sub escape {
110 $self->assert_scalar(@_);
111 my $text = shift;
112 $text =~ s/(\\.)/eval "qq{$1}"/ge;
113 return $text;
114 }
115
116 sub eval {
117 $self->assert_scalar(@_);
118 my @return = CORE::eval(shift);
119 return $@ if $@;
120 return @return;
121 }
122
123 sub eval_all {
124 $self->assert_scalar(@_);
125 my $out = '';
126 my $err = '';
127 Test::Base::tie_output(*STDOUT, $out);
128 Test::Base::tie_output(*STDERR, $err);
129 my $return = CORE::eval(shift);
130 no warnings;
131 untie *STDOUT;
132 untie *STDERR;
133 return $return, $@, $out, $err;
134 }
135
136 sub eval_stderr {
137 $self->assert_scalar(@_);
138 my $output = '';
139 Test::Base::tie_output(*STDERR, $output);
140 CORE::eval(shift);
141 no warnings;
142 untie *STDERR;
143 return $output;
144 }
145
146 sub eval_stdout {
147 $self->assert_scalar(@_);
148 my $output = '';
149 Test::Base::tie_output(*STDOUT, $output);
150 CORE::eval(shift);
151 no warnings;
152 untie *STDOUT;
153 return $output;
154 }
155
156 sub exec_perl_stdout {
157 my $tmpfile = "/tmp/test-blocks-$$";
158 $self->_write_to($tmpfile, @_);
159 open my $execution, "$^X $tmpfile 2>&1 |"
160 or die "Couldn't open subprocess: $!\n";
161 local $/;
162 my $output = <$execution>;
163 close $execution;
164 unlink($tmpfile)
165 or die "Couldn't unlink $tmpfile: $!\n";
166 return $output;
167 }
168
169 sub flatten {
170 $self->assert_scalar(@_);
171 my $ref = shift;
172 if (ref($ref) eq 'HASH') {
173 return map {
174 ($_, $ref->{$_});
175 } sort keys %$ref;
176 }
177 if (ref($ref) eq 'ARRAY') {
178 return @$ref;
179 }
180 die "Can only flatten a hash or array ref";
181 }
182
183 sub get_url {
184 $self->assert_scalar(@_);
185 my $url = shift;
186 CORE::chomp($url);
187 require LWP::Simple;
188 LWP::Simple::get($url);
189 }
190
191 sub hash {
192 return +{ @_ };
193 }
194
195 sub head {
196 my $size = $self->current_arguments || 1;
197 return splice(@_, 0, $size);
198 }
199
200 sub join {
201 my $string = $self->current_arguments;
202 $string = '' unless defined $string;
203 CORE::join $string, @_;
204 }
205
206 sub lines {
207 $self->assert_scalar(@_);
208 my $text = shift;
209 return () unless length $text;
210 my @lines = ($text =~ /^(.*\n?)/gm);
211 return @lines;
212 }
213
214 sub norm {
215 $self->assert_scalar(@_);
216 my $text = shift;
217 $text = '' unless defined $text;
218 $text =~ s/\015\012/\n/g;
219 $text =~ s/\r/\n/g;
220 return $text;
221 }
222
223 sub prepend {
224 my $prefix = $self->current_arguments;
225 map { $prefix . $_ } @_;
226 }
227
228 sub read_file {
229 $self->assert_scalar(@_);
230 my $file = shift;
231 CORE::chomp $file;
232 open my $fh, $file
233 or die "Can't open '$file' for input:\n$!";
234 CORE::join '', <$fh>;
235 }
236
237 sub regexp {
238 $self->assert_scalar(@_);
239 my $text = shift;
240 my $flags = $self->current_arguments;
241 if ($text =~ /\n.*?\n/s) {
242 $flags = 'xism'
243 unless defined $flags;
244 }
245 else {
246 CORE::chomp($text);
247 }
248 $flags ||= '';
249 my $regexp = eval "qr{$text}$flags";
250 die $@ if $@;
251 return $regexp;
252 }
253
254 sub reverse {
255 CORE::reverse(@_);
256 }
257
258 sub slice {
259 die "Invalid args for slice"
260 unless $self->current_arguments =~ /^(\d+)(?:,(\d))?$/;
261 my ($x, $y) = ($1, $2);
262 $y = $x if not defined $y;
263 die "Invalid args for slice"
264 if $x > $y;
265 return splice(@_, $x, 1 + $y - $x);
266 }
267
268 sub sort {
269 CORE::sort(@_);
270 }
271
272 sub split {
273 $self->assert_scalar(@_);
274 my $separator = $self->current_arguments;
275 if (defined $separator and $separator =~ s{^/(.*)/$}{$1}) {
276 my $regexp = $1;
277 $separator = qr{$regexp};
278 }
279 $separator = qr/\s+/ unless $separator;
280 CORE::split $separator, shift;
281 }
282
283 sub strict {
284 $self->assert_scalar(@_);
285 <<'...' . shift;
286 use strict;
287 use warnings;
288 ...
289 }
290
291 sub tail {
292 my $size = $self->current_arguments || 1;
293 return splice(@_, @_ - $size, $size);
294 }
295
296 sub trim {
297 map {
298 s/\A([ \t]*\n)+//;
299 s/(?<=\n)\s*\z//g;
300 $_;
301 } @_;
302 }
303
304 sub unchomp {
305 map { $_ . "\n" } @_;
306 }
307
308 sub write_file {
309 my $file = $self->current_arguments
310 or die "No file specified for write_file filter";
311 if ($file =~ /(.*)[\\\/]/) {
312 my $dir = $1;
313 if (not -e $dir) {
314 require File::Path;
315 File::Path::mkpath($dir)
316 or die "Can't create $dir";
317 }
318 }
319 open my $fh, ">$file"
320 or die "Can't open '$file' for output\n:$!";
321 print $fh @_;
322 close $fh;
323 return $file;
324 }
325
326 sub yaml {
327 $self->assert_scalar(@_);
328 require YAML;
329 return YAML::Load(shift);
330 }
331
332 sub _write_to {
333 my $filename = shift;
334 open my $script, ">$filename"
335 or die "Couldn't open $filename: $!\n";
336 print $script @_;
337 close $script
338 or die "Couldn't close $filename: $!\n";
339 }
340
341 __DATA__
342
343 #line 639
0 #line 1
1 # TODO:
2 #
3 package Test::Base;
4 use 5.006001;
5 use Spiffy 0.30 -Base;
6 use Spiffy ':XXX';
7 our $VERSION = '0.59';
8
9 my @test_more_exports;
10 BEGIN {
11 @test_more_exports = qw(
12 ok isnt like unlike is_deeply cmp_ok
13 skip todo_skip pass fail
14 eq_array eq_hash eq_set
15 plan can_ok isa_ok diag
16 use_ok
17 $TODO
18 );
19 }
20
21 use Test::More import => \@test_more_exports;
22 use Carp;
23
24 our @EXPORT = (@test_more_exports, qw(
25 is no_diff
26
27 blocks next_block first_block
28 delimiters spec_file spec_string
29 filters filters_delay filter_arguments
30 run run_compare run_is run_is_deeply run_like run_unlike
31 skip_all_unless_require is_deep run_is_deep
32 WWW XXX YYY ZZZ
33 tie_output no_diag_on_only
34
35 find_my_self default_object
36
37 croak carp cluck confess
38 ));
39
40 field '_spec_file';
41 field '_spec_string';
42 field _filters => [qw(norm trim)];
43 field _filters_map => {};
44 field spec =>
45 -init => '$self->_spec_init';
46 field block_list =>
47 -init => '$self->_block_list_init';
48 field _next_list => [];
49 field block_delim =>
50 -init => '$self->block_delim_default';
51 field data_delim =>
52 -init => '$self->data_delim_default';
53 field _filters_delay => 0;
54 field _no_diag_on_only => 0;
55
56 field block_delim_default => '===';
57 field data_delim_default => '---';
58
59 my $default_class;
60 my $default_object;
61 my $reserved_section_names = {};
62
63 sub default_object {
64 $default_object ||= $default_class->new;
65 return $default_object;
66 }
67
68 my $import_called = 0;
69 sub import() {
70 $import_called = 1;
71 my $class = (grep /^-base$/i, @_)
72 ? scalar(caller)
73 : $_[0];
74 if (not defined $default_class) {
75 $default_class = $class;
76 }
77 # else {
78 # croak "Can't use $class after using $default_class"
79 # unless $default_class->isa($class);
80 # }
81
82 unless (grep /^-base$/i, @_) {
83 my @args;
84 for (my $ii = 1; $ii <= $#_; ++$ii) {
85 if ($_[$ii] eq '-package') {
86 ++$ii;
87 } else {
88 push @args, $_[$ii];
89 }
90 }
91 Test::More->import(import => \@test_more_exports, @args)
92 if @args;
93 }
94
95 _strict_warnings();
96 goto &Spiffy::import;
97 }
98
99 # Wrap Test::Builder::plan
100 my $plan_code = \&Test::Builder::plan;
101 my $Have_Plan = 0;
102 {
103 no warnings 'redefine';
104 *Test::Builder::plan = sub {
105 $Have_Plan = 1;
106 goto &$plan_code;
107 };
108 }
109
110 my $DIED = 0;
111 $SIG{__DIE__} = sub { $DIED = 1; die @_ };
112
113 sub block_class { $self->find_class('Block') }
114 sub filter_class { $self->find_class('Filter') }
115
116 sub find_class {
117 my $suffix = shift;
118 my $class = ref($self) . "::$suffix";
119 return $class if $class->can('new');
120 $class = __PACKAGE__ . "::$suffix";
121 return $class if $class->can('new');
122 eval "require $class";
123 return $class if $class->can('new');
124 die "Can't find a class for $suffix";
125 }
126
127 sub check_late {
128 if ($self->{block_list}) {
129 my $caller = (caller(1))[3];
130 $caller =~ s/.*:://;
131 croak "Too late to call $caller()"
132 }
133 }
134
135 sub find_my_self() {
136 my $self = ref($_[0]) eq $default_class
137 ? splice(@_, 0, 1)
138 : default_object();
139 return $self, @_;
140 }
141
142 sub blocks() {
143 (my ($self), @_) = find_my_self(@_);
144
145 croak "Invalid arguments passed to 'blocks'"
146 if @_ > 1;
147 croak sprintf("'%s' is invalid argument to blocks()", shift(@_))
148 if @_ && $_[0] !~ /^[a-zA-Z]\w*$/;
149
150 my $blocks = $self->block_list;
151
152 my $section_name = shift || '';
153 my @blocks = $section_name
154 ? (grep { exists $_->{$section_name} } @$blocks)
155 : (@$blocks);
156
157 return scalar(@blocks) unless wantarray;
158
159 return (@blocks) if $self->_filters_delay;
160
161 for my $block (@blocks) {
162 $block->run_filters
163 unless $block->is_filtered;
164 }
165
166 return (@blocks);
167 }
168
169 sub next_block() {
170 (my ($self), @_) = find_my_self(@_);
171 my $list = $self->_next_list;
172 if (@$list == 0) {
173 $list = [@{$self->block_list}, undef];
174 $self->_next_list($list);
175 }
176 my $block = shift @$list;
177 if (defined $block and not $block->is_filtered) {
178 $block->run_filters;
179 }
180 return $block;
181 }
182
183 sub first_block() {
184 (my ($self), @_) = find_my_self(@_);
185 $self->_next_list([]);
186 $self->next_block;
187 }
188
189 sub filters_delay() {
190 (my ($self), @_) = find_my_self(@_);
191 $self->_filters_delay(defined $_[0] ? shift : 1);
192 }
193
194 sub no_diag_on_only() {
195 (my ($self), @_) = find_my_self(@_);
196 $self->_no_diag_on_only(defined $_[0] ? shift : 1);
197 }
198
199 sub delimiters() {
200 (my ($self), @_) = find_my_self(@_);
201 $self->check_late;
202 my ($block_delimiter, $data_delimiter) = @_;
203 $block_delimiter ||= $self->block_delim_default;
204 $data_delimiter ||= $self->data_delim_default;
205 $self->block_delim($block_delimiter);
206 $self->data_delim($data_delimiter);
207 return $self;
208 }
209
210 sub spec_file() {
211 (my ($self), @_) = find_my_self(@_);
212 $self->check_late;
213 $self->_spec_file(shift);
214 return $self;
215 }
216
217 sub spec_string() {
218 (my ($self), @_) = find_my_self(@_);
219 $self->check_late;
220 $self->_spec_string(shift);
221 return $self;
222 }
223
224 sub filters() {
225 (my ($self), @_) = find_my_self(@_);
226 if (ref($_[0]) eq 'HASH') {
227 $self->_filters_map(shift);
228 }
229 else {
230 my $filters = $self->_filters;
231 push @$filters, @_;
232 }
233 return $self;
234 }
235
236 sub filter_arguments() {
237 $Test::Base::Filter::arguments;
238 }
239
240 sub have_text_diff {
241 eval { require Text::Diff; 1 } &&
242 $Text::Diff::VERSION >= 0.35 &&
243 $Algorithm::Diff::VERSION >= 1.15;
244 }
245
246 sub is($$;$) {
247 (my ($self), @_) = find_my_self(@_);
248 my ($actual, $expected, $name) = @_;
249 local $Test::Builder::Level = $Test::Builder::Level + 1;
250 if ($ENV{TEST_SHOW_NO_DIFFS} or
251 not defined $actual or
252 not defined $expected or
253 $actual eq $expected or
254 not($self->have_text_diff) or
255 $expected !~ /\n./s
256 ) {
257 Test::More::is($actual, $expected, $name);
258 }
259 else {
260 $name = '' unless defined $name;
261 ok $actual eq $expected,
262 $name . "\n" . Text::Diff::diff(\$expected, \$actual);
263 }
264 }
265
266 sub run(&;$) {
267 (my ($self), @_) = find_my_self(@_);
268 my $callback = shift;
269 for my $block (@{$self->block_list}) {
270 $block->run_filters unless $block->is_filtered;
271 &{$callback}($block);
272 }
273 }
274
275 my $name_error = "Can't determine section names";
276 sub _section_names {
277 return @_ if @_ == 2;
278 my $block = $self->first_block
279 or croak $name_error;
280 my @names = grep {
281 $_ !~ /^(ONLY|LAST|SKIP)$/;
282 } @{$block->{_section_order}[0] || []};
283 croak "$name_error. Need two sections in first block"
284 unless @names == 2;
285 return @names;
286 }
287
288 sub _assert_plan {
289 plan('no_plan') unless $Have_Plan;
290 }
291
292 sub END {
293 run_compare() unless $Have_Plan or $DIED or not $import_called;
294 }
295
296 sub run_compare() {
297 (my ($self), @_) = find_my_self(@_);
298 $self->_assert_plan;
299 my ($x, $y) = $self->_section_names(@_);
300 local $Test::Builder::Level = $Test::Builder::Level + 1;
301 for my $block (@{$self->block_list}) {
302 next unless exists($block->{$x}) and exists($block->{$y});
303 $block->run_filters unless $block->is_filtered;
304 if (ref $block->$x) {
305 is_deeply($block->$x, $block->$y,
306 $block->name ? $block->name : ());
307 }
308 elsif (ref $block->$y eq 'Regexp') {
309 my $regexp = ref $y ? $y : $block->$y;
310 like($block->$x, $regexp, $block->name ? $block->name : ());
311 }
312 else {
313 is($block->$x, $block->$y, $block->name ? $block->name : ());
314 }
315 }
316 }
317
318 sub run_is() {
319 (my ($self), @_) = find_my_self(@_);
320 $self->_assert_plan;
321 my ($x, $y) = $self->_section_names(@_);
322 local $Test::Builder::Level = $Test::Builder::Level + 1;
323 for my $block (@{$self->block_list}) {
324 next unless exists($block->{$x}) and exists($block->{$y});
325 $block->run_filters unless $block->is_filtered;
326 is($block->$x, $block->$y,
327 $block->name ? $block->name : ()
328 );
329 }
330 }
331
332 sub run_is_deeply() {
333 (my ($self), @_) = find_my_self(@_);
334 $self->_assert_plan;
335 my ($x, $y) = $self->_section_names(@_);
336 for my $block (@{$self->block_list}) {
337 next unless exists($block->{$x}) and exists($block->{$y});
338 $block->run_filters unless $block->is_filtered;
339 is_deeply($block->$x, $block->$y,
340 $block->name ? $block->name : ()
341 );
342 }
343 }
344
345 sub run_like() {
346 (my ($self), @_) = find_my_self(@_);
347 $self->_assert_plan;
348 my ($x, $y) = $self->_section_names(@_);
349 for my $block (@{$self->block_list}) {
350 next unless exists($block->{$x}) and defined($y);
351 $block->run_filters unless $block->is_filtered;
352 my $regexp = ref $y ? $y : $block->$y;
353 like($block->$x, $regexp,
354 $block->name ? $block->name : ()
355 );
356 }
357 }
358
359 sub run_unlike() {
360 (my ($self), @_) = find_my_self(@_);
361 $self->_assert_plan;
362 my ($x, $y) = $self->_section_names(@_);
363 for my $block (@{$self->block_list}) {
364 next unless exists($block->{$x}) and defined($y);
365 $block->run_filters unless $block->is_filtered;
366 my $regexp = ref $y ? $y : $block->$y;
367 unlike($block->$x, $regexp,
368 $block->name ? $block->name : ()
369 );
370 }
371 }
372
373 sub skip_all_unless_require() {
374 (my ($self), @_) = find_my_self(@_);
375 my $module = shift;
376 eval "require $module; 1"
377 or Test::More::plan(
378 skip_all => "$module failed to load"
379 );
380 }
381
382 sub is_deep() {
383 (my ($self), @_) = find_my_self(@_);
384 require Test::Deep;
385 Test::Deep::cmp_deeply(@_);
386 }
387
388 sub run_is_deep() {
389 (my ($self), @_) = find_my_self(@_);
390 $self->_assert_plan;
391 my ($x, $y) = $self->_section_names(@_);
392 for my $block (@{$self->block_list}) {
393 next unless exists($block->{$x}) and exists($block->{$y});
394 $block->run_filters unless $block->is_filtered;
395 is_deep($block->$x, $block->$y,
396 $block->name ? $block->name : ()
397 );
398 }
399 }
400
401 sub _pre_eval {
402 my $spec = shift;
403 return $spec unless $spec =~
404 s/\A\s*<<<(.*?)>>>\s*$//sm;
405 my $eval_code = $1;
406 eval "package main; $eval_code";
407 croak $@ if $@;
408 return $spec;
409 }
410
411 sub _block_list_init {
412 my $spec = $self->spec;
413 $spec = $self->_pre_eval($spec);
414 my $cd = $self->block_delim;
415 my @hunks = ($spec =~ /^(\Q${cd}\E.*?(?=^\Q${cd}\E|\z))/msg);
416 my $blocks = $self->_choose_blocks(@hunks);
417 $self->block_list($blocks); # Need to set early for possible filter use
418 my $seq = 1;
419 for my $block (@$blocks) {
420 $block->blocks_object($self);
421 $block->seq_num($seq++);
422 }
423 return $blocks;
424 }
425
426 sub _choose_blocks {
427 my $blocks = [];
428 for my $hunk (@_) {
429 my $block = $self->_make_block($hunk);
430 if (exists $block->{ONLY}) {
431 diag "I found ONLY: maybe you're debugging?"
432 unless $self->_no_diag_on_only;
433 return [$block];
434 }
435 next if exists $block->{SKIP};
436 push @$blocks, $block;
437 if (exists $block->{LAST}) {
438 return $blocks;
439 }
440 }
441 return $blocks;
442 }
443
444 sub _check_reserved {
445 my $id = shift;
446 croak "'$id' is a reserved name. Use something else.\n"
447 if $reserved_section_names->{$id} or
448 $id =~ /^_/;
449 }
450
451 sub _make_block {
452 my $hunk = shift;
453 my $cd = $self->block_delim;
454 my $dd = $self->data_delim;
455 my $block = $self->block_class->new;
456 $hunk =~ s/\A\Q${cd}\E[ \t]*(.*)\s+// or die;
457 my $name = $1;
458 my @parts = split /^\Q${dd}\E +\(?(\w+)\)? *(.*)?\n/m, $hunk;
459 my $description = shift @parts;
460 $description ||= '';
461 unless ($description =~ /\S/) {
462 $description = $name;
463 }
464 $description =~ s/\s*\z//;
465 $block->set_value(description => $description);
466
467 my $section_map = {};
468 my $section_order = [];
469 while (@parts) {
470 my ($type, $filters, $value) = splice(@parts, 0, 3);
471 $self->_check_reserved($type);
472 $value = '' unless defined $value;
473 $filters = '' unless defined $filters;
474 if ($filters =~ /:(\s|\z)/) {
475 croak "Extra lines not allowed in '$type' section"
476 if $value =~ /\S/;
477 ($filters, $value) = split /\s*:(?:\s+|\z)/, $filters, 2;
478 $value = '' unless defined $value;
479 $value =~ s/^\s*(.*?)\s*$/$1/;
480 }
481 $section_map->{$type} = {
482 filters => $filters,
483 };
484 push @$section_order, $type;
485 $block->set_value($type, $value);
486 }
487 $block->set_value(name => $name);
488 $block->set_value(_section_map => $section_map);
489 $block->set_value(_section_order => $section_order);
490 return $block;
491 }
492
493 sub _spec_init {
494 return $self->_spec_string
495 if $self->_spec_string;
496 local $/;
497 my $spec;
498 if (my $spec_file = $self->_spec_file) {
499 open FILE, $spec_file or die $!;
500 $spec = <FILE>;
501 close FILE;
502 }
503 else {
504 $spec = do {
505 package main;
506 no warnings 'once';
507 <DATA>;
508 };
509 }
510 return $spec;
511 }
512
513 sub _strict_warnings() {
514 require Filter::Util::Call;
515 my $done = 0;
516 Filter::Util::Call::filter_add(
517 sub {
518 return 0 if $done;
519 my ($data, $end) = ('', '');
520 while (my $status = Filter::Util::Call::filter_read()) {
521 return $status if $status < 0;
522 if (/^__(?:END|DATA)__\r?$/) {
523 $end = $_;
524 last;
525 }
526 $data .= $_;
527 $_ = '';
528 }
529 $_ = "use strict;use warnings;$data$end";
530 $done = 1;
531 }
532 );
533 }
534
535 sub tie_output() {
536 my $handle = shift;
537 die "No buffer to tie" unless @_;
538 tie $handle, 'Test::Base::Handle', $_[0];
539 }
540
541 sub no_diff {
542 $ENV{TEST_SHOW_NO_DIFFS} = 1;
543 }
544
545 package Test::Base::Handle;
546
547 sub TIEHANDLE() {
548 my $class = shift;
549 bless \ $_[0], $class;
550 }
551
552 sub PRINT {
553 $$self .= $_ for @_;
554 }
555
556 #===============================================================================
557 # Test::Base::Block
558 #
559 # This is the default class for accessing a Test::Base block object.
560 #===============================================================================
561 package Test::Base::Block;
562 our @ISA = qw(Spiffy);
563
564 our @EXPORT = qw(block_accessor);
565
566 sub AUTOLOAD {
567 return;
568 }
569
570 sub block_accessor() {
571 my $accessor = shift;
572 no strict 'refs';
573 return if defined &$accessor;
574 *$accessor = sub {
575 my $self = shift;
576 if (@_) {
577 Carp::croak "Not allowed to set values for '$accessor'";
578 }
579 my @list = @{$self->{$accessor} || []};
580 return wantarray
581 ? (@list)
582 : $list[0];
583 };
584 }
585
586 block_accessor 'name';
587 block_accessor 'description';
588 Spiffy::field 'seq_num';
589 Spiffy::field 'is_filtered';
590 Spiffy::field 'blocks_object';
591 Spiffy::field 'original_values' => {};
592
593 sub set_value {
594 no strict 'refs';
595 my $accessor = shift;
596 block_accessor $accessor
597 unless defined &$accessor;
598 $self->{$accessor} = [@_];
599 }
600
601 sub run_filters {
602 my $map = $self->_section_map;
603 my $order = $self->_section_order;
604 Carp::croak "Attempt to filter a block twice"
605 if $self->is_filtered;
606 for my $type (@$order) {
607 my $filters = $map->{$type}{filters};
608 my @value = $self->$type;
609 $self->original_values->{$type} = $value[0];
610 for my $filter ($self->_get_filters($type, $filters)) {
611 $Test::Base::Filter::arguments =
612 $filter =~ s/=(.*)$// ? $1 : undef;
613 my $function = "main::$filter";
614 no strict 'refs';
615 if (defined &$function) {
616 local $_ =
617 (@value == 1 and not defined($value[0])) ? undef :
618 join '', @value;
619 my $old = $_;
620 @value = &$function(@value);
621 if (not(@value) or
622 @value == 1 and defined($value[0]) and $value[0] =~ /\A(\d+|)\z/
623 ) {
624 if ($value[0] && $_ eq $old) {
625 Test::Base::diag("Filters returning numbers are supposed to do munging \$_: your filter '$function' apparently doesn't.");
626 }
627 @value = ($_);
628 }
629 }
630 else {
631 my $filter_object = $self->blocks_object->filter_class->new;
632 die "Can't find a function or method for '$filter' filter\n"
633 unless $filter_object->can($filter);
634 $filter_object->current_block($self);
635 @value = $filter_object->$filter(@value);
636 }
637 # Set the value after each filter since other filters may be
638 # introspecting.
639 $self->set_value($type, @value);
640 }
641 }
642 $self->is_filtered(1);
643 }
644
645 sub _get_filters {
646 my $type = shift;
647 my $string = shift || '';
648 $string =~ s/\s*(.*?)\s*/$1/;
649 my @filters = ();
650 my $map_filters = $self->blocks_object->_filters_map->{$type} || [];
651 $map_filters = [ $map_filters ] unless ref $map_filters;
652 my @append = ();
653 for (
654 @{$self->blocks_object->_filters},
655 @$map_filters,
656 split(/\s+/, $string),
657 ) {
658 my $filter = $_;
659 last unless length $filter;
660 if ($filter =~ s/^-//) {
661 @filters = grep { $_ ne $filter } @filters;
662 }
663 elsif ($filter =~ s/^\+//) {
664 push @append, $filter;
665 }
666 else {
667 push @filters, $filter;
668 }
669 }
670 return @filters, @append;
671 }
672
673 {
674 %$reserved_section_names = map {
675 ($_, 1);
676 } keys(%Test::Base::Block::), qw( new DESTROY );
677 }
678
679 __DATA__
680
681 =encoding utf8
682
683 #line 1376
0 #line 1
1 package Test::Builder::Module;
2
3 use strict;
4
5 use Test::Builder;
6
7 require Exporter;
8 our @ISA = qw(Exporter);
9
10 our $VERSION = '0.94';
11 $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
12
13
14 #line 74
15
16 sub import {
17 my($class) = shift;
18
19 # Don't run all this when loading ourself.
20 return 1 if $class eq 'Test::Builder::Module';
21
22 my $test = $class->builder;
23
24 my $caller = caller;
25
26 $test->exported_to($caller);
27
28 $class->import_extra( \@_ );
29 my(@imports) = $class->_strip_imports( \@_ );
30
31 $test->plan(@_);
32
33 $class->export_to_level( 1, $class, @imports );
34 }
35
36 sub _strip_imports {
37 my $class = shift;
38 my $list = shift;
39
40 my @imports = ();
41 my @other = ();
42 my $idx = 0;
43 while( $idx <= $#{$list} ) {
44 my $item = $list->[$idx];
45
46 if( defined $item and $item eq 'import' ) {
47 push @imports, @{ $list->[ $idx + 1 ] };
48 $idx++;
49 }
50 else {
51 push @other, $item;
52 }
53
54 $idx++;
55 }
56
57 @$list = @other;
58
59 return @imports;
60 }
61
62 #line 137
63
64 sub import_extra { }
65
66 #line 167
67
68 sub builder {
69 return Test::Builder->new;
70 }
71
72 1;
0 #line 1
1 package Test::Builder;
2
3 use 5.006;
4 use strict;
5 use warnings;
6
7 our $VERSION = '0.94';
8 $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
9
10 BEGIN {
11 if( $] < 5.008 ) {
12 require Test::Builder::IO::Scalar;
13 }
14 }
15
16
17 # Make Test::Builder thread-safe for ithreads.
18 BEGIN {
19 use Config;
20 # Load threads::shared when threads are turned on.
21 # 5.8.0's threads are so busted we no longer support them.
22 if( $] >= 5.008001 && $Config{useithreads} && $INC{'threads.pm'} ) {
23 require threads::shared;
24
25 # Hack around YET ANOTHER threads::shared bug. It would
26 # occassionally forget the contents of the variable when sharing it.
27 # So we first copy the data, then share, then put our copy back.
28 *share = sub (\[$@%]) {
29 my $type = ref $_[0];
30 my $data;
31
32 if( $type eq 'HASH' ) {
33 %$data = %{ $_[0] };
34 }
35 elsif( $type eq 'ARRAY' ) {
36 @$data = @{ $_[0] };
37 }
38 elsif( $type eq 'SCALAR' ) {
39 $$data = ${ $_[0] };
40 }
41 else {
42 die( "Unknown type: " . $type );
43 }
44
45 $_[0] = &threads::shared::share( $_[0] );
46
47 if( $type eq 'HASH' ) {
48 %{ $_[0] } = %$data;
49 }
50 elsif( $type eq 'ARRAY' ) {
51 @{ $_[0] } = @$data;
52 }
53 elsif( $type eq 'SCALAR' ) {
54 ${ $_[0] } = $$data;
55 }
56 else {
57 die( "Unknown type: " . $type );
58 }
59
60 return $_[0];
61 };
62 }
63 # 5.8.0's threads::shared is busted when threads are off
64 # and earlier Perls just don't have that module at all.
65 else {
66 *share = sub { return $_[0] };
67 *lock = sub { 0 };
68 }
69 }
70
71 #line 117
72
73 our $Test = Test::Builder->new;
74
75 sub new {
76 my($class) = shift;
77 $Test ||= $class->create;
78 return $Test;
79 }
80
81 #line 139
82
83 sub create {
84 my $class = shift;
85
86 my $self = bless {}, $class;
87 $self->reset;
88
89 return $self;
90 }
91
92 #line 168
93
94 sub child {
95 my( $self, $name ) = @_;
96
97 if( $self->{Child_Name} ) {
98 $self->croak("You already have a child named ($self->{Child_Name}) running");
99 }
100
101 my $child = bless {}, ref $self;
102 $child->reset;
103
104 # Add to our indentation
105 $child->_indent( $self->_indent . ' ' );
106 $child->{$_} = $self->{$_} foreach qw{Out_FH Todo_FH Fail_FH};
107
108 # This will be reset in finalize. We do this here lest one child failure
109 # cause all children to fail.
110 $child->{Child_Error} = $?;
111 $? = 0;
112 $child->{Parent} = $self;
113 $child->{Name} = $name || "Child of " . $self->name;
114 $self->{Child_Name} = $child->name;
115 return $child;
116 }
117
118
119 #line 201
120
121 sub subtest {
122 my $self = shift;
123 my($name, $subtests) = @_;
124
125 if ('CODE' ne ref $subtests) {
126 $self->croak("subtest()'s second argument must be a code ref");
127 }
128
129 # Turn the child into the parent so anyone who has stored a copy of
130 # the Test::Builder singleton will get the child.
131 my $child = $self->child($name);
132 my %parent = %$self;
133 %$self = %$child;
134
135 my $error;
136 if( !eval { $subtests->(); 1 } ) {
137 $error = $@;
138 }
139
140 # Restore the parent and the copied child.
141 %$child = %$self;
142 %$self = %parent;
143
144 # Die *after* we restore the parent.
145 die $error if $error and !eval { $error->isa('Test::Builder::Exception') };
146
147 return $child->finalize;
148 }
149
150
151 #line 250
152
153 sub finalize {
154 my $self = shift;
155
156 return unless $self->parent;
157 if( $self->{Child_Name} ) {
158 $self->croak("Can't call finalize() with child ($self->{Child_Name}) active");
159 }
160 $self->_ending;
161
162 # XXX This will only be necessary for TAP envelopes (we think)
163 #$self->_print( $self->is_passing ? "PASS\n" : "FAIL\n" );
164
165 my $ok = 1;
166 $self->parent->{Child_Name} = undef;
167 if ( $self->{Skip_All} ) {
168 $self->parent->skip($self->{Skip_All});
169 }
170 elsif ( not @{ $self->{Test_Results} } ) {
171 $self->parent->ok( 0, sprintf q[No tests run for subtest "%s"], $self->name );
172 }
173 else {
174 $self->parent->ok( $self->is_passing, $self->name );
175 }
176 $? = $self->{Child_Error};
177 delete $self->{Parent};
178
179 return $self->is_passing;
180 }
181
182 sub _indent {
183 my $self = shift;
184
185 if( @_ ) {
186 $self->{Indent} = shift;
187 }
188
189 return $self->{Indent};
190 }
191
192 #line 300
193
194 sub parent { shift->{Parent} }
195
196 #line 312
197
198 sub name { shift->{Name} }
199
200 sub DESTROY {
201 my $self = shift;
202 if ( $self->parent ) {
203 my $name = $self->name;
204 $self->diag(<<"FAIL");
205 Child ($name) exited without calling finalize()
206 FAIL
207 $self->parent->{In_Destroy} = 1;
208 $self->parent->ok(0, $name);
209 }
210 }
211
212 #line 336
213
214 our $Level;
215
216 sub reset { ## no critic (Subroutines::ProhibitBuiltinHomonyms)
217 my($self) = @_;
218
219 # We leave this a global because it has to be localized and localizing
220 # hash keys is just asking for pain. Also, it was documented.
221 $Level = 1;
222
223 $self->{Name} = $0;
224 $self->is_passing(1);
225 $self->{Ending} = 0;
226 $self->{Have_Plan} = 0;
227 $self->{No_Plan} = 0;
228 $self->{Have_Output_Plan} = 0;
229
230 $self->{Original_Pid} = $$;
231 $self->{Child_Name} = undef;
232 $self->{Indent} ||= '';
233
234 share( $self->{Curr_Test} );
235 $self->{Curr_Test} = 0;
236 $self->{Test_Results} = &share( [] );
237
238 $self->{Exported_To} = undef;
239 $self->{Expected_Tests} = 0;
240
241 $self->{Skip_All} = 0;
242
243 $self->{Use_Nums} = 1;
244
245 $self->{No_Header} = 0;
246 $self->{No_Ending} = 0;
247
248 $self->{Todo} = undef;
249 $self->{Todo_Stack} = [];
250 $self->{Start_Todo} = 0;
251 $self->{Opened_Testhandles} = 0;
252
253 $self->_dup_stdhandles;
254
255 return;
256 }
257
258 #line 414
259
260 my %plan_cmds = (
261 no_plan => \&no_plan,
262 skip_all => \&skip_all,
263 tests => \&_plan_tests,
264 );
265
266 sub plan {
267 my( $self, $cmd, $arg ) = @_;
268
269 return unless $cmd;
270
271 local $Level = $Level + 1;
272
273 $self->croak("You tried to plan twice") if $self->{Have_Plan};
274
275 if( my $method = $plan_cmds{$cmd} ) {
276 local $Level = $Level + 1;
277 $self->$method($arg);
278 }
279 else {
280 my @args = grep { defined } ( $cmd, $arg );
281 $self->croak("plan() doesn't understand @args");
282 }
283
284 return 1;
285 }
286
287
288 sub _plan_tests {
289 my($self, $arg) = @_;
290
291 if($arg) {
292 local $Level = $Level + 1;
293 return $self->expected_tests($arg);
294 }
295 elsif( !defined $arg ) {
296 $self->croak("Got an undefined number of tests");
297 }
298 else {
299 $self->croak("You said to run 0 tests");
300 }
301
302 return;
303 }
304
305
306 #line 470
307
308 sub expected_tests {
309 my $self = shift;
310 my($max) = @_;
311
312 if(@_) {
313 $self->croak("Number of tests must be a positive integer. You gave it '$max'")
314 unless $max =~ /^\+?\d+$/;
315
316 $self->{Expected_Tests} = $max;
317 $self->{Have_Plan} = 1;
318
319 $self->_output_plan($max) unless $self->no_header;
320 }
321 return $self->{Expected_Tests};
322 }
323
324 #line 494
325
326 sub no_plan {
327 my($self, $arg) = @_;
328
329 $self->carp("no_plan takes no arguments") if $arg;
330
331 $self->{No_Plan} = 1;
332 $self->{Have_Plan} = 1;
333
334 return 1;
335 }
336
337
338 #line 528
339
340 sub _output_plan {
341 my($self, $max, $directive, $reason) = @_;
342
343 $self->carp("The plan was already output") if $self->{Have_Output_Plan};
344
345 my $plan = "1..$max";
346 $plan .= " # $directive" if defined $directive;
347 $plan .= " $reason" if defined $reason;
348
349 $self->_print("$plan\n");
350
351 $self->{Have_Output_Plan} = 1;
352
353 return;
354 }
355
356 #line 579
357
358 sub done_testing {
359 my($self, $num_tests) = @_;
360
361 # If done_testing() specified the number of tests, shut off no_plan.
362 if( defined $num_tests ) {
363 $self->{No_Plan} = 0;
364 }
365 else {
366 $num_tests = $self->current_test;
367 }
368
369 if( $self->{Done_Testing} ) {
370 my($file, $line) = @{$self->{Done_Testing}}[1,2];
371 $self->ok(0, "done_testing() was already called at $file line $line");
372 return;
373 }
374
375 $self->{Done_Testing} = [caller];
376
377 if( $self->expected_tests && $num_tests != $self->expected_tests ) {
378 $self->ok(0, "planned to run @{[ $self->expected_tests ]} ".
379 "but done_testing() expects $num_tests");
380 }
381 else {
382 $self->{Expected_Tests} = $num_tests;
383 }
384
385 $self->_output_plan($num_tests) unless $self->{Have_Output_Plan};
386
387 $self->{Have_Plan} = 1;
388
389 # The wrong number of tests were run
390 $self->is_passing(0) if $self->{Expected_Tests} != $self->{Curr_Test};
391
392 # No tests were run
393 $self->is_passing(0) if $self->{Curr_Test} == 0;
394
395 return 1;
396 }
397
398
399 #line 630
400
401 sub has_plan {
402 my $self = shift;
403
404 return( $self->{Expected_Tests} ) if $self->{Expected_Tests};
405 return('no_plan') if $self->{No_Plan};
406 return(undef);
407 }
408
409 #line 647
410
411 sub skip_all {
412 my( $self, $reason ) = @_;
413
414 $self->{Skip_All} = $self->parent ? $reason : 1;
415
416 $self->_output_plan(0, "SKIP", $reason) unless $self->no_header;
417 if ( $self->parent ) {
418 die bless {} => 'Test::Builder::Exception';
419 }
420 exit(0);
421 }
422
423 #line 672
424
425 sub exported_to {
426 my( $self, $pack ) = @_;
427
428 if( defined $pack ) {
429 $self->{Exported_To} = $pack;
430 }
431 return $self->{Exported_To};
432 }
433
434 #line 702
435
436 sub ok {
437 my( $self, $test, $name ) = @_;
438
439 if ( $self->{Child_Name} and not $self->{In_Destroy} ) {
440 $name = 'unnamed test' unless defined $name;
441 $self->is_passing(0);
442 $self->croak("Cannot run test ($name) with active children");
443 }
444 # $test might contain an object which we don't want to accidentally
445 # store, so we turn it into a boolean.
446 $test = $test ? 1 : 0;
447
448 lock $self->{Curr_Test};
449 $self->{Curr_Test}++;
450
451 # In case $name is a string overloaded object, force it to stringify.
452 $self->_unoverload_str( \$name );
453
454 $self->diag(<<"ERR") if defined $name and $name =~ /^[\d\s]+$/;
455 You named your test '$name'. You shouldn't use numbers for your test names.
456 Very confusing.
457 ERR
458
459 # Capture the value of $TODO for the rest of this ok() call
460 # so it can more easily be found by other routines.
461 my $todo = $self->todo();
462 my $in_todo = $self->in_todo;
463 local $self->{Todo} = $todo if $in_todo;
464
465 $self->_unoverload_str( \$todo );
466
467 my $out;
468 my $result = &share( {} );
469
470 unless($test) {
471 $out .= "not ";
472 @$result{ 'ok', 'actual_ok' } = ( ( $self->in_todo ? 1 : 0 ), 0 );
473 }
474 else {
475 @$result{ 'ok', 'actual_ok' } = ( 1, $test );
476 }
477
478 $out .= "ok";
479 $out .= " $self->{Curr_Test}" if $self->use_numbers;
480
481 if( defined $name ) {
482 $name =~ s|#|\\#|g; # # in a name can confuse Test::Harness.
483 $out .= " - $name";
484 $result->{name} = $name;
485 }
486 else {
487 $result->{name} = '';
488 }
489
490 if( $self->in_todo ) {
491 $out .= " # TODO $todo";
492 $result->{reason} = $todo;
493 $result->{type} = 'todo';
494 }
495 else {
496 $result->{reason} = '';
497 $result->{type} = '';
498 }
499
500 $self->{Test_Results}[ $self->{Curr_Test} - 1 ] = $result;
501 $out .= "\n";
502
503 $self->_print($out);
504
505 unless($test) {
506 my $msg = $self->in_todo ? "Failed (TODO)" : "Failed";
507 $self->_print_to_fh( $self->_diag_fh, "\n" ) if $ENV{HARNESS_ACTIVE};
508
509 my( undef, $file, $line ) = $self->caller;
510 if( defined $name ) {
511 $self->diag(qq[ $msg test '$name'\n]);
512 $self->diag(qq[ at $file line $line.\n]);
513 }
514 else {
515 $self->diag(qq[ $msg test at $file line $line.\n]);
516 }
517 }
518
519 $self->is_passing(0) unless $test || $self->in_todo;
520
521 # Check that we haven't violated the plan
522 $self->_check_is_passing_plan();
523
524 return $test ? 1 : 0;
525 }
526
527
528 # Check that we haven't yet violated the plan and set
529 # is_passing() accordingly
530 sub _check_is_passing_plan {
531 my $self = shift;
532
533 my $plan = $self->has_plan;
534 return unless defined $plan; # no plan yet defined
535 return unless $plan !~ /\D/; # no numeric plan
536 $self->is_passing(0) if $plan < $self->{Curr_Test};
537 }
538
539
540 sub _unoverload {
541 my $self = shift;
542 my $type = shift;
543
544 $self->_try(sub { require overload; }, die_on_fail => 1);
545
546 foreach my $thing (@_) {
547 if( $self->_is_object($$thing) ) {
548 if( my $string_meth = overload::Method( $$thing, $type ) ) {
549 $$thing = $$thing->$string_meth();
550 }
551 }
552 }
553
554 return;
555 }
556
557 sub _is_object {
558 my( $self, $thing ) = @_;
559
560 return $self->_try( sub { ref $thing && $thing->isa('UNIVERSAL') } ) ? 1 : 0;
561 }
562
563 sub _unoverload_str {
564 my $self = shift;
565
566 return $self->_unoverload( q[""], @_ );
567 }
568
569 sub _unoverload_num {
570 my $self = shift;
571
572 $self->_unoverload( '0+', @_ );
573
574 for my $val (@_) {
575 next unless $self->_is_dualvar($$val);
576 $$val = $$val + 0;
577 }
578
579 return;
580 }
581
582 # This is a hack to detect a dualvar such as $!
583 sub _is_dualvar {
584 my( $self, $val ) = @_;
585
586 # Objects are not dualvars.
587 return 0 if ref $val;
588
589 no warnings 'numeric';
590 my $numval = $val + 0;
591 return $numval != 0 and $numval ne $val ? 1 : 0;
592 }
593
594 #line 876
595
596 sub is_eq {
597 my( $self, $got, $expect, $name ) = @_;
598 local $Level = $Level + 1;
599
600 $self->_unoverload_str( \$got, \$expect );
601
602 if( !defined $got || !defined $expect ) {
603 # undef only matches undef and nothing else
604 my $test = !defined $got && !defined $expect;
605
606 $self->ok( $test, $name );
607 $self->_is_diag( $got, 'eq', $expect ) unless $test;
608 return $test;
609 }
610
611 return $self->cmp_ok( $got, 'eq', $expect, $name );
612 }
613
614 sub is_num {
615 my( $self, $got, $expect, $name ) = @_;
616 local $Level = $Level + 1;
617
618 $self->_unoverload_num( \$got, \$expect );
619
620 if( !defined $got || !defined $expect ) {
621 # undef only matches undef and nothing else
622 my $test = !defined $got && !defined $expect;
623
624 $self->ok( $test, $name );
625 $self->_is_diag( $got, '==', $expect ) unless $test;
626 return $test;
627 }
628
629 return $self->cmp_ok( $got, '==', $expect, $name );
630 }
631
632 sub _diag_fmt {
633 my( $self, $type, $val ) = @_;
634
635 if( defined $$val ) {
636 if( $type eq 'eq' or $type eq 'ne' ) {
637 # quote and force string context
638 $$val = "'$$val'";
639 }
640 else {
641 # force numeric context
642 $self->_unoverload_num($val);
643 }
644 }
645 else {
646 $$val = 'undef';
647 }
648
649 return;
650 }
651
652 sub _is_diag {
653 my( $self, $got, $type, $expect ) = @_;
654
655 $self->_diag_fmt( $type, $_ ) for \$got, \$expect;
656
657 local $Level = $Level + 1;
658 return $self->diag(<<"DIAGNOSTIC");
659 got: $got
660 expected: $expect
661 DIAGNOSTIC
662
663 }
664
665 sub _isnt_diag {
666 my( $self, $got, $type ) = @_;
667
668 $self->_diag_fmt( $type, \$got );
669
670 local $Level = $Level + 1;
671 return $self->diag(<<"DIAGNOSTIC");
672 got: $got
673 expected: anything else
674 DIAGNOSTIC
675 }
676
677 #line 973
678
679 sub isnt_eq {
680 my( $self, $got, $dont_expect, $name ) = @_;
681 local $Level = $Level + 1;
682
683 if( !defined $got || !defined $dont_expect ) {
684 # undef only matches undef and nothing else
685 my $test = defined $got || defined $dont_expect;
686
687 $self->ok( $test, $name );
688 $self->_isnt_diag( $got, 'ne' ) unless $test;
689 return $test;
690 }
691
692 return $self->cmp_ok( $got, 'ne', $dont_expect, $name );
693 }
694
695 sub isnt_num {
696 my( $self, $got, $dont_expect, $name ) = @_;
697 local $Level = $Level + 1;
698
699 if( !defined $got || !defined $dont_expect ) {
700 # undef only matches undef and nothing else
701 my $test = defined $got || defined $dont_expect;
702
703 $self->ok( $test, $name );
704 $self->_isnt_diag( $got, '!=' ) unless $test;
705 return $test;
706 }
707
708 return $self->cmp_ok( $got, '!=', $dont_expect, $name );
709 }
710
711 #line 1022
712
713 sub like {
714 my( $self, $this, $regex, $name ) = @_;
715
716 local $Level = $Level + 1;
717 return $self->_regex_ok( $this, $regex, '=~', $name );
718 }
719
720 sub unlike {
721 my( $self, $this, $regex, $name ) = @_;
722
723 local $Level = $Level + 1;
724 return $self->_regex_ok( $this, $regex, '!~', $name );
725 }
726
727 #line 1046
728
729 my %numeric_cmps = map { ( $_, 1 ) } ( "<", "<=", ">", ">=", "==", "!=", "<=>" );
730
731 sub cmp_ok {
732 my( $self, $got, $type, $expect, $name ) = @_;
733
734 my $test;
735 my $error;
736 {
737 ## no critic (BuiltinFunctions::ProhibitStringyEval)
738
739 local( $@, $!, $SIG{__DIE__} ); # isolate eval
740
741 my($pack, $file, $line) = $self->caller();
742
743 $test = eval qq[
744 #line 1 "cmp_ok [from $file line $line]"
745 \$got $type \$expect;
746 ];
747 $error = $@;
748 }
749 local $Level = $Level + 1;
750 my $ok = $self->ok( $test, $name );
751
752 # Treat overloaded objects as numbers if we're asked to do a
753 # numeric comparison.
754 my $unoverload
755 = $numeric_cmps{$type}
756 ? '_unoverload_num'
757 : '_unoverload_str';
758
759 $self->diag(<<"END") if $error;
760 An error occurred while using $type:
761 ------------------------------------
762 $error
763 ------------------------------------
764 END
765
766 unless($ok) {
767 $self->$unoverload( \$got, \$expect );
768
769 if( $type =~ /^(eq|==)$/ ) {
770 $self->_is_diag( $got, $type, $expect );
771 }
772 elsif( $type =~ /^(ne|!=)$/ ) {
773 $self->_isnt_diag( $got, $type );
774 }
775 else {
776 $self->_cmp_diag( $got, $type, $expect );
777 }
778 }
779 return $ok;
780 }
781
782 sub _cmp_diag {
783 my( $self, $got, $type, $expect ) = @_;
784
785 $got = defined $got ? "'$got'" : 'undef';
786 $expect = defined $expect ? "'$expect'" : 'undef';
787
788 local $Level = $Level + 1;
789 return $self->diag(<<"DIAGNOSTIC");
790 $got
791 $type
792 $expect
793 DIAGNOSTIC
794 }
795
796 sub _caller_context {
797 my $self = shift;
798
799 my( $pack, $file, $line ) = $self->caller(1);
800
801 my $code = '';
802 $code .= "#line $line $file\n" if defined $file and defined $line;
803
804 return $code;
805 }
806
807 #line 1145
808
809 sub BAIL_OUT {
810 my( $self, $reason ) = @_;
811
812 $self->{Bailed_Out} = 1;
813 $self->_print("Bail out! $reason");
814 exit 255;
815 }
816
817 #line 1158
818
819 {
820 no warnings 'once';
821 *BAILOUT = \&BAIL_OUT;
822 }
823
824 #line 1172
825
826 sub skip {
827 my( $self, $why ) = @_;
828 $why ||= '';
829 $self->_unoverload_str( \$why );
830
831 lock( $self->{Curr_Test} );
832 $self->{Curr_Test}++;
833
834 $self->{Test_Results}[ $self->{Curr_Test} - 1 ] = &share(
835 {
836 'ok' => 1,
837 actual_ok => 1,
838 name => '',
839 type => 'skip',
840 reason => $why,
841 }
842 );
843
844 my $out = "ok";
845 $out .= " $self->{Curr_Test}" if $self->use_numbers;
846 $out .= " # skip";
847 $out .= " $why" if length $why;
848 $out .= "\n";
849
850 $self->_print($out);
851
852 return 1;
853 }
854
855 #line 1213
856
857 sub todo_skip {
858 my( $self, $why ) = @_;
859 $why ||= '';
860
861 lock( $self->{Curr_Test} );
862 $self->{Curr_Test}++;
863
864 $self->{Test_Results}[ $self->{Curr_Test} - 1 ] = &share(
865 {
866 'ok' => 1,
867 actual_ok => 0,
868 name => '',
869 type => 'todo_skip',
870 reason => $why,
871 }
872 );
873
874 my $out = "not ok";
875 $out .= " $self->{Curr_Test}" if $self->use_numbers;
876 $out .= " # TODO & SKIP $why\n";
877
878 $self->_print($out);
879
880 return 1;
881 }
882
883 #line 1293
884
885 sub maybe_regex {
886 my( $self, $regex ) = @_;
887 my $usable_regex = undef;
888
889 return $usable_regex unless defined $regex;
890
891 my( $re, $opts );
892
893 # Check for qr/foo/
894 if( _is_qr($regex) ) {
895 $usable_regex = $regex;
896 }
897 # Check for '/foo/' or 'm,foo,'
898 elsif(( $re, $opts ) = $regex =~ m{^ /(.*)/ (\w*) $ }sx or
899 ( undef, $re, $opts ) = $regex =~ m,^ m([^\w\s]) (.+) \1 (\w*) $,sx
900 )
901 {
902 $usable_regex = length $opts ? "(?$opts)$re" : $re;
903 }
904
905 return $usable_regex;
906 }
907
908 sub _is_qr {
909 my $regex = shift;
910
911 # is_regexp() checks for regexes in a robust manner, say if they're
912 # blessed.
913 return re::is_regexp($regex) if defined &re::is_regexp;
914 return ref $regex eq 'Regexp';
915 }
916
917 sub _regex_ok {
918 my( $self, $this, $regex, $cmp, $name ) = @_;
919
920 my $ok = 0;
921 my $usable_regex = $self->maybe_regex($regex);
922 unless( defined $usable_regex ) {
923 local $Level = $Level + 1;
924 $ok = $self->ok( 0, $name );
925 $self->diag(" '$regex' doesn't look much like a regex to me.");
926 return $ok;
927 }
928
929 {
930 ## no critic (BuiltinFunctions::ProhibitStringyEval)
931
932 my $test;
933 my $context = $self->_caller_context;
934
935 local( $@, $!, $SIG{__DIE__} ); # isolate eval
936
937 $test = eval $context . q{$test = $this =~ /$usable_regex/ ? 1 : 0};
938
939 $test = !$test if $cmp eq '!~';
940
941 local $Level = $Level + 1;
942 $ok = $self->ok( $test, $name );
943 }
944
945 unless($ok) {
946 $this = defined $this ? "'$this'" : 'undef';
947 my $match = $cmp eq '=~' ? "doesn't match" : "matches";
948
949 local $Level = $Level + 1;
950 $self->diag( sprintf <<'DIAGNOSTIC', $this, $match, $regex );
951 %s
952 %13s '%s'
953 DIAGNOSTIC
954
955 }
956
957 return $ok;
958 }
959
960 # I'm not ready to publish this. It doesn't deal with array return
961 # values from the code or context.
962
963 #line 1389
964
965 sub _try {
966 my( $self, $code, %opts ) = @_;
967
968 my $error;
969 my $return;
970 {
971 local $!; # eval can mess up $!
972 local $@; # don't set $@ in the test
973 local $SIG{__DIE__}; # don't trip an outside DIE handler.
974 $return = eval { $code->() };
975 $error = $@;
976 }
977
978 die $error if $error and $opts{die_on_fail};
979
980 return wantarray ? ( $return, $error ) : $return;
981 }
982
983 #line 1418
984
985 sub is_fh {
986 my $self = shift;
987 my $maybe_fh = shift;
988 return 0 unless defined $maybe_fh;
989
990 return 1 if ref $maybe_fh eq 'GLOB'; # its a glob ref
991 return 1 if ref \$maybe_fh eq 'GLOB'; # its a glob
992
993 return eval { $maybe_fh->isa("IO::Handle") } ||
994 eval { tied($maybe_fh)->can('TIEHANDLE') };
995 }
996
997 #line 1461
998
999 sub level {
1000 my( $self, $level ) = @_;
1001
1002 if( defined $level ) {
1003 $Level = $level;
1004 }
1005 return $Level;
1006 }
1007
1008 #line 1493
1009
1010 sub use_numbers {
1011 my( $self, $use_nums ) = @_;
1012
1013 if( defined $use_nums ) {
1014 $self->{Use_Nums} = $use_nums;
1015 }
1016 return $self->{Use_Nums};
1017 }
1018
1019 #line 1526
1020
1021 foreach my $attribute (qw(No_Header No_Ending No_Diag)) {
1022 my $method = lc $attribute;
1023
1024 my $code = sub {
1025 my( $self, $no ) = @_;
1026
1027 if( defined $no ) {
1028 $self->{$attribute} = $no;
1029 }
1030 return $self->{$attribute};
1031 };
1032
1033 no strict 'refs'; ## no critic
1034 *{ __PACKAGE__ . '::' . $method } = $code;
1035 }
1036
1037 #line 1579
1038
1039 sub diag {
1040 my $self = shift;
1041
1042 $self->_print_comment( $self->_diag_fh, @_ );
1043 }
1044
1045 #line 1594
1046
1047 sub note {
1048 my $self = shift;
1049
1050 $self->_print_comment( $self->output, @_ );
1051 }
1052
1053 sub _diag_fh {
1054 my $self = shift;
1055
1056 local $Level = $Level + 1;
1057 return $self->in_todo ? $self->todo_output : $self->failure_output;
1058 }
1059
1060 sub _print_comment {
1061 my( $self, $fh, @msgs ) = @_;
1062
1063 return if $self->no_diag;
1064 return unless @msgs;
1065
1066 # Prevent printing headers when compiling (i.e. -c)
1067 return if $^C;
1068
1069 # Smash args together like print does.
1070 # Convert undef to 'undef' so its readable.
1071 my $msg = join '', map { defined($_) ? $_ : 'undef' } @msgs;
1072
1073 # Escape the beginning, _print will take care of the rest.
1074 $msg =~ s/^/# /;
1075
1076 local $Level = $Level + 1;
1077 $self->_print_to_fh( $fh, $msg );
1078
1079 return 0;
1080 }
1081
1082 #line 1644
1083
1084 sub explain {
1085 my $self = shift;
1086
1087 return map {
1088 ref $_
1089 ? do {
1090 $self->_try(sub { require Data::Dumper }, die_on_fail => 1);
1091
1092 my $dumper = Data::Dumper->new( [$_] );
1093 $dumper->Indent(1)->Terse(1);
1094 $dumper->Sortkeys(1) if $dumper->can("Sortkeys");
1095 $dumper->Dump;
1096 }
1097 : $_
1098 } @_;
1099 }
1100
1101 #line 1673
1102
1103 sub _print {
1104 my $self = shift;
1105 return $self->_print_to_fh( $self->output, @_ );
1106 }
1107
1108 sub _print_to_fh {
1109 my( $self, $fh, @msgs ) = @_;
1110
1111 # Prevent printing headers when only compiling. Mostly for when
1112 # tests are deparsed with B::Deparse
1113 return if $^C;
1114
1115 my $msg = join '', @msgs;
1116
1117 local( $\, $", $, ) = ( undef, ' ', '' );
1118
1119 # Escape each line after the first with a # so we don't
1120 # confuse Test::Harness.
1121 $msg =~ s{\n(?!\z)}{\n# }sg;
1122
1123 # Stick a newline on the end if it needs it.
1124 $msg .= "\n" unless $msg =~ /\n\z/;
1125
1126 return print $fh $self->_indent, $msg;
1127 }
1128
1129 #line 1732
1130
1131 sub output {
1132 my( $self, $fh ) = @_;
1133
1134 if( defined $fh ) {
1135 $self->{Out_FH} = $self->_new_fh($fh);
1136 }
1137 return $self->{Out_FH};
1138 }
1139
1140 sub failure_output {
1141 my( $self, $fh ) = @_;
1142
1143 if( defined $fh ) {
1144 $self->{Fail_FH} = $self->_new_fh($fh);
1145 }
1146 return $self->{Fail_FH};
1147 }
1148
1149 sub todo_output {
1150 my( $self, $fh ) = @_;
1151
1152 if( defined $fh ) {
1153 $self->{Todo_FH} = $self->_new_fh($fh);
1154 }
1155 return $self->{Todo_FH};
1156 }
1157
1158 sub _new_fh {
1159 my $self = shift;
1160 my($file_or_fh) = shift;
1161
1162 my $fh;
1163 if( $self->is_fh($file_or_fh) ) {
1164 $fh = $file_or_fh;
1165 }
1166 elsif( ref $file_or_fh eq 'SCALAR' ) {
1167 # Scalar refs as filehandles was added in 5.8.
1168 if( $] >= 5.008 ) {
1169 open $fh, ">>", $file_or_fh
1170 or $self->croak("Can't open scalar ref $file_or_fh: $!");
1171 }
1172 # Emulate scalar ref filehandles with a tie.
1173 else {
1174 $fh = Test::Builder::IO::Scalar->new($file_or_fh)
1175 or $self->croak("Can't tie scalar ref $file_or_fh");
1176 }
1177 }
1178 else {
1179 open $fh, ">", $file_or_fh
1180 or $self->croak("Can't open test output log $file_or_fh: $!");
1181 _autoflush($fh);
1182 }
1183
1184 return $fh;
1185 }
1186
1187 sub _autoflush {
1188 my($fh) = shift;
1189 my $old_fh = select $fh;
1190 $| = 1;
1191 select $old_fh;
1192
1193 return;
1194 }
1195
1196 my( $Testout, $Testerr );
1197
1198 sub _dup_stdhandles {
1199 my $self = shift;
1200
1201 $self->_open_testhandles;
1202
1203 # Set everything to unbuffered else plain prints to STDOUT will
1204 # come out in the wrong order from our own prints.
1205 _autoflush($Testout);
1206 _autoflush( \*STDOUT );
1207 _autoflush($Testerr);
1208 _autoflush( \*STDERR );
1209
1210 $self->reset_outputs;
1211
1212 return;
1213 }
1214
1215 sub _open_testhandles {
1216 my $self = shift;
1217
1218 return if $self->{Opened_Testhandles};
1219
1220 # We dup STDOUT and STDERR so people can change them in their
1221 # test suites while still getting normal test output.
1222 open( $Testout, ">&STDOUT" ) or die "Can't dup STDOUT: $!";
1223 open( $Testerr, ">&STDERR" ) or die "Can't dup STDERR: $!";
1224
1225 # $self->_copy_io_layers( \*STDOUT, $Testout );
1226 # $self->_copy_io_layers( \*STDERR, $Testerr );
1227
1228 $self->{Opened_Testhandles} = 1;
1229
1230 return;
1231 }
1232
1233 sub _copy_io_layers {
1234 my( $self, $src, $dst ) = @_;
1235
1236 $self->_try(
1237 sub {
1238 require PerlIO;
1239 my @src_layers = PerlIO::get_layers($src);
1240
1241 binmode $dst, join " ", map ":$_", @src_layers if @src_layers;
1242 }
1243 );
1244
1245 return;
1246 }
1247
1248 #line 1857
1249
1250 sub reset_outputs {
1251 my $self = shift;
1252
1253 $self->output ($Testout);
1254 $self->failure_output($Testerr);
1255 $self->todo_output ($Testout);
1256
1257 return;
1258 }
1259
1260 #line 1883
1261
1262 sub _message_at_caller {
1263 my $self = shift;
1264
1265 local $Level = $Level + 1;
1266 my( $pack, $file, $line ) = $self->caller;
1267 return join( "", @_ ) . " at $file line $line.\n";
1268 }
1269
1270 sub carp {
1271 my $self = shift;
1272 return warn $self->_message_at_caller(@_);
1273 }
1274
1275 sub croak {
1276 my $self = shift;
1277 return die $self->_message_at_caller(@_);
1278 }
1279
1280
1281 #line 1923
1282
1283 sub current_test {
1284 my( $self, $num ) = @_;
1285
1286 lock( $self->{Curr_Test} );
1287 if( defined $num ) {
1288 $self->{Curr_Test} = $num;
1289
1290 # If the test counter is being pushed forward fill in the details.
1291 my $test_results = $self->{Test_Results};
1292 if( $num > @$test_results ) {
1293 my $start = @$test_results ? @$test_results : 0;
1294 for( $start .. $num - 1 ) {
1295 $test_results->[$_] = &share(
1296 {
1297 'ok' => 1,
1298 actual_ok => undef,
1299 reason => 'incrementing test number',
1300 type => 'unknown',
1301 name => undef
1302 }
1303 );
1304 }
1305 }
1306 # If backward, wipe history. Its their funeral.
1307 elsif( $num < @$test_results ) {
1308 $#{$test_results} = $num - 1;
1309 }
1310 }
1311 return $self->{Curr_Test};
1312 }
1313
1314 #line 1971
1315
1316 sub is_passing {
1317 my $self = shift;
1318
1319 if( @_ ) {
1320 $self->{Is_Passing} = shift;
1321 }
1322
1323 return $self->{Is_Passing};
1324 }
1325
1326
1327 #line 1993
1328
1329 sub summary {
1330 my($self) = shift;
1331
1332 return map { $_->{'ok'} } @{ $self->{Test_Results} };
1333 }
1334
1335 #line 2048
1336
1337 sub details {
1338 my $self = shift;
1339 return @{ $self->{Test_Results} };
1340 }
1341
1342 #line 2077
1343
1344 sub todo {
1345 my( $self, $pack ) = @_;
1346
1347 return $self->{Todo} if defined $self->{Todo};
1348
1349 local $Level = $Level + 1;
1350 my $todo = $self->find_TODO($pack);
1351 return $todo if defined $todo;
1352
1353 return '';
1354 }
1355
1356 #line 2099
1357
1358 sub find_TODO {
1359 my( $self, $pack ) = @_;
1360
1361 $pack = $pack || $self->caller(1) || $self->exported_to;
1362 return unless $pack;
1363
1364 no strict 'refs'; ## no critic
1365 return ${ $pack . '::TODO' };
1366 }
1367
1368 #line 2117
1369
1370 sub in_todo {
1371 my $self = shift;
1372
1373 local $Level = $Level + 1;
1374 return( defined $self->{Todo} || $self->find_TODO ) ? 1 : 0;
1375 }
1376
1377 #line 2167
1378
1379 sub todo_start {
1380 my $self = shift;
1381 my $message = @_ ? shift : '';
1382
1383 $self->{Start_Todo}++;
1384 if( $self->in_todo ) {
1385 push @{ $self->{Todo_Stack} } => $self->todo;
1386 }
1387 $self->{Todo} = $message;
1388
1389 return;
1390 }
1391
1392 #line 2189
1393
1394 sub todo_end {
1395 my $self = shift;
1396
1397 if( !$self->{Start_Todo} ) {
1398 $self->croak('todo_end() called without todo_start()');
1399 }
1400
1401 $self->{Start_Todo}--;
1402
1403 if( $self->{Start_Todo} && @{ $self->{Todo_Stack} } ) {
1404 $self->{Todo} = pop @{ $self->{Todo_Stack} };
1405 }
1406 else {
1407 delete $self->{Todo};
1408 }
1409
1410 return;
1411 }
1412
1413 #line 2222
1414
1415 sub caller { ## no critic (Subroutines::ProhibitBuiltinHomonyms)
1416 my( $self, $height ) = @_;
1417 $height ||= 0;
1418
1419 my $level = $self->level + $height + 1;
1420 my @caller;
1421 do {
1422 @caller = CORE::caller( $level );
1423 $level--;
1424 } until @caller;
1425 return wantarray ? @caller : $caller[0];
1426 }
1427
1428 #line 2239
1429
1430 #line 2253
1431
1432 #'#
1433 sub _sanity_check {
1434 my $self = shift;
1435
1436 $self->_whoa( $self->{Curr_Test} < 0, 'Says here you ran a negative number of tests!' );
1437 $self->_whoa( $self->{Curr_Test} != @{ $self->{Test_Results} },
1438 'Somehow you got a different number of results than tests ran!' );
1439
1440 return;
1441 }
1442
1443 #line 2274
1444
1445 sub _whoa {
1446 my( $self, $check, $desc ) = @_;
1447 if($check) {
1448 local $Level = $Level + 1;
1449 $self->croak(<<"WHOA");
1450 WHOA! $desc
1451 This should never happen! Please contact the author immediately!
1452 WHOA
1453 }
1454
1455 return;
1456 }
1457
1458 #line 2298
1459
1460 sub _my_exit {
1461 $? = $_[0]; ## no critic (Variables::RequireLocalizedPunctuationVars)
1462
1463 return 1;
1464 }
1465
1466 #line 2310
1467
1468 sub _ending {
1469 my $self = shift;
1470 return if $self->no_ending;
1471 return if $self->{Ending}++;
1472
1473 my $real_exit_code = $?;
1474
1475 # Don't bother with an ending if this is a forked copy. Only the parent
1476 # should do the ending.
1477 if( $self->{Original_Pid} != $$ ) {
1478 return;
1479 }
1480
1481 # Ran tests but never declared a plan or hit done_testing
1482 if( !$self->{Have_Plan} and $self->{Curr_Test} ) {
1483 $self->is_passing(0);
1484 $self->diag("Tests were run but no plan was declared and done_testing() was not seen.");
1485 }
1486
1487 # Exit if plan() was never called. This is so "require Test::Simple"
1488 # doesn't puke.
1489 if( !$self->{Have_Plan} ) {
1490 return;
1491 }
1492
1493 # Don't do an ending if we bailed out.
1494 if( $self->{Bailed_Out} ) {
1495 $self->is_passing(0);
1496 return;
1497 }
1498 # Figure out if we passed or failed and print helpful messages.
1499 my $test_results = $self->{Test_Results};
1500 if(@$test_results) {
1501 # The plan? We have no plan.
1502 if( $self->{No_Plan} ) {
1503 $self->_output_plan($self->{Curr_Test}) unless $self->no_header;
1504 $self->{Expected_Tests} = $self->{Curr_Test};
1505 }
1506
1507 # Auto-extended arrays and elements which aren't explicitly
1508 # filled in with a shared reference will puke under 5.8.0
1509 # ithreads. So we have to fill them in by hand. :(
1510 my $empty_result = &share( {} );
1511 for my $idx ( 0 .. $self->{Expected_Tests} - 1 ) {
1512 $test_results->[$idx] = $empty_result
1513 unless defined $test_results->[$idx];
1514 }
1515
1516 my $num_failed = grep !$_->{'ok'}, @{$test_results}[ 0 .. $self->{Curr_Test} - 1 ];
1517
1518 my $num_extra = $self->{Curr_Test} - $self->{Expected_Tests};
1519
1520 if( $num_extra != 0 ) {
1521 my $s = $self->{Expected_Tests} == 1 ? '' : 's';
1522 $self->diag(<<"FAIL");
1523 Looks like you planned $self->{Expected_Tests} test$s but ran $self->{Curr_Test}.
1524 FAIL
1525 $self->is_passing(0);
1526 }
1527
1528 if($num_failed) {
1529 my $num_tests = $self->{Curr_Test};
1530 my $s = $num_failed == 1 ? '' : 's';
1531
1532 my $qualifier = $num_extra == 0 ? '' : ' run';
1533
1534 $self->diag(<<"FAIL");
1535 Looks like you failed $num_failed test$s of $num_tests$qualifier.
1536 FAIL
1537 $self->is_passing(0);
1538 }
1539
1540 if($real_exit_code) {
1541 $self->diag(<<"FAIL");
1542 Looks like your test exited with $real_exit_code just after $self->{Curr_Test}.
1543 FAIL
1544 $self->is_passing(0);
1545 _my_exit($real_exit_code) && return;
1546 }
1547
1548 my $exit_code;
1549 if($num_failed) {
1550 $exit_code = $num_failed <= 254 ? $num_failed : 254;
1551 }
1552 elsif( $num_extra != 0 ) {
1553 $exit_code = 255;
1554 }
1555 else {
1556 $exit_code = 0;
1557 }
1558
1559 _my_exit($exit_code) && return;
1560 }
1561 elsif( $self->{Skip_All} ) {
1562 _my_exit(0) && return;
1563 }
1564 elsif($real_exit_code) {
1565 $self->diag(<<"FAIL");
1566 Looks like your test exited with $real_exit_code before it could output anything.
1567 FAIL
1568 $self->is_passing(0);
1569 _my_exit($real_exit_code) && return;
1570 }
1571 else {
1572 $self->diag("No tests run!\n");
1573 $self->is_passing(0);
1574 _my_exit(255) && return;
1575 }
1576
1577 $self->is_passing(0);
1578 $self->_whoa( 1, "We fell off the end of _ending()" );
1579 }
1580
1581 END {
1582 $Test->_ending if defined $Test;
1583 }
1584
1585 #line 2498
1586
1587 1;
1588
0 #line 1
1 use strict;
2 use warnings;
3
4 package Test::Exception;
5 use Test::Builder;
6 use Sub::Uplevel qw( uplevel );
7 use base qw( Exporter );
8
9 our $VERSION = '0.29';
10 our @EXPORT = qw(dies_ok lives_ok throws_ok lives_and);
11
12 my $Tester = Test::Builder->new;
13
14 sub import {
15 my $self = shift;
16 if ( @_ ) {
17 my $package = caller;
18 $Tester->exported_to( $package );
19 $Tester->plan( @_ );
20 };
21 $self->export_to_level( 1, $self, $_ ) foreach @EXPORT;
22 }
23
24 #line 83
25
26 sub _quiet_caller (;$) { ## no critic Prototypes
27 my $height = $_[0];
28 $height++;
29 if( wantarray and !@_ ) {
30 return (CORE::caller($height))[0..2];
31 }
32 else {
33 return CORE::caller($height);
34 }
35 }
36
37 sub _try_as_caller {
38 my $coderef = shift;
39
40 # local works here because Sub::Uplevel has already overridden caller
41 local *CORE::GLOBAL::caller;
42 { no warnings 'redefine'; *CORE::GLOBAL::caller = \&_quiet_caller; }
43
44 eval { uplevel 3, $coderef };
45 return $@;
46 };
47
48
49 sub _is_exception {
50 my $exception = shift;
51 return ref $exception || $exception ne '';
52 };
53
54
55 sub _exception_as_string {
56 my ( $prefix, $exception ) = @_;
57 return "$prefix normal exit" unless _is_exception( $exception );
58 my $class = ref $exception;
59 $exception = "$class ($exception)"
60 if $class && "$exception" !~ m/^\Q$class/;
61 chomp $exception;
62 return "$prefix $exception";
63 };
64
65
66 #line 168
67
68
69 sub throws_ok (&$;$) {
70 my ( $coderef, $expecting, $description ) = @_;
71 unless (defined $expecting) {
72 require Carp;
73 Carp::croak( "throws_ok: must pass exception class/object or regex" );
74 }
75 $description = _exception_as_string( "threw", $expecting )
76 unless defined $description;
77 my $exception = _try_as_caller( $coderef );
78 my $regex = $Tester->maybe_regex( $expecting );
79 my $ok = $regex
80 ? ( $exception =~ m/$regex/ )
81 : eval {
82 $exception->isa( ref $expecting ? ref $expecting : $expecting )
83 };
84 $Tester->ok( $ok, $description );
85 unless ( $ok ) {
86 $Tester->diag( _exception_as_string( "expecting:", $expecting ) );
87 $Tester->diag( _exception_as_string( "found:", $exception ) );
88 };
89 $@ = $exception;
90 return $ok;
91 };
92
93
94 #line 216
95
96 sub dies_ok (&;$) {
97 my ( $coderef, $description ) = @_;
98 my $exception = _try_as_caller( $coderef );
99 my $ok = $Tester->ok( _is_exception($exception), $description );
100 $@ = $exception;
101 return $ok;
102 }
103
104
105 #line 255
106
107 sub lives_ok (&;$) {
108 my ( $coderef, $description ) = @_;
109 my $exception = _try_as_caller( $coderef );
110 my $ok = $Tester->ok( ! _is_exception( $exception ), $description );
111 $Tester->diag( _exception_as_string( "died:", $exception ) ) unless $ok;
112 $@ = $exception;
113 return $ok;
114 }
115
116
117 #line 295
118
119 sub lives_and (&;$) {
120 my ( $test, $description ) = @_;
121 {
122 local $Test::Builder::Level = $Test::Builder::Level + 1;
123 my $ok = \&Test::Builder::ok;
124 no warnings;
125 local *Test::Builder::ok = sub {
126 $_[2] = $description unless defined $_[2];
127 $ok->(@_);
128 };
129 use warnings;
130 eval { $test->() } and return 1;
131 };
132 my $exception = $@;
133 if ( _is_exception( $exception ) ) {
134 $Tester->ok( 0, $description );
135 $Tester->diag( _exception_as_string( "died:", $exception ) );
136 };
137 $@ = $exception;
138 return;
139 }
140
141 #line 462
142
143 1;
0 #line 1
1 package Test::More;
2
3 use 5.006;
4 use strict;
5 use warnings;
6
7 #---- perlcritic exemptions. ----#
8
9 # We use a lot of subroutine prototypes
10 ## no critic (Subroutines::ProhibitSubroutinePrototypes)
11
12 # Can't use Carp because it might cause use_ok() to accidentally succeed
13 # even though the module being used forgot to use Carp. Yes, this
14 # actually happened.
15 sub _carp {
16 my( $file, $line ) = ( caller(1) )[ 1, 2 ];
17 return warn @_, " at $file line $line\n";
18 }
19
20 our $VERSION = '0.94';
21 $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
22
23 use Test::Builder::Module;
24 our @ISA = qw(Test::Builder::Module);
25 our @EXPORT = qw(ok use_ok require_ok
26 is isnt like unlike is_deeply
27 cmp_ok
28 skip todo todo_skip
29 pass fail
30 eq_array eq_hash eq_set
31 $TODO
32 plan
33 done_testing
34 can_ok isa_ok new_ok
35 diag note explain
36 subtest
37 BAIL_OUT
38 );
39
40 #line 164
41
42 sub plan {
43 my $tb = Test::More->builder;
44
45 return $tb->plan(@_);
46 }
47
48 # This implements "use Test::More 'no_diag'" but the behavior is
49 # deprecated.
50 sub import_extra {
51 my $class = shift;
52 my $list = shift;
53
54 my @other = ();
55 my $idx = 0;
56 while( $idx <= $#{$list} ) {
57 my $item = $list->[$idx];
58
59 if( defined $item and $item eq 'no_diag' ) {
60 $class->builder->no_diag(1);
61 }
62 else {
63 push @other, $item;
64 }
65
66 $idx++;
67 }
68
69 @$list = @other;
70
71 return;
72 }
73
74 #line 217
75
76 sub done_testing {
77 my $tb = Test::More->builder;
78 $tb->done_testing(@_);
79 }
80
81 #line 289
82
83 sub ok ($;$) {
84 my( $test, $name ) = @_;
85 my $tb = Test::More->builder;
86
87 return $tb->ok( $test, $name );
88 }
89
90 #line 367
91
92 sub is ($$;$) {
93 my $tb = Test::More->builder;
94
95 return $tb->is_eq(@_);
96 }
97
98 sub isnt ($$;$) {
99 my $tb = Test::More->builder;
100
101 return $tb->isnt_eq(@_);
102 }
103
104 *isn't = \&isnt;
105
106 #line 411
107
108 sub like ($$;$) {
109 my $tb = Test::More->builder;
110
111 return $tb->like(@_);
112 }
113
114 #line 426
115
116 sub unlike ($$;$) {
117 my $tb = Test::More->builder;
118
119 return $tb->unlike(@_);
120 }
121
122 #line 471
123
124 sub cmp_ok($$$;$) {
125 my $tb = Test::More->builder;
126
127 return $tb->cmp_ok(@_);
128 }
129
130 #line 506
131
132 sub can_ok ($@) {
133 my( $proto, @methods ) = @_;
134 my $class = ref $proto || $proto;
135 my $tb = Test::More->builder;
136
137 unless($class) {
138 my $ok = $tb->ok( 0, "->can(...)" );
139 $tb->diag(' can_ok() called with empty class or reference');
140 return $ok;
141 }
142
143 unless(@methods) {
144 my $ok = $tb->ok( 0, "$class->can(...)" );
145 $tb->diag(' can_ok() called with no methods');
146 return $ok;
147 }
148
149 my @nok = ();
150 foreach my $method (@methods) {
151 $tb->_try( sub { $proto->can($method) } ) or push @nok, $method;
152 }
153
154 my $name = (@methods == 1) ? "$class->can('$methods[0]')" :
155 "$class->can(...)" ;
156
157 my $ok = $tb->ok( !@nok, $name );
158
159 $tb->diag( map " $class->can('$_') failed\n", @nok );
160
161 return $ok;
162 }
163
164 #line 572
165
166 sub isa_ok ($$;$) {
167 my( $object, $class, $obj_name ) = @_;
168 my $tb = Test::More->builder;
169
170 my $diag;
171
172 if( !defined $object ) {
173 $obj_name = 'The thing' unless defined $obj_name;
174 $diag = "$obj_name isn't defined";
175 }
176 else {
177 my $whatami = ref $object ? 'object' : 'class';
178 # We can't use UNIVERSAL::isa because we want to honor isa() overrides
179 my( $rslt, $error ) = $tb->_try( sub { $object->isa($class) } );
180 if($error) {
181 if( $error =~ /^Can't call method "isa" on unblessed reference/ ) {
182 # Its an unblessed reference
183 $obj_name = 'The reference' unless defined $obj_name;
184 if( !UNIVERSAL::isa( $object, $class ) ) {
185 my $ref = ref $object;
186 $diag = "$obj_name isn't a '$class' it's a '$ref'";
187 }
188 }
189 elsif( $error =~ /Can't call method "isa" without a package/ ) {
190 # It's something that can't even be a class
191 $obj_name = 'The thing' unless defined $obj_name;
192 $diag = "$obj_name isn't a class or reference";
193 }
194 else {
195 die <<WHOA;
196 WHOA! I tried to call ->isa on your $whatami and got some weird error.
197 Here's the error.
198 $error
199 WHOA
200 }
201 }
202 else {
203 $obj_name = "The $whatami" unless defined $obj_name;
204 if( !$rslt ) {
205 my $ref = ref $object;
206 $diag = "$obj_name isn't a '$class' it's a '$ref'";
207 }
208 }
209 }
210
211 my $name = "$obj_name isa $class";
212 my $ok;
213 if($diag) {
214 $ok = $tb->ok( 0, $name );
215 $tb->diag(" $diag\n");
216 }
217 else {
218 $ok = $tb->ok( 1, $name );
219 }
220
221 return $ok;
222 }
223
224 #line 651
225
226 sub new_ok {
227 my $tb = Test::More->builder;
228 $tb->croak("new_ok() must be given at least a class") unless @_;
229
230 my( $class, $args, $object_name ) = @_;
231
232 $args ||= [];
233 $object_name = "The object" unless defined $object_name;
234
235 my $obj;
236 my( $success, $error ) = $tb->_try( sub { $obj = $class->new(@$args); 1 } );
237 if($success) {
238 local $Test::Builder::Level = $Test::Builder::Level + 1;
239 isa_ok $obj, $class, $object_name;
240 }
241 else {
242 $tb->ok( 0, "new() died" );
243 $tb->diag(" Error was: $error");
244 }
245
246 return $obj;
247 }
248
249 #line 719
250
251 sub subtest($&) {
252 my ($name, $subtests) = @_;
253
254 my $tb = Test::More->builder;
255 return $tb->subtest(@_);
256 }
257
258 #line 743
259
260 sub pass (;$) {
261 my $tb = Test::More->builder;
262
263 return $tb->ok( 1, @_ );
264 }
265
266 sub fail (;$) {
267 my $tb = Test::More->builder;
268
269 return $tb->ok( 0, @_ );
270 }
271
272 #line 806
273
274 sub use_ok ($;@) {
275 my( $module, @imports ) = @_;
276 @imports = () unless @imports;
277 my $tb = Test::More->builder;
278
279 my( $pack, $filename, $line ) = caller;
280
281 my $code;
282 if( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) {
283 # probably a version check. Perl needs to see the bare number
284 # for it to work with non-Exporter based modules.
285 $code = <<USE;
286 package $pack;
287 use $module $imports[0];
288 1;
289 USE
290 }
291 else {
292 $code = <<USE;
293 package $pack;
294 use $module \@{\$args[0]};
295 1;
296 USE
297 }
298
299 my( $eval_result, $eval_error ) = _eval( $code, \@imports );
300 my $ok = $tb->ok( $eval_result, "use $module;" );
301
302 unless($ok) {
303 chomp $eval_error;
304 $@ =~ s{^BEGIN failed--compilation aborted at .*$}
305 {BEGIN failed--compilation aborted at $filename line $line.}m;
306 $tb->diag(<<DIAGNOSTIC);
307 Tried to use '$module'.
308 Error: $eval_error
309 DIAGNOSTIC
310
311 }
312
313 return $ok;
314 }
315
316 sub _eval {
317 my( $code, @args ) = @_;
318
319 # Work around oddities surrounding resetting of $@ by immediately
320 # storing it.
321 my( $sigdie, $eval_result, $eval_error );
322 {
323 local( $@, $!, $SIG{__DIE__} ); # isolate eval
324 $eval_result = eval $code; ## no critic (BuiltinFunctions::ProhibitStringyEval)
325 $eval_error = $@;
326 $sigdie = $SIG{__DIE__} || undef;
327 }
328 # make sure that $code got a chance to set $SIG{__DIE__}
329 $SIG{__DIE__} = $sigdie if defined $sigdie;
330
331 return( $eval_result, $eval_error );
332 }
333
334 #line 875
335
336 sub require_ok ($) {
337 my($module) = shift;
338 my $tb = Test::More->builder;
339
340 my $pack = caller;
341
342 # Try to deterine if we've been given a module name or file.
343 # Module names must be barewords, files not.
344 $module = qq['$module'] unless _is_module_name($module);
345
346 my $code = <<REQUIRE;
347 package $pack;
348 require $module;
349 1;
350 REQUIRE
351
352 my( $eval_result, $eval_error ) = _eval($code);
353 my $ok = $tb->ok( $eval_result, "require $module;" );
354
355 unless($ok) {
356 chomp $eval_error;
357 $tb->diag(<<DIAGNOSTIC);
358 Tried to require '$module'.
359 Error: $eval_error
360 DIAGNOSTIC
361
362 }
363
364 return $ok;
365 }
366
367 sub _is_module_name {
368 my $module = shift;
369
370 # Module names start with a letter.
371 # End with an alphanumeric.
372 # The rest is an alphanumeric or ::
373 $module =~ s/\b::\b//g;
374
375 return $module =~ /^[a-zA-Z]\w*$/ ? 1 : 0;
376 }
377
378 #line 952
379
380 our( @Data_Stack, %Refs_Seen );
381 my $DNE = bless [], 'Does::Not::Exist';
382
383 sub _dne {
384 return ref $_[0] eq ref $DNE;
385 }
386
387 ## no critic (Subroutines::RequireArgUnpacking)
388 sub is_deeply {
389 my $tb = Test::More->builder;
390
391 unless( @_ == 2 or @_ == 3 ) {
392 my $msg = <<'WARNING';
393 is_deeply() takes two or three args, you gave %d.
394 This usually means you passed an array or hash instead
395 of a reference to it
396 WARNING
397 chop $msg; # clip off newline so carp() will put in line/file
398
399 _carp sprintf $msg, scalar @_;
400
401 return $tb->ok(0);
402 }
403
404 my( $got, $expected, $name ) = @_;
405
406 $tb->_unoverload_str( \$expected, \$got );
407
408 my $ok;
409 if( !ref $got and !ref $expected ) { # neither is a reference
410 $ok = $tb->is_eq( $got, $expected, $name );
411 }
412 elsif( !ref $got xor !ref $expected ) { # one's a reference, one isn't
413 $ok = $tb->ok( 0, $name );
414 $tb->diag( _format_stack({ vals => [ $got, $expected ] }) );
415 }
416 else { # both references
417 local @Data_Stack = ();
418 if( _deep_check( $got, $expected ) ) {
419 $ok = $tb->ok( 1, $name );
420 }
421 else {
422 $ok = $tb->ok( 0, $name );
423 $tb->diag( _format_stack(@Data_Stack) );
424 }
425 }
426
427 return $ok;
428 }
429
430 sub _format_stack {
431 my(@Stack) = @_;
432
433 my $var = '$FOO';
434 my $did_arrow = 0;
435 foreach my $entry (@Stack) {
436 my $type = $entry->{type} || '';
437 my $idx = $entry->{'idx'};
438 if( $type eq 'HASH' ) {
439 $var .= "->" unless $did_arrow++;
440 $var .= "{$idx}";
441 }
442 elsif( $type eq 'ARRAY' ) {
443 $var .= "->" unless $did_arrow++;
444 $var .= "[$idx]";
445 }
446 elsif( $type eq 'REF' ) {
447 $var = "\${$var}";
448 }
449 }
450
451 my @vals = @{ $Stack[-1]{vals} }[ 0, 1 ];
452 my @vars = ();
453 ( $vars[0] = $var ) =~ s/\$FOO/ \$got/;
454 ( $vars[1] = $var ) =~ s/\$FOO/\$expected/;
455
456 my $out = "Structures begin differing at:\n";
457 foreach my $idx ( 0 .. $#vals ) {
458 my $val = $vals[$idx];
459 $vals[$idx]
460 = !defined $val ? 'undef'
461 : _dne($val) ? "Does not exist"
462 : ref $val ? "$val"
463 : "'$val'";
464 }
465
466 $out .= "$vars[0] = $vals[0]\n";
467 $out .= "$vars[1] = $vals[1]\n";
468
469 $out =~ s/^/ /msg;
470 return $out;
471 }
472
473 sub _type {
474 my $thing = shift;
475
476 return '' if !ref $thing;
477
478 for my $type (qw(ARRAY HASH REF SCALAR GLOB CODE Regexp)) {
479 return $type if UNIVERSAL::isa( $thing, $type );
480 }
481
482 return '';
483 }
484
485 #line 1112
486
487 sub diag {
488 return Test::More->builder->diag(@_);
489 }
490
491 sub note {
492 return Test::More->builder->note(@_);
493 }
494
495 #line 1138
496
497 sub explain {
498 return Test::More->builder->explain(@_);
499 }
500
501 #line 1204
502
503 ## no critic (Subroutines::RequireFinalReturn)
504 sub skip {
505 my( $why, $how_many ) = @_;
506 my $tb = Test::More->builder;
507
508 unless( defined $how_many ) {
509 # $how_many can only be avoided when no_plan is in use.
510 _carp "skip() needs to know \$how_many tests are in the block"
511 unless $tb->has_plan eq 'no_plan';
512 $how_many = 1;
513 }
514
515 if( defined $how_many and $how_many =~ /\D/ ) {
516 _carp
517 "skip() was passed a non-numeric number of tests. Did you get the arguments backwards?";
518 $how_many = 1;
519 }
520
521 for( 1 .. $how_many ) {
522 $tb->skip($why);
523 }
524
525 no warnings 'exiting';
526 last SKIP;
527 }
528
529 #line 1288
530
531 sub todo_skip {
532 my( $why, $how_many ) = @_;
533 my $tb = Test::More->builder;
534
535 unless( defined $how_many ) {
536 # $how_many can only be avoided when no_plan is in use.
537 _carp "todo_skip() needs to know \$how_many tests are in the block"
538 unless $tb->has_plan eq 'no_plan';
539 $how_many = 1;
540 }
541
542 for( 1 .. $how_many ) {
543 $tb->todo_skip($why);
544 }
545
546 no warnings 'exiting';
547 last TODO;
548 }
549
550 #line 1343
551
552 sub BAIL_OUT {
553 my $reason = shift;
554 my $tb = Test::More->builder;
555
556 $tb->BAIL_OUT($reason);
557 }
558
559 #line 1382
560
561 #'#
562 sub eq_array {
563 local @Data_Stack = ();
564 _deep_check(@_);
565 }
566
567 sub _eq_array {
568 my( $a1, $a2 ) = @_;
569
570 if( grep _type($_) ne 'ARRAY', $a1, $a2 ) {
571 warn "eq_array passed a non-array ref";
572 return 0;
573 }
574
575 return 1 if $a1 eq $a2;
576
577 my $ok = 1;
578 my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2;
579 for( 0 .. $max ) {
580 my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_];
581 my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_];
582
583 push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [ $e1, $e2 ] };
584 $ok = _deep_check( $e1, $e2 );
585 pop @Data_Stack if $ok;
586
587 last unless $ok;
588 }
589
590 return $ok;
591 }
592
593 sub _deep_check {
594 my( $e1, $e2 ) = @_;
595 my $tb = Test::More->builder;
596
597 my $ok = 0;
598
599 # Effectively turn %Refs_Seen into a stack. This avoids picking up
600 # the same referenced used twice (such as [\$a, \$a]) to be considered
601 # circular.
602 local %Refs_Seen = %Refs_Seen;
603
604 {
605 # Quiet uninitialized value warnings when comparing undefs.
606 no warnings 'uninitialized';
607
608 $tb->_unoverload_str( \$e1, \$e2 );
609
610 # Either they're both references or both not.
611 my $same_ref = !( !ref $e1 xor !ref $e2 );
612 my $not_ref = ( !ref $e1 and !ref $e2 );
613
614 if( defined $e1 xor defined $e2 ) {
615 $ok = 0;
616 }
617 elsif( !defined $e1 and !defined $e2 ) {
618 # Shortcut if they're both defined.
619 $ok = 1;
620 }
621 elsif( _dne($e1) xor _dne($e2) ) {
622 $ok = 0;
623 }
624 elsif( $same_ref and( $e1 eq $e2 ) ) {
625 $ok = 1;
626 }
627 elsif($not_ref) {
628 push @Data_Stack, { type => '', vals => [ $e1, $e2 ] };
629 $ok = 0;
630 }
631 else {
632 if( $Refs_Seen{$e1} ) {
633 return $Refs_Seen{$e1} eq $e2;
634 }
635 else {
636 $Refs_Seen{$e1} = "$e2";
637 }
638
639 my $type = _type($e1);
640 $type = 'DIFFERENT' unless _type($e2) eq $type;
641
642 if( $type eq 'DIFFERENT' ) {
643 push @Data_Stack, { type => $type, vals => [ $e1, $e2 ] };
644 $ok = 0;
645 }
646 elsif( $type eq 'ARRAY' ) {
647 $ok = _eq_array( $e1, $e2 );
648 }
649 elsif( $type eq 'HASH' ) {
650 $ok = _eq_hash( $e1, $e2 );
651 }
652 elsif( $type eq 'REF' ) {
653 push @Data_Stack, { type => $type, vals => [ $e1, $e2 ] };
654 $ok = _deep_check( $$e1, $$e2 );
655 pop @Data_Stack if $ok;
656 }
657 elsif( $type eq 'SCALAR' ) {
658 push @Data_Stack, { type => 'REF', vals => [ $e1, $e2 ] };
659 $ok = _deep_check( $$e1, $$e2 );
660 pop @Data_Stack if $ok;
661 }
662 elsif($type) {
663 push @Data_Stack, { type => $type, vals => [ $e1, $e2 ] };
664 $ok = 0;
665 }
666 else {
667 _whoa( 1, "No type in _deep_check" );
668 }
669 }
670 }
671
672 return $ok;
673 }
674
675 sub _whoa {
676 my( $check, $desc ) = @_;
677 if($check) {
678 die <<"WHOA";
679 WHOA! $desc
680 This should never happen! Please contact the author immediately!
681 WHOA
682 }
683 }
684
685 #line 1515
686
687 sub eq_hash {
688 local @Data_Stack = ();
689 return _deep_check(@_);
690 }
691
692 sub _eq_hash {
693 my( $a1, $a2 ) = @_;
694
695 if( grep _type($_) ne 'HASH', $a1, $a2 ) {
696 warn "eq_hash passed a non-hash ref";
697 return 0;
698 }
699
700 return 1 if $a1 eq $a2;
701
702 my $ok = 1;
703 my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2;
704 foreach my $k ( keys %$bigger ) {
705 my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE;
706 my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE;
707
708 push @Data_Stack, { type => 'HASH', idx => $k, vals => [ $e1, $e2 ] };
709 $ok = _deep_check( $e1, $e2 );
710 pop @Data_Stack if $ok;
711
712 last unless $ok;
713 }
714
715 return $ok;
716 }
717
718 #line 1572
719
720 sub eq_set {
721 my( $a1, $a2 ) = @_;
722 return 0 unless @$a1 == @$a2;
723
724 no warnings 'uninitialized';
725
726 # It really doesn't matter how we sort them, as long as both arrays are
727 # sorted with the same algorithm.
728 #
729 # Ensure that references are not accidentally treated the same as a
730 # string containing the reference.
731 #
732 # Have to inline the sort routine due to a threading/sort bug.
733 # See [rt.cpan.org 6782]
734 #
735 # I don't know how references would be sorted so we just don't sort
736 # them. This means eq_set doesn't really work with refs.
737 return eq_array(
738 [ grep( ref, @$a1 ), sort( grep( !ref, @$a1 ) ) ],
739 [ grep( ref, @$a2 ), sort( grep( !ref, @$a2 ) ) ],
740 );
741 }
742
743 #line 1774
744
745 1;
0 # $Id: CBC.pm 1829 2005-05-25 21:51:40Z btrott $
1
20 package Convert::PEM::CBC;
31 use strict;
42
114112 Passphrase => 'foo'
115113 );
116114
115 my $plaintext = 'foo bar baz';
117116 $cbc->encrypt($plaintext);
118117
119118 =head1 DESCRIPTION
0 # $Id: PEM.pm 1829 2005-05-25 21:51:40Z btrott $
1
20 package Convert::PEM;
31 use strict;
2 use 5.008_001;
3
44 use base qw( Class::ErrorHandler );
55
66 use MIME::Base64;
1010 use Convert::PEM::CBC;
1111
1212 use vars qw( $VERSION );
13 $VERSION = '0.07';
13 $VERSION = '0.08';
1414
1515 sub new {
1616 my $class = shift;
134134 sub explode {
135135 my $pem = shift;
136136 my($message) = @_;
137
138 # Canonicalize line endings into "\n".
139 $message =~ s/\r\n|\n|\r/\n/g;
140
137141 my($head, $object, $headers, $content, $tail) = $message =~
138142 m:(-----BEGIN ([^\n\-]+)-----)\n(.*?\n\n)?(.+)(-----END .*?-----)$:s;
139143 my $buf = decode_base64($content);
224228 }
225229 ));
226230
231 my $keyfile = 'private-key.pem';
232 my $pwd = 'foobar';
233
227234 my $pkey = $pem->read(
228235 Filename => $keyfile,
229236 Password => $pwd
459466 my $obj = $pem->read( Filename => "encrypted.pem" )
460467 or die "Decryption failed: ", $pem->errstr;
461468
469 =head1 LICENSE
470
471 Convert::PEM is free software; you may redistribute it and/or modify
472 it under the same terms as Perl itself.
473
462474 =head1 AUTHOR & COPYRIGHTS
463475
464 Benjamin Trott, ben@rhumba.pair.com
465
466 Except where otherwise noted, Convert::PEM is Copyright 2001
467 Benjamin Trott. All rights reserved. Convert::PEM is free
468 software; you may redistribute it and/or modify it under
469 the same terms as Perl itself.
476 Except where otherwise noted, Convert::PEM is Copyright Benjamin
477 Trott, cpan@stupidfool.org. All rights reserved.
470478
471479 =cut
0 # $Id: 00-compile.t 85 2001-04-22 07:22:42Z btrott $
0 use strict;
1 use Test::More tests => 1;
12
2 my $loaded;
3 BEGIN { print "1..1\n" }
4 use Convert::PEM;
5 $loaded++;
6 print "ok 1\n";
7 END { print "not ok 1\n" unless $loaded }
3 BEGIN { use_ok 'Convert::PEM' }
0 # $Id: 01-readwrite.t 85 2001-04-22 07:22:42Z btrott $
0 use strict;
1 use Test::More tests => 16;
2 use Test::Exception;
13
2 use strict;
3
4 use Test;
54 use Convert::PEM;
65 use Math::BigInt;
7
8 BEGIN { plan tests => 15 };
96
107 my $objfile = "./object.pem";
118
1613 int INTEGER
1714 }
1815 ));
19 ok($pem);
16 isa_ok $pem, 'Convert::PEM';
2017
2118 my($obj, $obj2);
2219 $obj = { TestObject => { int => 4 } };
2320
24 ok($pem->write( Filename => $objfile, Content => $obj));
25 ok(-e $objfile);
26 $obj2 = $pem->read( Filename => $objfile );
27 ok($obj2);
28 ok($obj->{TestObject}{int}, $obj2->{TestObject}{int});
21 lives_ok { $pem->write( Filename => $objfile, Content => $obj) } 'can write';
22 ok -e $objfile, 'output file exists';
23 lives_ok { $obj2 = $pem->read( Filename => $objfile ) } 'can read';
24 is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output';
2925 unlink $objfile;
3026
31 ok($pem->write( Filename => $objfile, Content => $obj, Password => 'xx' ));
32 ok(-e $objfile);
33 $obj2 = $pem->read( Filename => $objfile );
34 ok(!$obj2);
35 ok($pem->errstr =~ /^Decryption failed/);
36 $obj2 = $pem->read( Filename => $objfile, Password => 'xx');
37 ok($obj2);
38 ok($obj->{TestObject}{int}, $obj2->{TestObject}{int});
27 lives_ok { $pem->write( Filename => $objfile, Content => $obj, Password => 'xx' ) } 'can write';
28 ok -e $objfile, 'output file exists';
29 lives_ok { $obj2 = $pem->read( Filename => $objfile ) } 'can read';
30 ok !defined $obj2, 'cannot read encrypted file';
31 like $pem->errstr, qr/^Decryption failed/, 'errstr matches decryption failed';
32 lives_ok { $obj2 = $pem->read( Filename => $objfile, Password => 'xx') } 'can read';
33 is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output';
3934 unlink $objfile;
4035
4136 $obj->{TestObject}{int} = Math::BigInt->new("110982309809809850938509");
42 ok($pem->write( Filename => $objfile, Content => $obj));
43 ok(-e $objfile);
44 $obj2 = $pem->read( Filename => $objfile );
45 ok($obj2);
46 ok($obj->{TestObject}{int}, $obj2->{TestObject}{int});
37 lives_ok { $pem->write( Filename => $objfile, Content => $obj) } 'can write';
38 ok -e $objfile, 'output file exists';
39 lives_ok { $obj2 = $pem->read( Filename => $objfile ) } 'can read';
40 is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output';
4741 unlink $objfile;
0 # $Id: 02-encode.t 89 2001-04-22 08:01:45Z btrott $
0 use strict;
1 use Test::More tests => 9;
12
2 use strict;
3
4 use Test;
53 use Convert::PEM;
64 use Math::BigInt;
7
8 BEGIN { plan tests => 12 };
95
106 my $pem = Convert::PEM->new(
117 Name => 'TEST OBJECT',
1410 int INTEGER
1511 }
1612 ));
17 ok($pem);
13 isa_ok $pem, 'Convert::PEM';
1814
1915 my($obj, $obj2, $blob);
2016 $obj = { TestObject => { int => 4 } };
2117
22 $blob = $pem->encode( Content => $obj);
23 ok($blob);
18 $blob = $pem->encode( Content => $obj );
19 ok $blob, 'encode gave us something';
2420 $obj2 = $pem->decode( Content => $blob );
25 ok($obj2);
26 ok($obj->{TestObject}{int}, $obj2->{TestObject}{int});
21 is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output';
2722
2823 $blob = $pem->encode( Content => $obj, Password => 'xx' );
29 ok($blob);
24 ok $blob, 'encode gave us something';
3025 $obj2 = $pem->decode( Content => $blob );
31 ok(!$obj2);
32 ok($pem->errstr =~ /^Decryption failed/);
33 $obj2 = $pem->decode( Content => $blob, Password => 'xx');
34 ok($obj2);
35 ok($obj->{TestObject}{int}, $obj2->{TestObject}{int});
26 ok !defined $obj2, 'decode fails on encrypted input';
27 like $pem->errstr, qr/^Decryption failed/, 'errstr matches decrypt failed';
28 $obj2 = $pem->decode( Content => $blob, Password => 'xx' );
29 is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output';
3630
3731 $obj->{TestObject}{int} = Math::BigInt->new("110982309809809850938509");
3832 $blob = $pem->encode( Content => $obj );
39 ok($blob);
33 ok $blob, 'encode gave us something';
4034 $obj2 = $pem->decode( Content => $blob );
41 ok($obj2);
42 ok($obj->{TestObject}{int}, $obj2->{TestObject}{int});
35 is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output';
0 # $Id: 03-ede3.t 86 2001-04-22 07:31:08Z btrott $
0 use strict;
1 use Test::More tests => 6;
12
2 use strict;
3
4 use Test;
53 use Convert::PEM::CBC;
6
7 BEGIN { plan tests => 6 };
84
95 my $KEY = pack "H64", ("0123456789ABCDEF" x 4);
106 my $IV = "\0" x 8;
1612 Key => $KEY,
1713 IV => $IV,
1814 );
19 ok($cbc1);
15 isa_ok $cbc1, 'Convert::PEM::CBC';
2016
2117 $cbc2 = Convert::PEM::CBC->new(
2218 Cipher => 'Crypt::DES_EDE3',
2319 Key => $KEY,
2420 IV => $IV,
2521 );
26 ok($cbc2);
22 isa_ok $cbc2, 'Convert::PEM::CBC';
2723
2824 my($enc, $dec);
2925 $enc = $cbc1->encrypt( _checkbytes() );
30 ok($enc);
26 ok defined $enc, 'got something from encrypt';
3127 $dec = $cbc2->decrypt($enc);
32 ok($dec);
28 ok defined $dec, 'got something from decrypt';
3329
34 ok( vec($dec, 0, 8) == vec($dec, 2, 8) );
35 ok( vec($dec, 1, 8) == vec($dec, 3, 8) );
30 is vec($dec, 0, 8), vec($dec, 2, 8), 'input1 matches output1';
31 is vec($dec, 1, 8), vec($dec, 3, 8), 'input2 matches output2';
3632
3733 sub _checkbytes {
3834 my($check1, $check2) = (chr int rand 255, chr int rand 255);
0 use strict;
1 use Test::More tests => 4;
2
3 use Convert::PEM;
4
5 my $pem = Convert::PEM->new(
6 'Name' => 'TEST OBJECT',
7 'ASN' => q(
8 TestObject SEQUENCE {
9 int INTEGER
10 }
11 )
12 );
13
14 isa_ok( $pem, 'Convert::PEM' );
15
16 my %pemhash = (
17 'Object' => 'TEST OBJECT',
18 'Content' => 'Simple test content that is long enough to wrap in base64.',
19 'Headers' =>
20 [ [ 'A' => 'Alpha' ], [ 'B' => 'Bravo' ], [ 'C' => 'Charlie' ] ],
21 );
22
23 my $pemData = $pem->implode( %pemhash );
24
25 my $pemUnix = my $pemDos = my $pemOldMac = $pemData;
26 $pemUnix =~ s/\r\n|\n|\r/\n/g;
27 $pemDos =~ s/\r\n|\n|\r/\r\n/g;
28 $pemOldMac =~ s/\r\n|\n|\r/\r/g;
29
30 my $explodeUnix = $pem->explode( $pemUnix );
31 is_deeply( $explodeUnix, \%pemhash, "explode with unix line break" );
32
33 my $explodeDos = $pem->explode( $pemDos );
34 is_deeply( $explodeDos, \%pemhash, "explode with dos line break" );
35
36 my $explodeOldMac = $pem->explode( $pemOldMac );
37 is_deeply( $explodeOldMac, \%pemhash, "explode with old mac line break" );
0 use Test::More;
1 eval "use Test::Pod 1.00";
2 plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
3 all_pod_files_ok();
0 use Test::More;
1 eval "use Test::Synopsis";
2 plan skip_all => "Test::Synopsis required" if $@;
3 all_synopsis_ok();