Codebase list libperlx-maybe-perl / upstream/0.002
Imported Upstream version 0.002 Jonas Smedegaard 11 years ago
33 changed file(s) with 5240 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 PerlX-Maybe
1 ===========
2
3 Created: 2012-02-15
4 Home page: <https://metacpan.org/release/PerlX-Maybe>
5 Bug tracker: <http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe>
6
7 0.002 2012-05-03
8
9 - Faster implementation. Tested on Perl 5.10.1 on Linux, the new version
10 is 60% faster. (Not that it was slow to begin with - 'maybe' is a pretty
11 simple function.)
12
13 0.001 2012-02-15 # Initial release
14
15
0 This software is copyright (c) 2012 by Toby Inkster <tobyink@cpan.org>.
1
2 This is free software; you can redistribute it and/or modify it under
3 the same terms as the Perl 5 programming language system itself.
4
5 Terms of the Perl programming language system itself
6
7 a) the GNU General Public License as published by the Free
8 Software Foundation; either version 1, or (at your option) any
9 later version, or
10 b) the "Artistic License"
11
12 --- The GNU General Public License, Version 1, February 1989 ---
13
14 This software is Copyright (c) 2012 by Toby Inkster <tobyink@cpan.org>.
15
16 This is free software, licensed under:
17
18 The GNU General Public License, Version 1, February 1989
19
20 GNU GENERAL PUBLIC LICENSE
21 Version 1, February 1989
22
23 Copyright (C) 1989 Free Software Foundation, Inc.
24 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
25 Everyone is permitted to copy and distribute verbatim copies
26 of this license document, but changing it is not allowed.
27
28 Preamble
29
30 The license agreements of most software companies try to keep users
31 at the mercy of those companies. By contrast, our General Public
32 License is intended to guarantee your freedom to share and change free
33 software--to make sure the software is free for all its users. The
34 General Public License applies to the Free Software Foundation's
35 software and to any other program whose authors commit to using it.
36 You can use it for your programs, too.
37
38 When we speak of free software, we are referring to freedom, not
39 price. Specifically, the General Public License is designed to make
40 sure that you have the freedom to give away or sell copies of free
41 software, that you receive source code or can get it if you want it,
42 that you can change the software or use pieces of it in new free
43 programs; and that you know you can do these things.
44
45 To protect your rights, we need to make restrictions that forbid
46 anyone to deny you these rights or to ask you to surrender the rights.
47 These restrictions translate to certain responsibilities for you if you
48 distribute copies of the software, or if you modify it.
49
50 For example, if you distribute copies of a such a program, whether
51 gratis or for a fee, you must give the recipients all the rights that
52 you have. You must make sure that they, too, receive or can get the
53 source code. And you must tell them their rights.
54
55 We protect your rights with two steps: (1) copyright the software, and
56 (2) offer you this license which gives you legal permission to copy,
57 distribute and/or modify the software.
58
59 Also, for each author's protection and ours, we want to make certain
60 that everyone understands that there is no warranty for this free
61 software. If the software is modified by someone else and passed on, we
62 want its recipients to know that what they have is not the original, so
63 that any problems introduced by others will not reflect on the original
64 authors' reputations.
65
66 The precise terms and conditions for copying, distribution and
67 modification follow.
68
69 GNU GENERAL PUBLIC LICENSE
70 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
71
72 0. This License Agreement applies to any program or other work which
73 contains a notice placed by the copyright holder saying it may be
74 distributed under the terms of this General Public License. The
75 "Program", below, refers to any such program or work, and a "work based
76 on the Program" means either the Program or any work containing the
77 Program or a portion of it, either verbatim or with modifications. Each
78 licensee is addressed as "you".
79
80 1. You may copy and distribute verbatim copies of the Program's source
81 code as you receive it, in any medium, provided that you conspicuously and
82 appropriately publish on each copy an appropriate copyright notice and
83 disclaimer of warranty; keep intact all the notices that refer to this
84 General Public License and to the absence of any warranty; and give any
85 other recipients of the Program a copy of this General Public License
86 along with the Program. You may charge a fee for the physical act of
87 transferring a copy.
88
89 2. You may modify your copy or copies of the Program or any portion of
90 it, and copy and distribute such modifications under the terms of Paragraph
91 1 above, provided that you also do the following:
92
93 a) cause the modified files to carry prominent notices stating that
94 you changed the files and the date of any change; and
95
96 b) cause the whole of any work that you distribute or publish, that
97 in whole or in part contains the Program or any part thereof, either
98 with or without modifications, to be licensed at no charge to all
99 third parties under the terms of this General Public License (except
100 that you may choose to grant warranty protection to some or all
101 third parties, at your option).
102
103 c) If the modified program normally reads commands interactively when
104 run, you must cause it, when started running for such interactive use
105 in the simplest and most usual way, to print or display an
106 announcement including an appropriate copyright notice and a notice
107 that there is no warranty (or else, saying that you provide a
108 warranty) and that users may redistribute the program under these
109 conditions, and telling the user how to view a copy of this General
110 Public License.
111
112 d) You may charge a fee for the physical act of transferring a
113 copy, and you may at your option offer warranty protection in
114 exchange for a fee.
115
116 Mere aggregation of another independent work with the Program (or its
117 derivative) on a volume of a storage or distribution medium does not bring
118 the other work under the scope of these terms.
119
120 3. You may copy and distribute the Program (or a portion or derivative of
121 it, under Paragraph 2) in object code or executable form under the terms of
122 Paragraphs 1 and 2 above provided that you also do one of the following:
123
124 a) accompany it with the complete corresponding machine-readable
125 source code, which must be distributed under the terms of
126 Paragraphs 1 and 2 above; or,
127
128 b) accompany it with a written offer, valid for at least three
129 years, to give any third party free (except for a nominal charge
130 for the cost of distribution) a complete machine-readable copy of the
131 corresponding source code, to be distributed under the terms of
132 Paragraphs 1 and 2 above; or,
133
134 c) accompany it with the information you received as to where the
135 corresponding source code may be obtained. (This alternative is
136 allowed only for noncommercial distribution and only if you
137 received the program in object code or executable form alone.)
138
139 Source code for a work means the preferred form of the work for making
140 modifications to it. For an executable file, complete source code means
141 all the source code for all modules it contains; but, as a special
142 exception, it need not include source code for modules which are standard
143 libraries that accompany the operating system on which the executable
144 file runs, or for standard header files or definitions files that
145 accompany that operating system.
146
147 4. You may not copy, modify, sublicense, distribute or transfer the
148 Program except as expressly provided under this General Public License.
149 Any attempt otherwise to copy, modify, sublicense, distribute or transfer
150 the Program is void, and will automatically terminate your rights to use
151 the Program under this License. However, parties who have received
152 copies, or rights to use copies, from you under this General Public
153 License will not have their licenses terminated so long as such parties
154 remain in full compliance.
155
156 5. By copying, distributing or modifying the Program (or any work based
157 on the Program) you indicate your acceptance of this license to do so,
158 and all its terms and conditions.
159
160 6. Each time you redistribute the Program (or any work based on the
161 Program), the recipient automatically receives a license from the original
162 licensor to copy, distribute or modify the Program subject to these
163 terms and conditions. You may not impose any further restrictions on the
164 recipients' exercise of the rights granted herein.
165
166 7. The Free Software Foundation may publish revised and/or new versions
167 of the General Public License from time to time. Such new versions will
168 be similar in spirit to the present version, but may differ in detail to
169 address new problems or concerns.
170
171 Each version is given a distinguishing version number. If the Program
172 specifies a version number of the license which applies to it and "any
173 later version", you have the option of following the terms and conditions
174 either of that version or of any later version published by the Free
175 Software Foundation. If the Program does not specify a version number of
176 the license, you may choose any version ever published by the Free Software
177 Foundation.
178
179 8. If you wish to incorporate parts of the Program into other free
180 programs whose distribution conditions are different, write to the author
181 to ask for permission. For software which is copyrighted by the Free
182 Software Foundation, write to the Free Software Foundation; we sometimes
183 make exceptions for this. Our decision will be guided by the two goals
184 of preserving the free status of all derivatives of our free software and
185 of promoting the sharing and reuse of software generally.
186
187 NO WARRANTY
188
189 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
190 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
191 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
192 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
193 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
194 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
195 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
196 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
197 REPAIR OR CORRECTION.
198
199 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
200 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
201 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
202 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
203 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
204 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
205 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
206 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
207 POSSIBILITY OF SUCH DAMAGES.
208
209 END OF TERMS AND CONDITIONS
210
211 Appendix: How to Apply These Terms to Your New Programs
212
213 If you develop a new program, and you want it to be of the greatest
214 possible use to humanity, the best way to achieve this is to make it
215 free software which everyone can redistribute and change under these
216 terms.
217
218 To do so, attach the following notices to the program. It is safest to
219 attach them to the start of each source file to most effectively convey
220 the exclusion of warranty; and each file should have at least the
221 "copyright" line and a pointer to where the full notice is found.
222
223 <one line to give the program's name and a brief idea of what it does.>
224 Copyright (C) 19yy <name of author>
225
226 This program is free software; you can redistribute it and/or modify
227 it under the terms of the GNU General Public License as published by
228 the Free Software Foundation; either version 1, or (at your option)
229 any later version.
230
231 This program is distributed in the hope that it will be useful,
232 but WITHOUT ANY WARRANTY; without even the implied warranty of
233 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
234 GNU General Public License for more details.
235
236 You should have received a copy of the GNU General Public License
237 along with this program; if not, write to the Free Software Foundation,
238 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
239
240 Also add information on how to contact you by electronic and paper mail.
241
242 If the program is interactive, make it output a short notice like this
243 when it starts in an interactive mode:
244
245 Gnomovision version 69, Copyright (C) 19xx name of author
246 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
247 This is free software, and you are welcome to redistribute it
248 under certain conditions; type `show c' for details.
249
250 The hypothetical commands `show w' and `show c' should show the
251 appropriate parts of the General Public License. Of course, the
252 commands you use may be called something other than `show w' and `show
253 c'; they could even be mouse-clicks or menu items--whatever suits your
254 program.
255
256 You should also get your employer (if you work as a programmer) or your
257 school, if any, to sign a "copyright disclaimer" for the program, if
258 necessary. Here a sample; alter the names:
259
260 Yoyodyne, Inc., hereby disclaims all copyright interest in the
261 program `Gnomovision' (a program to direct compilers to make passes
262 at assemblers) written by James Hacker.
263
264 <signature of Ty Coon>, 1 April 1989
265 Ty Coon, President of Vice
266
267 That's all there is to it!
268
269
270 --- The Artistic License 1.0 ---
271
272 This software is Copyright (c) 2012 by Toby Inkster <tobyink@cpan.org>.
273
274 This is free software, licensed under:
275
276 The Artistic License 1.0
277
278 The Artistic License
279
280 Preamble
281
282 The intent of this document is to state the conditions under which a Package
283 may be copied, such that the Copyright Holder maintains some semblance of
284 artistic control over the development of the package, while giving the users of
285 the package the right to use and distribute the Package in a more-or-less
286 customary fashion, plus the right to make reasonable modifications.
287
288 Definitions:
289
290 - "Package" refers to the collection of files distributed by the Copyright
291 Holder, and derivatives of that collection of files created through
292 textual modification.
293 - "Standard Version" refers to such a Package if it has not been modified,
294 or has been modified in accordance with the wishes of the Copyright
295 Holder.
296 - "Copyright Holder" is whoever is named in the copyright or copyrights for
297 the package.
298 - "You" is you, if you're thinking about copying or distributing this Package.
299 - "Reasonable copying fee" is whatever you can justify on the basis of media
300 cost, duplication charges, time of people involved, and so on. (You will
301 not be required to justify it to the Copyright Holder, but only to the
302 computing community at large as a market that must bear the fee.)
303 - "Freely Available" means that no fee is charged for the item itself, though
304 there may be fees involved in handling the item. It also means that
305 recipients of the item may redistribute it under the same conditions they
306 received it.
307
308 1. You may make and give away verbatim copies of the source form of the
309 Standard Version of this Package without restriction, provided that you
310 duplicate all of the original copyright notices and associated disclaimers.
311
312 2. You may apply bug fixes, portability fixes and other modifications derived
313 from the Public Domain or from the Copyright Holder. A Package modified in such
314 a way shall still be considered the Standard Version.
315
316 3. You may otherwise modify your copy of this Package in any way, provided that
317 you insert a prominent notice in each changed file stating how and when you
318 changed that file, and provided that you do at least ONE of the following:
319
320 a) place your modifications in the Public Domain or otherwise make them
321 Freely Available, such as by posting said modifications to Usenet or an
322 equivalent medium, or placing the modifications on a major archive site
323 such as ftp.uu.net, or by allowing the Copyright Holder to include your
324 modifications in the Standard Version of the Package.
325
326 b) use the modified Package only within your corporation or organization.
327
328 c) rename any non-standard executables so the names do not conflict with
329 standard executables, which must also be provided, and provide a separate
330 manual page for each non-standard executable that clearly documents how it
331 differs from the Standard Version.
332
333 d) make other distribution arrangements with the Copyright Holder.
334
335 4. You may distribute the programs of this Package in object code or executable
336 form, provided that you do at least ONE of the following:
337
338 a) distribute a Standard Version of the executables and library files,
339 together with instructions (in the manual page or equivalent) on where to
340 get the Standard Version.
341
342 b) accompany the distribution with the machine-readable source of the Package
343 with your modifications.
344
345 c) accompany any non-standard executables with their corresponding Standard
346 Version executables, giving the non-standard executables non-standard
347 names, and clearly documenting the differences in manual pages (or
348 equivalent), together with instructions on where to get the Standard
349 Version.
350
351 d) make other distribution arrangements with the Copyright Holder.
352
353 5. You may charge a reasonable copying fee for any distribution of this
354 Package. You may charge any fee you choose for support of this Package. You
355 may not charge a fee for this Package itself. However, you may distribute this
356 Package in aggregate with other (possibly commercial) programs as part of a
357 larger (possibly commercial) software distribution provided that you do not
358 advertise this Package as a product of your own.
359
360 6. The scripts and library files supplied as input to or produced as output
361 from the programs of this Package do not automatically fall under the copyright
362 of this Package, but belong to whomever generated them, and may be sold
363 commercially, and may be aggregated with this Package.
364
365 7. C or perl subroutines supplied by you and linked into this Package shall not
366 be considered part of this Package.
367
368 8. The name of the Copyright Holder may not be used to endorse or promote
369 products derived from this software without specific prior written permission.
370
371 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
372 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
373 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
374
375 The End
376
0 Changes
1 inc/Module/AutoInstall.pm
2 inc/Module/Install.pm
3 inc/Module/Install/AutoInstall.pm
4 inc/Module/Install/AutoManifest.pm
5 inc/Module/Install/Base.pm
6 inc/Module/Install/Can.pm
7 inc/Module/Install/Fetch.pm
8 inc/Module/Install/Include.pm
9 inc/Module/Install/Makefile.pm
10 inc/Module/Install/Metadata.pm
11 inc/Module/Install/Package.pm
12 inc/Module/Install/TrustMetaYml.pm
13 inc/Module/Install/Win32.pm
14 inc/Module/Install/WriteAll.pm
15 inc/Module/Package.pm
16 inc/Module/Package/Dist/RDF.pm
17 inc/Scalar/Util.pm
18 inc/Scalar/Util/PP.pm
19 inc/YAML/Tiny.pm
20 lib/PerlX/Maybe.pm
21 lib/Syntax/Feature/Maybe.pm
22 LICENSE
23 Makefile.PL
24 MANIFEST This list of files
25 META.yml
26 meta/changes.ttl
27 meta/doap.ttl
28 meta/makefile.ttl
29 README
30 t/01basic.t
31 t/02maybe.t
32 SIGNATURE Public-key signature (added by MakeMaker)
0 ---
1 abstract: 'return a given list only if they are all defined'
2 author:
3 - 'Toby Inkster <tobyink@cpan.org>'
4 build_requires:
5 ExtUtils::MakeMaker: 6.42
6 Test::More: 0.61
7 configure_requires:
8 ExtUtils::MakeMaker: 6.42
9 distribution_type: module
10 generated_by: 'Module::Install version 1.02'
11 keywords: []
12 license: perl
13 meta-spec:
14 url: http://module-build.sourceforge.net/META-spec-v1.4.html
15 version: 1.4
16 module_name: PerlX::Maybe
17 name: PerlX-Maybe
18 no_index:
19 directory:
20 - inc
21 - t
22 - xt
23 requires:
24 Exporter: 0
25 perl: 5.8.0
26 strict: 0
27 resources:
28 bugtracker: http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe
29 homepage: https://metacpan.org/release/PerlX-Maybe
30 license: http://dev.perl.org/licenses/
31 repository: https://bitbucket.org/tobyink/p5-perlx-maybe
32 version: 0.002
0 use inc::Module::Package 'RDF:standard';
1
0 NAME
1 PerlX::Maybe - return a pair only if they are both defined
2
3 SYNOPSIS
4 You once wrote:
5
6 my $bob = Person->new(
7 defined $name ? (name => $name) : (),
8 defined $age ? (age => $age) : (),
9 );
10
11 Now you can write:
12
13 my $bob = Person->new(
14 maybe name => $name,
15 maybe age => $age,
16 );
17
18 DESCRIPTION
19 Moose classes (and some other classes) distinguish between an attribute
20 being unset and the attribute being set to undef. Supplying a
21 constructor arguments like this:
22
23 my $bob = Person->new(
24 name => $name,
25 age => $age,
26 );
27
28 Will result in the "name" and "age" attributes possibly being set to
29 undef (if the corresponding $name and $age variables are not defined),
30 which may violate the Person class' type constraints.
31
32 (Note: if you are the *author* of the class in question, you can solve
33 this using MooseX::UndefTolerant. However, some of us are stuck using
34 non-UndefTolerant classes written by third parties.)
35
36 To ensure that the Person constructor does not try to set a name or age
37 at all when they are undefined, ugly looking code like this is often
38 used:
39
40 my $bob = Person->new(
41 defined $name ? (name => $name) : (),
42 defined $age ? (age => $age) : (),
43 );
44
45 or:
46
47 my $bob = Person->new(
48 (name => $name) x!!(defined $name),
49 (age => $age) x!!(defined $age),
50 );
51
52 A slightly more elegant solution is the "maybe" function:
53
54 "maybe $x => $y, @rest"
55 This function checks that $x and $y are both defined. If they are, it
56 returns them both as a list; otherwise it returns the empty list.
57
58 If @rest is provided, it is unconditionally appended to the end of
59 whatever list is returned.
60
61 The combination of these behaviours allows the following very sugary
62 syntax to "just work".
63
64 my $bob = Person->new(
65 name => $name,
66 address => $addr,
67 maybe phone => $tel,
68 maybe email => $email,
69 unique_id => $id,
70 );
71
72 This function is exported by default.
73
74 BUGS
75 Please report any bugs to
76 <http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe>.
77
78 SEE ALSO
79 Syntax::Feature::Maybe.
80
81 MooseX::UndefTolerant, PerlX::Perform, Exporter.
82
83 AUTHOR
84 Toby Inkster <tobyink@cpan.org>.
85
86 COPYRIGHT AND LICENCE
87 This software is copyright (c) 2012 by Toby Inkster.
88
89 This is free software; you can redistribute it and/or modify it under
90 the same terms as the Perl 5 programming language system itself.
91
92 DISCLAIMER OF WARRANTIES
93 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
94 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
95 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
96
0 This file contains message digests of all files listed in MANIFEST,
1 signed via the Module::Signature module, version 0.66.
2
3 To verify the content in this distribution, first make sure you have
4 Module::Signature installed, then type:
5
6 % cpansign -v
7
8 It will check each file's integrity, as well as the signature's
9 validity. If "==> Signature verified OK! <==" is not displayed,
10 the distribution may already have been compromised, and you should
11 not run its Makefile.PL or Build.PL.
12
13 -----BEGIN PGP SIGNED MESSAGE-----
14 Hash: SHA1
15
16 SHA1 92ef62c0de13e8545a0d31f10406025371aa50ba Changes
17 SHA1 1d54db0b8134eb1c8ea0cee400f9dc612bcaa61a LICENSE
18 SHA1 cf87de9185eb4d8409344c716b72930449430a1d MANIFEST
19 SHA1 9b5306cfd14416ef353fb8a78154b453cb3f008e META.yml
20 SHA1 7150e5e086ef493e1e527a1eeec44a8344b80db6 Makefile.PL
21 SHA1 da978d574620c957831376dbe75cd0a699b983d8 README
22 SHA1 5d94bc10deff1dd74e4bc5dfa6fc015e39271f15 inc/Module/AutoInstall.pm
23 SHA1 40106479d4e07f379cb82ca1d69fca92e3a40f47 inc/Module/Install.pm
24 SHA1 34a24a530ecf0365cc02e4150b06c9bed702a441 inc/Module/Install/AutoInstall.pm
25 SHA1 c04f94f91fa97b9f8cfb5a36071098ab0e6c78e3 inc/Module/Install/AutoManifest.pm
26 SHA1 ae8aa01a73cb83da31c39e8eed1120c59cb530a1 inc/Module/Install/Base.pm
27 SHA1 5c87d2d0e2c08b5173259006c88ad81c24303f9d inc/Module/Install/Can.pm
28 SHA1 98daf9d8c50b4b7e8988cf1fa2b86044ad219533 inc/Module/Install/Fetch.pm
29 SHA1 f3e008113f7f49b0625083b6cc358a312854f613 inc/Module/Install/Include.pm
30 SHA1 e67589fcbacdda6c98ff34d8e26a004ab0467bdc inc/Module/Install/Makefile.pm
31 SHA1 209ea405d4ab94475661bb450d0ea042d2ec25b5 inc/Module/Install/Metadata.pm
32 SHA1 3b9281ddf7dd6d6f5de0a9642c69333023193c80 inc/Module/Install/Package.pm
33 SHA1 b86d0385e10881db680d28bde94f275e49e34a27 inc/Module/Install/TrustMetaYml.pm
34 SHA1 1326052d1df1065debee74f9d8583a734b9b3d00 inc/Module/Install/Win32.pm
35 SHA1 bb607f3715c40fc3bc1c46496587cdb215bc4fa2 inc/Module/Install/WriteAll.pm
36 SHA1 26d58a041cd6b3d21db98b32e8fd1841aae21204 inc/Module/Package.pm
37 SHA1 6b807287940754cc31a3db59f2b22e363d5525be inc/Module/Package/Dist/RDF.pm
38 SHA1 e31c281782183601e1e057c5914f63269e043932 inc/Scalar/Util.pm
39 SHA1 5eae2f71c45a996a296d2445b18d0589307111f0 inc/Scalar/Util/PP.pm
40 SHA1 eef6bff62046bff2ce08ba132d0b58fba30f40b4 inc/YAML/Tiny.pm
41 SHA1 03d73a6ec001330a0caafeef4e1aa5b2c013d934 lib/PerlX/Maybe.pm
42 SHA1 dbab1703220f624dec03528977fe5ccb76e708a7 lib/Syntax/Feature/Maybe.pm
43 SHA1 ad2bfe18cd3501353c1bc805692549dc31507d3c meta/changes.ttl
44 SHA1 4615287be6141b45a1f5466d1316f0ee77f89fd0 meta/doap.ttl
45 SHA1 21b1360a6a156c4deafd2eab8a4e8b686af8b310 meta/makefile.ttl
46 SHA1 0eda281cd41c7bfa28293ff92f8599deb2f9e288 t/01basic.t
47 SHA1 3079896117a38ecef4125ac9756cb2d665434bea t/02maybe.t
48 -----BEGIN PGP SIGNATURE-----
49 Version: GnuPG v1.4.10 (GNU/Linux)
50
51 iEYEARECAAYFAk+iR1oACgkQzr+BKGoqfTlp1wCdGZ9q8phvamW03KjFUPtm2dtD
52 CEMAoJixIRK0Y0ebLz4YLYIxM5TtrPx4
53 =oOf5
54 -----END PGP SIGNATURE-----
0 #line 1
1 package Module::AutoInstall;
2
3 use strict;
4 use Cwd ();
5 use ExtUtils::MakeMaker ();
6
7 use vars qw{$VERSION};
8 BEGIN {
9 $VERSION = '1.03';
10 }
11
12 # special map on pre-defined feature sets
13 my %FeatureMap = (
14 '' => 'Core Features', # XXX: deprecated
15 '-core' => 'Core Features',
16 );
17
18 # various lexical flags
19 my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $InstallDepsTarget, $HasCPANPLUS );
20 my (
21 $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps,
22 $UpgradeDeps
23 );
24 my ( $PostambleActions, $PostambleActionsNoTest, $PostambleActionsUpgradeDeps,
25 $PostambleActionsUpgradeDepsNoTest, $PostambleActionsListDeps,
26 $PostambleActionsListAllDeps, $PostambleUsed, $NoTest);
27
28 # See if it's a testing or non-interactive session
29 _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN );
30 _init();
31
32 sub _accept_default {
33 $AcceptDefault = shift;
34 }
35
36 sub _installdeps_target {
37 $InstallDepsTarget = shift;
38 }
39
40 sub missing_modules {
41 return @Missing;
42 }
43
44 sub do_install {
45 __PACKAGE__->install(
46 [
47 $Config
48 ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
49 : ()
50 ],
51 @Missing,
52 );
53 }
54
55 # initialize various flags, and/or perform install
56 sub _init {
57 foreach my $arg (
58 @ARGV,
59 split(
60 /[\s\t]+/,
61 $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || ''
62 )
63 )
64 {
65 if ( $arg =~ /^--config=(.*)$/ ) {
66 $Config = [ split( ',', $1 ) ];
67 }
68 elsif ( $arg =~ /^--installdeps=(.*)$/ ) {
69 __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) );
70 exit 0;
71 }
72 elsif ( $arg =~ /^--upgradedeps=(.*)$/ ) {
73 $UpgradeDeps = 1;
74 __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) );
75 exit 0;
76 }
77 elsif ( $arg =~ /^--default(?:deps)?$/ ) {
78 $AcceptDefault = 1;
79 }
80 elsif ( $arg =~ /^--check(?:deps)?$/ ) {
81 $CheckOnly = 1;
82 }
83 elsif ( $arg =~ /^--skip(?:deps)?$/ ) {
84 $SkipInstall = 1;
85 }
86 elsif ( $arg =~ /^--test(?:only)?$/ ) {
87 $TestOnly = 1;
88 }
89 elsif ( $arg =~ /^--all(?:deps)?$/ ) {
90 $AllDeps = 1;
91 }
92 }
93 }
94
95 # overrides MakeMaker's prompt() to automatically accept the default choice
96 sub _prompt {
97 goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault;
98
99 my ( $prompt, $default ) = @_;
100 my $y = ( $default =~ /^[Yy]/ );
101
102 print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] ';
103 print "$default\n";
104 return $default;
105 }
106
107 # the workhorse
108 sub import {
109 my $class = shift;
110 my @args = @_ or return;
111 my $core_all;
112
113 print "*** $class version " . $class->VERSION . "\n";
114 print "*** Checking for Perl dependencies...\n";
115
116 my $cwd = Cwd::cwd();
117
118 $Config = [];
119
120 my $maxlen = length(
121 (
122 sort { length($b) <=> length($a) }
123 grep { /^[^\-]/ }
124 map {
125 ref($_)
126 ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} )
127 : ''
128 }
129 map { +{@args}->{$_} }
130 grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} }
131 )[0]
132 );
133
134 # We want to know if we're under CPAN early to avoid prompting, but
135 # if we aren't going to try and install anything anyway then skip the
136 # check entirely since we don't want to have to load (and configure)
137 # an old CPAN just for a cosmetic message
138
139 $UnderCPAN = _check_lock(1) unless $SkipInstall || $InstallDepsTarget;
140
141 while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) {
142 my ( @required, @tests, @skiptests );
143 my $default = 1;
144 my $conflict = 0;
145
146 if ( $feature =~ m/^-(\w+)$/ ) {
147 my $option = lc($1);
148
149 # check for a newer version of myself
150 _update_to( $modules, @_ ) and return if $option eq 'version';
151
152 # sets CPAN configuration options
153 $Config = $modules if $option eq 'config';
154
155 # promote every features to core status
156 $core_all = ( $modules =~ /^all$/i ) and next
157 if $option eq 'core';
158
159 next unless $option eq 'core';
160 }
161
162 print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n";
163
164 $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' );
165
166 unshift @$modules, -default => &{ shift(@$modules) }
167 if ( ref( $modules->[0] ) eq 'CODE' ); # XXX: bugward combatability
168
169 while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) {
170 if ( $mod =~ m/^-(\w+)$/ ) {
171 my $option = lc($1);
172
173 $default = $arg if ( $option eq 'default' );
174 $conflict = $arg if ( $option eq 'conflict' );
175 @tests = @{$arg} if ( $option eq 'tests' );
176 @skiptests = @{$arg} if ( $option eq 'skiptests' );
177
178 next;
179 }
180
181 printf( "- %-${maxlen}s ...", $mod );
182
183 if ( $arg and $arg =~ /^\D/ ) {
184 unshift @$modules, $arg;
185 $arg = 0;
186 }
187
188 # XXX: check for conflicts and uninstalls(!) them.
189 my $cur = _load($mod);
190 if (_version_cmp ($cur, $arg) >= 0)
191 {
192 print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n";
193 push @Existing, $mod => $arg;
194 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
195 }
196 else {
197 if (not defined $cur) # indeed missing
198 {
199 print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n";
200 }
201 else
202 {
203 # no need to check $arg as _version_cmp ($cur, undef) would satisfy >= above
204 print "too old. ($cur < $arg)\n";
205 }
206
207 push @required, $mod => $arg;
208 }
209 }
210
211 next unless @required;
212
213 my $mandatory = ( $feature eq '-core' or $core_all );
214
215 if (
216 !$SkipInstall
217 and (
218 $CheckOnly
219 or ($mandatory and $UnderCPAN)
220 or $AllDeps
221 or $InstallDepsTarget
222 or _prompt(
223 qq{==> Auto-install the }
224 . ( @required / 2 )
225 . ( $mandatory ? ' mandatory' : ' optional' )
226 . qq{ module(s) from CPAN?},
227 $default ? 'y' : 'n',
228 ) =~ /^[Yy]/
229 )
230 )
231 {
232 push( @Missing, @required );
233 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
234 }
235
236 elsif ( !$SkipInstall
237 and $default
238 and $mandatory
239 and
240 _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', )
241 =~ /^[Nn]/ )
242 {
243 push( @Missing, @required );
244 $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
245 }
246
247 else {
248 $DisabledTests{$_} = 1 for map { glob($_) } @tests;
249 }
250 }
251
252 if ( @Missing and not( $CheckOnly or $UnderCPAN) ) {
253 require Config;
254 my $make = $Config::Config{make};
255 if ($InstallDepsTarget) {
256 print
257 "*** To install dependencies type '$make installdeps' or '$make installdeps_notest'.\n";
258 }
259 else {
260 print
261 "*** Dependencies will be installed the next time you type '$make'.\n";
262 }
263
264 # make an educated guess of whether we'll need root permission.
265 print " (You may need to do that as the 'root' user.)\n"
266 if eval '$>';
267 }
268 print "*** $class configuration finished.\n";
269
270 chdir $cwd;
271
272 # import to main::
273 no strict 'refs';
274 *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main';
275
276 return (@Existing, @Missing);
277 }
278
279 sub _running_under {
280 my $thing = shift;
281 print <<"END_MESSAGE";
282 *** Since we're running under ${thing}, I'll just let it take care
283 of the dependency's installation later.
284 END_MESSAGE
285 return 1;
286 }
287
288 # Check to see if we are currently running under CPAN.pm and/or CPANPLUS;
289 # if we are, then we simply let it taking care of our dependencies
290 sub _check_lock {
291 return unless @Missing or @_;
292
293 if ($ENV{PERL5_CPANM_IS_RUNNING}) {
294 return _running_under('cpanminus');
295 }
296
297 my $cpan_env = $ENV{PERL5_CPAN_IS_RUNNING};
298
299 if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) {
300 return _running_under($cpan_env ? 'CPAN' : 'CPANPLUS');
301 }
302
303 require CPAN;
304
305 if ($CPAN::VERSION > '1.89') {
306 if ($cpan_env) {
307 return _running_under('CPAN');
308 }
309 return; # CPAN.pm new enough, don't need to check further
310 }
311
312 # last ditch attempt, this -will- configure CPAN, very sorry
313
314 _load_cpan(1); # force initialize even though it's already loaded
315
316 # Find the CPAN lock-file
317 my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" );
318 return unless -f $lock;
319
320 # Check the lock
321 local *LOCK;
322 return unless open(LOCK, $lock);
323
324 if (
325 ( $^O eq 'MSWin32' ? _under_cpan() : <LOCK> == getppid() )
326 and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore'
327 ) {
328 print <<'END_MESSAGE';
329
330 *** Since we're running under CPAN, I'll just let it take care
331 of the dependency's installation later.
332 END_MESSAGE
333 return 1;
334 }
335
336 close LOCK;
337 return;
338 }
339
340 sub install {
341 my $class = shift;
342
343 my $i; # used below to strip leading '-' from config keys
344 my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } );
345
346 my ( @modules, @installed );
347 while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) {
348
349 # grep out those already installed
350 if ( _version_cmp( _load($pkg), $ver ) >= 0 ) {
351 push @installed, $pkg;
352 }
353 else {
354 push @modules, $pkg, $ver;
355 }
356 }
357
358 if ($UpgradeDeps) {
359 push @modules, @installed;
360 @installed = ();
361 }
362
363 return @installed unless @modules; # nothing to do
364 return @installed if _check_lock(); # defer to the CPAN shell
365
366 print "*** Installing dependencies...\n";
367
368 return unless _connected_to('cpan.org');
369
370 my %args = @config;
371 my %failed;
372 local *FAILED;
373 if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) {
374 while (<FAILED>) { chomp; $failed{$_}++ }
375 close FAILED;
376
377 my @newmod;
378 while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) {
379 push @newmod, ( $k => $v ) unless $failed{$k};
380 }
381 @modules = @newmod;
382 }
383
384 if ( _has_cpanplus() and not $ENV{PERL_AUTOINSTALL_PREFER_CPAN} ) {
385 _install_cpanplus( \@modules, \@config );
386 } else {
387 _install_cpan( \@modules, \@config );
388 }
389
390 print "*** $class installation finished.\n";
391
392 # see if we have successfully installed them
393 while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
394 if ( _version_cmp( _load($pkg), $ver ) >= 0 ) {
395 push @installed, $pkg;
396 }
397 elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) {
398 print FAILED "$pkg\n";
399 }
400 }
401
402 close FAILED if $args{do_once};
403
404 return @installed;
405 }
406
407 sub _install_cpanplus {
408 my @modules = @{ +shift };
409 my @config = _cpanplus_config( @{ +shift } );
410 my $installed = 0;
411
412 require CPANPLUS::Backend;
413 my $cp = CPANPLUS::Backend->new;
414 my $conf = $cp->configure_object;
415
416 return unless $conf->can('conf') # 0.05x+ with "sudo" support
417 or _can_write($conf->_get_build('base')); # 0.04x
418
419 # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
420 my $makeflags = $conf->get_conf('makeflags') || '';
421 if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) {
422 # 0.03+ uses a hashref here
423 $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST};
424
425 } else {
426 # 0.02 and below uses a scalar
427 $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' )
428 if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } );
429
430 }
431 $conf->set_conf( makeflags => $makeflags );
432 $conf->set_conf( prereqs => 1 );
433
434
435
436 while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) {
437 $conf->set_conf( $key, $val );
438 }
439
440 my $modtree = $cp->module_tree;
441 while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
442 print "*** Installing $pkg...\n";
443
444 MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall;
445
446 my $success;
447 my $obj = $modtree->{$pkg};
448
449 if ( $obj and _version_cmp( $obj->{version}, $ver ) >= 0 ) {
450 my $pathname = $pkg;
451 $pathname =~ s/::/\\W/;
452
453 foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) {
454 delete $INC{$inc};
455 }
456
457 my $rv = $cp->install( modules => [ $obj->{module} ] );
458
459 if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) {
460 print "*** $pkg successfully installed.\n";
461 $success = 1;
462 } else {
463 print "*** $pkg installation cancelled.\n";
464 $success = 0;
465 }
466
467 $installed += $success;
468 } else {
469 print << ".";
470 *** Could not find a version $ver or above for $pkg; skipping.
471 .
472 }
473
474 MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall;
475 }
476
477 return $installed;
478 }
479
480 sub _cpanplus_config {
481 my @config = ();
482 while ( @_ ) {
483 my ($key, $value) = (shift(), shift());
484 if ( $key eq 'prerequisites_policy' ) {
485 if ( $value eq 'follow' ) {
486 $value = CPANPLUS::Internals::Constants::PREREQ_INSTALL();
487 } elsif ( $value eq 'ask' ) {
488 $value = CPANPLUS::Internals::Constants::PREREQ_ASK();
489 } elsif ( $value eq 'ignore' ) {
490 $value = CPANPLUS::Internals::Constants::PREREQ_IGNORE();
491 } else {
492 die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n";
493 }
494 push @config, 'prereqs', $value;
495 } elsif ( $key eq 'force' ) {
496 push @config, $key, $value;
497 } elsif ( $key eq 'notest' ) {
498 push @config, 'skiptest', $value;
499 } else {
500 die "*** Cannot convert option $key to CPANPLUS version.\n";
501 }
502 }
503 return @config;
504 }
505
506 sub _install_cpan {
507 my @modules = @{ +shift };
508 my @config = @{ +shift };
509 my $installed = 0;
510 my %args;
511
512 _load_cpan();
513 require Config;
514
515 if (CPAN->VERSION < 1.80) {
516 # no "sudo" support, probe for writableness
517 return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) )
518 and _can_write( $Config::Config{sitelib} );
519 }
520
521 # if we're root, set UNINST=1 to avoid trouble unless user asked for it.
522 my $makeflags = $CPAN::Config->{make_install_arg} || '';
523 $CPAN::Config->{make_install_arg} =
524 join( ' ', split( ' ', $makeflags ), 'UNINST=1' )
525 if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } );
526
527 # don't show start-up info
528 $CPAN::Config->{inhibit_startup_message} = 1;
529
530 # set additional options
531 while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) {
532 ( $args{$opt} = $arg, next )
533 if $opt =~ /^(?:force|notest)$/; # pseudo-option
534 $CPAN::Config->{$opt} = $arg;
535 }
536
537 if ($args{notest} && (not CPAN::Shell->can('notest'))) {
538 die "Your version of CPAN is too old to support the 'notest' pragma";
539 }
540
541 local $CPAN::Config->{prerequisites_policy} = 'follow';
542
543 while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
544 MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall;
545
546 print "*** Installing $pkg...\n";
547
548 my $obj = CPAN::Shell->expand( Module => $pkg );
549 my $success = 0;
550
551 if ( $obj and _version_cmp( $obj->cpan_version, $ver ) >= 0 ) {
552 my $pathname = $pkg;
553 $pathname =~ s/::/\\W/;
554
555 foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) {
556 delete $INC{$inc};
557 }
558
559 my $rv = do {
560 if ($args{force}) {
561 CPAN::Shell->force( install => $pkg )
562 } elsif ($args{notest}) {
563 CPAN::Shell->notest( install => $pkg )
564 } else {
565 CPAN::Shell->install($pkg)
566 }
567 };
568
569 $rv ||= eval {
570 $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, )
571 ->{install}
572 if $CPAN::META;
573 };
574
575 if ( $rv eq 'YES' ) {
576 print "*** $pkg successfully installed.\n";
577 $success = 1;
578 }
579 else {
580 print "*** $pkg installation failed.\n";
581 $success = 0;
582 }
583
584 $installed += $success;
585 }
586 else {
587 print << ".";
588 *** Could not find a version $ver or above for $pkg; skipping.
589 .
590 }
591
592 MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall;
593 }
594
595 return $installed;
596 }
597
598 sub _has_cpanplus {
599 return (
600 $HasCPANPLUS = (
601 $INC{'CPANPLUS/Config.pm'}
602 or _load('CPANPLUS::Shell::Default')
603 )
604 );
605 }
606
607 # make guesses on whether we're under the CPAN installation directory
608 sub _under_cpan {
609 require Cwd;
610 require File::Spec;
611
612 my $cwd = File::Spec->canonpath( Cwd::cwd() );
613 my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} );
614
615 return ( index( $cwd, $cpan ) > -1 );
616 }
617
618 sub _update_to {
619 my $class = __PACKAGE__;
620 my $ver = shift;
621
622 return
623 if _version_cmp( _load($class), $ver ) >= 0; # no need to upgrade
624
625 if (
626 _prompt( "==> A newer version of $class ($ver) is required. Install?",
627 'y' ) =~ /^[Nn]/
628 )
629 {
630 die "*** Please install $class $ver manually.\n";
631 }
632
633 print << ".";
634 *** Trying to fetch it from CPAN...
635 .
636
637 # install ourselves
638 _load($class) and return $class->import(@_)
639 if $class->install( [], $class, $ver );
640
641 print << '.'; exit 1;
642
643 *** Cannot bootstrap myself. :-( Installation terminated.
644 .
645 }
646
647 # check if we're connected to some host, using inet_aton
648 sub _connected_to {
649 my $site = shift;
650
651 return (
652 ( _load('Socket') and Socket::inet_aton($site) ) or _prompt(
653 qq(
654 *** Your host cannot resolve the domain name '$site', which
655 probably means the Internet connections are unavailable.
656 ==> Should we try to install the required module(s) anyway?), 'n'
657 ) =~ /^[Yy]/
658 );
659 }
660
661 # check if a directory is writable; may create it on demand
662 sub _can_write {
663 my $path = shift;
664 mkdir( $path, 0755 ) unless -e $path;
665
666 return 1 if -w $path;
667
668 print << ".";
669 *** You are not allowed to write to the directory '$path';
670 the installation may fail due to insufficient permissions.
671 .
672
673 if (
674 eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt(
675 qq(
676 ==> Should we try to re-execute the autoinstall process with 'sudo'?),
677 ((-t STDIN) ? 'y' : 'n')
678 ) =~ /^[Yy]/
679 )
680 {
681
682 # try to bootstrap ourselves from sudo
683 print << ".";
684 *** Trying to re-execute the autoinstall process with 'sudo'...
685 .
686 my $missing = join( ',', @Missing );
687 my $config = join( ',',
688 UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
689 if $Config;
690
691 return
692 unless system( 'sudo', $^X, $0, "--config=$config",
693 "--installdeps=$missing" );
694
695 print << ".";
696 *** The 'sudo' command exited with error! Resuming...
697 .
698 }
699
700 return _prompt(
701 qq(
702 ==> Should we try to install the required module(s) anyway?), 'n'
703 ) =~ /^[Yy]/;
704 }
705
706 # load a module and return the version it reports
707 sub _load {
708 my $mod = pop; # class/instance doesn't matter
709 my $file = $mod;
710
711 $file =~ s|::|/|g;
712 $file .= '.pm';
713
714 local $@;
715 return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 );
716 }
717
718 # Load CPAN.pm and it's configuration
719 sub _load_cpan {
720 return if $CPAN::VERSION and $CPAN::Config and not @_;
721 require CPAN;
722
723 # CPAN-1.82+ adds CPAN::Config::AUTOLOAD to redirect to
724 # CPAN::HandleConfig->load. CPAN reports that the redirection
725 # is deprecated in a warning printed at the user.
726
727 # CPAN-1.81 expects CPAN::HandleConfig->load, does not have
728 # $CPAN::HandleConfig::VERSION but cannot handle
729 # CPAN::Config->load
730
731 # Which "versions expect CPAN::Config->load?
732
733 if ( $CPAN::HandleConfig::VERSION
734 || CPAN::HandleConfig->can('load')
735 ) {
736 # Newer versions of CPAN have a HandleConfig module
737 CPAN::HandleConfig->load;
738 } else {
739 # Older versions had the load method in Config directly
740 CPAN::Config->load;
741 }
742 }
743
744 # compare two versions, either use Sort::Versions or plain comparison
745 # return values same as <=>
746 sub _version_cmp {
747 my ( $cur, $min ) = @_;
748 return -1 unless defined $cur; # if 0 keep comparing
749 return 1 unless $min;
750
751 $cur =~ s/\s+$//;
752
753 # check for version numbers that are not in decimal format
754 if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) {
755 if ( ( $version::VERSION or defined( _load('version') )) and
756 version->can('new')
757 ) {
758
759 # use version.pm if it is installed.
760 return version->new($cur) <=> version->new($min);
761 }
762 elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) )
763 {
764
765 # use Sort::Versions as the sorting algorithm for a.b.c versions
766 return Sort::Versions::versioncmp( $cur, $min );
767 }
768
769 warn "Cannot reliably compare non-decimal formatted versions.\n"
770 . "Please install version.pm or Sort::Versions.\n";
771 }
772
773 # plain comparison
774 local $^W = 0; # shuts off 'not numeric' bugs
775 return $cur <=> $min;
776 }
777
778 # nothing; this usage is deprecated.
779 sub main::PREREQ_PM { return {}; }
780
781 sub _make_args {
782 my %args = @_;
783
784 $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing }
785 if $UnderCPAN or $TestOnly;
786
787 if ( $args{EXE_FILES} and -e 'MANIFEST' ) {
788 require ExtUtils::Manifest;
789 my $manifest = ExtUtils::Manifest::maniread('MANIFEST');
790
791 $args{EXE_FILES} =
792 [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ];
793 }
794
795 $args{test}{TESTS} ||= 't/*.t';
796 $args{test}{TESTS} = join( ' ',
797 grep { !exists( $DisabledTests{$_} ) }
798 map { glob($_) } split( /\s+/, $args{test}{TESTS} ) );
799
800 my $missing = join( ',', @Missing );
801 my $config =
802 join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} )
803 if $Config;
804
805 $PostambleActions = (
806 ($missing and not $UnderCPAN)
807 ? "\$(PERL) $0 --config=$config --installdeps=$missing"
808 : "\$(NOECHO) \$(NOOP)"
809 );
810
811 my $deps_list = join( ',', @Missing, @Existing );
812
813 $PostambleActionsUpgradeDeps =
814 "\$(PERL) $0 --config=$config --upgradedeps=$deps_list";
815
816 my $config_notest =
817 join( ',', (UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config}),
818 'notest', 1 )
819 if $Config;
820
821 $PostambleActionsNoTest = (
822 ($missing and not $UnderCPAN)
823 ? "\$(PERL) $0 --config=$config_notest --installdeps=$missing"
824 : "\$(NOECHO) \$(NOOP)"
825 );
826
827 $PostambleActionsUpgradeDepsNoTest =
828 "\$(PERL) $0 --config=$config_notest --upgradedeps=$deps_list";
829
830 $PostambleActionsListDeps =
831 '@$(PERL) -le "print for @ARGV" '
832 . join(' ', map $Missing[$_], grep $_ % 2 == 0, 0..$#Missing);
833
834 my @all = (@Missing, @Existing);
835
836 $PostambleActionsListAllDeps =
837 '@$(PERL) -le "print for @ARGV" '
838 . join(' ', map $all[$_], grep $_ % 2 == 0, 0..$#all);
839
840 return %args;
841 }
842
843 # a wrapper to ExtUtils::MakeMaker::WriteMakefile
844 sub Write {
845 require Carp;
846 Carp::croak "WriteMakefile: Need even number of args" if @_ % 2;
847
848 if ($CheckOnly) {
849 print << ".";
850 *** Makefile not written in check-only mode.
851 .
852 return;
853 }
854
855 my %args = _make_args(@_);
856
857 no strict 'refs';
858
859 $PostambleUsed = 0;
860 local *MY::postamble = \&postamble unless defined &MY::postamble;
861 ExtUtils::MakeMaker::WriteMakefile(%args);
862
863 print << "." unless $PostambleUsed;
864 *** WARNING: Makefile written with customized MY::postamble() without
865 including contents from Module::AutoInstall::postamble() --
866 auto installation features disabled. Please contact the author.
867 .
868
869 return 1;
870 }
871
872 sub postamble {
873 $PostambleUsed = 1;
874 my $fragment;
875
876 $fragment .= <<"AUTO_INSTALL" if !$InstallDepsTarget;
877
878 config :: installdeps
879 \t\$(NOECHO) \$(NOOP)
880 AUTO_INSTALL
881
882 $fragment .= <<"END_MAKE";
883
884 checkdeps ::
885 \t\$(PERL) $0 --checkdeps
886
887 installdeps ::
888 \t$PostambleActions
889
890 installdeps_notest ::
891 \t$PostambleActionsNoTest
892
893 upgradedeps ::
894 \t$PostambleActionsUpgradeDeps
895
896 upgradedeps_notest ::
897 \t$PostambleActionsUpgradeDepsNoTest
898
899 listdeps ::
900 \t$PostambleActionsListDeps
901
902 listalldeps ::
903 \t$PostambleActionsListAllDeps
904
905 END_MAKE
906
907 return $fragment;
908 }
909
910 1;
911
912 __END__
913
914 #line 1178
0 #line 1
1 package Module::Install::AutoInstall;
2
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.02';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
11 }
12
13 sub AutoInstall { $_[0] }
14
15 sub run {
16 my $self = shift;
17 $self->auto_install_now(@_);
18 }
19
20 sub write {
21 my $self = shift;
22 $self->auto_install(@_);
23 }
24
25 sub auto_install {
26 my $self = shift;
27 return if $self->{done}++;
28
29 # Flatten array of arrays into a single array
30 my @core = map @$_, map @$_, grep ref,
31 $self->build_requires, $self->requires;
32
33 my @config = @_;
34
35 # We'll need Module::AutoInstall
36 $self->include('Module::AutoInstall');
37 require Module::AutoInstall;
38
39 my @features_require = Module::AutoInstall->import(
40 (@config ? (-config => \@config) : ()),
41 (@core ? (-core => \@core) : ()),
42 $self->features,
43 );
44
45 my %seen;
46 my @requires = map @$_, map @$_, grep ref, $self->requires;
47 while (my ($mod, $ver) = splice(@requires, 0, 2)) {
48 $seen{$mod}{$ver}++;
49 }
50 my @build_requires = map @$_, map @$_, grep ref, $self->build_requires;
51 while (my ($mod, $ver) = splice(@build_requires, 0, 2)) {
52 $seen{$mod}{$ver}++;
53 }
54 my @configure_requires = map @$_, map @$_, grep ref, $self->configure_requires;
55 while (my ($mod, $ver) = splice(@configure_requires, 0, 2)) {
56 $seen{$mod}{$ver}++;
57 }
58
59 my @deduped;
60 while (my ($mod, $ver) = splice(@features_require, 0, 2)) {
61 push @deduped, $mod => $ver unless $seen{$mod}{$ver}++;
62 }
63
64 $self->requires(@deduped);
65
66 $self->makemaker_args( Module::AutoInstall::_make_args() );
67
68 my $class = ref($self);
69 $self->postamble(
70 "# --- $class section:\n" .
71 Module::AutoInstall::postamble()
72 );
73 }
74
75 sub installdeps_target {
76 my ($self, @args) = @_;
77
78 $self->include('Module::AutoInstall');
79 require Module::AutoInstall;
80
81 Module::AutoInstall::_installdeps_target(1);
82
83 $self->auto_install(@args);
84 }
85
86 sub auto_install_now {
87 my $self = shift;
88 $self->auto_install(@_);
89 Module::AutoInstall::do_install();
90 }
91
92 1;
0 #line 1
1 use strict;
2 use warnings;
3
4 package Module::Install::AutoManifest;
5
6 use Module::Install::Base;
7
8 BEGIN {
9 our $VERSION = '0.003';
10 our $ISCORE = 1;
11 our @ISA = qw(Module::Install::Base);
12 }
13
14 sub auto_manifest {
15 my ($self) = @_;
16
17 return unless $Module::Install::AUTHOR;
18
19 die "auto_manifest requested, but no MANIFEST.SKIP exists\n"
20 unless -e "MANIFEST.SKIP";
21
22 if (-e "MANIFEST") {
23 unlink('MANIFEST') or die "Can't remove MANIFEST: $!";
24 }
25
26 $self->postamble(<<"END");
27 create_distdir: manifest_clean manifest
28
29 distclean :: manifest_clean
30
31 manifest_clean:
32 \t\$(RM_F) MANIFEST
33 END
34
35 }
36
37 1;
38 __END__
39
40 #line 48
41
42 #line 131
43
44 1; # End of Module::Install::AutoManifest
0 #line 1
1 package Module::Install::Base;
2
3 use strict 'vars';
4 use vars qw{$VERSION};
5 BEGIN {
6 $VERSION = '1.02';
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
16
17 sub new {
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;
26 }
27
28 #line 61
29
30 sub AUTOLOAD {
31 local $@;
32 my $func = eval { shift->_top->autoload } or return;
33 goto &$func;
34 }
35
36 #line 75
37
38 sub _top {
39 $_[0]->{_top};
40 }
41
42 #line 90
43
44 sub admin {
45 $_[0]->_top->{admin}
46 or
47 Module::Install::Base::FakeAdmin->new;
48 }
49
50 #line 106
51
52 sub is_admin {
53 ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin');
54 }
55
56 sub DESTROY {}
57
58 package Module::Install::Base::FakeAdmin;
59
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
71 sub AUTOLOAD {}
72
73 sub DESTROY {}
74
75 # Restore warning handler
76 BEGIN {
77 $SIG{__WARN__} = $SIG{__WARN__}->();
78 }
79
80 1;
81
82 #line 159
0 #line 1
1 package Module::Install::Can;
2
3 use strict;
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.02';
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 }
30
31 # check if we can run some command
32 sub can_run {
33 my ($self, $cmd) = @_;
34
35 my $_cmd = $cmd;
36 return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));
37
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 }
43
44 return;
45 }
46
47 # can we locate a (the) C compiler
48 sub can_cc {
49 my $self = shift;
50 my @chunks = split(/ /, $Config::Config{cc}) or return;
51
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 }
56
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 }
74 }
75
76 1;
77
78 __END__
79
80 #line 156
0 #line 1
1 package Module::Install::Fetch;
2
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.02';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
11 }
12
13 sub get_file {
14 my ($self, %args) = @_;
15 my ($scheme, $host, $path, $file) =
16 $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
17
18 if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) {
19 $args{url} = $args{ftp_url}
20 or (warn("LWP support unavailable!\n"), return);
21 ($scheme, $host, $path, $file) =
22 $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
23 }
24
25 $|++;
26 print "Fetching '$file' from $host... ";
27
28 unless (eval { require Socket; Socket::inet_aton($host) }) {
29 warn "'$host' resolve failed!\n";
30 return;
31 }
32
33 return unless $scheme eq 'ftp' or $scheme eq 'http';
34
35 require Cwd;
36 my $dir = Cwd::getcwd();
37 chdir $args{local_dir} or return if exists $args{local_dir};
38
39 if (eval { require LWP::Simple; 1 }) {
40 LWP::Simple::mirror($args{url}, $file);
41 }
42 elsif (eval { require Net::FTP; 1 }) { eval {
43 # use Net::FTP to get past firewall
44 my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600);
45 $ftp->login("anonymous", 'anonymous@example.com');
46 $ftp->cwd($path);
47 $ftp->binary;
48 $ftp->get($file) or (warn("$!\n"), return);
49 $ftp->quit;
50 } }
51 elsif (my $ftp = $self->can_run('ftp')) { eval {
52 # no Net::FTP, fallback to ftp.exe
53 require FileHandle;
54 my $fh = FileHandle->new;
55
56 local $SIG{CHLD} = 'IGNORE';
57 unless ($fh->open("|$ftp -n")) {
58 warn "Couldn't open ftp: $!\n";
59 chdir $dir; return;
60 }
61
62 my @dialog = split(/\n/, <<"END_FTP");
63 open $host
64 user anonymous anonymous\@example.com
65 cd $path
66 binary
67 get $file $file
68 quit
69 END_FTP
70 foreach (@dialog) { $fh->print("$_\n") }
71 $fh->close;
72 } }
73 else {
74 warn "No working 'ftp' program available!\n";
75 chdir $dir; return;
76 }
77
78 unless (-f $file) {
79 warn "Fetching failed: $@\n";
80 chdir $dir; return;
81 }
82
83 return if exists $args{size} and -s $file != $args{size};
84 system($args{run}) if exists $args{run};
85 unlink($file) if $args{remove};
86
87 print(((!exists $args{check_for} or -e $args{check_for})
88 ? "done!" : "failed! ($!)"), "\n");
89 chdir $dir; return !$?;
90 }
91
92 1;
0 #line 1
1 package Module::Install::Include;
2
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.02';
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 }
32
33 1;
0 #line 1
1 package Module::Install::Makefile;
2
3 use strict 'vars';
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.02';
11 @ISA = 'Module::Install::Base';
12 $ISCORE = 1;
13 }
14
15 sub Makefile { $_[0] }
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 );
99
100 sub makemaker_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 }
152 }
153
154 sub 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
197 );
198 $self->tests( join ' ', sort keys %tests );
199 }
200
201 sub write {
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');
351 }
352
353 sub fix_up_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;
395 }
396
397 sub preamble {
398 my ($self, $text) = @_;
399 $self->{preamble} = $text . $self->{preamble} if defined $text;
400 $self->{preamble};
401 }
402
403 sub postamble {
404 my ($self, $text) = @_;
405 $self->{postamble} ||= $self->admin->postamble;
406 $self->{postamble} .= $text if defined $text;
407 $self->{postamble}
408 }
409
410 1;
411
412 __END__
413
414 #line 541
0 #line 1
1 package Module::Install::Metadata;
2
3 use strict 'vars';
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.02';
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 really 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,
467 );
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 2\.0' => 'artistic_2', 1,
518 'Artistic license' => 'artistic', 1,
519 'Apache (?:Software )?license' => 'apache', 1,
520 'GPL' => 'gpl', 1,
521 'LGPL' => 'lgpl', 1,
522 'BSD' => 'bsd', 1,
523 'Artistic' => 'artistic', 1,
524 'MIT' => 'mit', 1,
525 'Mozilla Public License' => 'mozilla', 1,
526 'Q Public License' => 'open_source', 1,
527 'OpenSSL License' => 'unrestricted', 1,
528 'SSLeay License' => 'unrestricted', 1,
529 'zlib License' => 'open_source', 1,
530 'proprietary' => 'proprietary', 0,
531 );
532 while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
533 $pattern =~ s#\s+#\\s+#gs;
534 if ( $license_text =~ /\b$pattern\b/i ) {
535 return $license;
536 }
537 }
538 return '';
539 }
540
541 sub license_from {
542 my $self = shift;
543 if (my $license=_extract_license(Module::Install::_read($_[0]))) {
544 $self->license($license);
545 } else {
546 warn "Cannot determine license info from $_[0]\n";
547 return 'unknown';
548 }
549 }
550
551 sub _extract_bugtracker {
552 my @links = $_[0] =~ m#L<(
553 https?\Q://rt.cpan.org/\E[^>]+|
554 https?\Q://github.com/\E[\w_]+/[\w_]+/issues|
555 https?\Q://code.google.com/p/\E[\w_\-]+/issues/list
556 )>#gx;
557 my %links;
558 @links{@links}=();
559 @links=keys %links;
560 return @links;
561 }
562
563 sub bugtracker_from {
564 my $self = shift;
565 my $content = Module::Install::_read($_[0]);
566 my @links = _extract_bugtracker($content);
567 unless ( @links ) {
568 warn "Cannot determine bugtracker info from $_[0]\n";
569 return 0;
570 }
571 if ( @links > 1 ) {
572 warn "Found more than one bugtracker link in $_[0]\n";
573 return 0;
574 }
575
576 # Set the bugtracker
577 bugtracker( $links[0] );
578 return 1;
579 }
580
581 sub requires_from {
582 my $self = shift;
583 my $content = Module::Install::_readperl($_[0]);
584 my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(v?[\d\.]+)/mg;
585 while ( @requires ) {
586 my $module = shift @requires;
587 my $version = shift @requires;
588 $self->requires( $module => $version );
589 }
590 }
591
592 sub test_requires_from {
593 my $self = shift;
594 my $content = Module::Install::_readperl($_[0]);
595 my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg;
596 while ( @requires ) {
597 my $module = shift @requires;
598 my $version = shift @requires;
599 $self->test_requires( $module => $version );
600 }
601 }
602
603 # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to
604 # numbers (eg, 5.006001 or 5.008009).
605 # Also, convert double-part versions (eg, 5.8)
606 sub _perl_version {
607 my $v = $_[-1];
608 $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e;
609 $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e;
610 $v =~ s/(\.\d\d\d)000$/$1/;
611 $v =~ s/_.+$//;
612 if ( ref($v) ) {
613 # Numify
614 $v = $v + 0;
615 }
616 return $v;
617 }
618
619 sub add_metadata {
620 my $self = shift;
621 my %hash = @_;
622 for my $key (keys %hash) {
623 warn "add_metadata: $key is not prefixed with 'x_'.\n" .
624 "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/;
625 $self->{values}->{$key} = $hash{$key};
626 }
627 }
628
629
630 ######################################################################
631 # MYMETA Support
632
633 sub WriteMyMeta {
634 die "WriteMyMeta has been deprecated";
635 }
636
637 sub write_mymeta_yaml {
638 my $self = shift;
639
640 # We need YAML::Tiny to write the MYMETA.yml file
641 unless ( eval { require YAML::Tiny; 1; } ) {
642 return 1;
643 }
644
645 # Generate the data
646 my $meta = $self->_write_mymeta_data or return 1;
647
648 # Save as the MYMETA.yml file
649 print "Writing MYMETA.yml\n";
650 YAML::Tiny::DumpFile('MYMETA.yml', $meta);
651 }
652
653 sub write_mymeta_json {
654 my $self = shift;
655
656 # We need JSON to write the MYMETA.json file
657 unless ( eval { require JSON; 1; } ) {
658 return 1;
659 }
660
661 # Generate the data
662 my $meta = $self->_write_mymeta_data or return 1;
663
664 # Save as the MYMETA.yml file
665 print "Writing MYMETA.json\n";
666 Module::Install::_write(
667 'MYMETA.json',
668 JSON->new->pretty(1)->canonical->encode($meta),
669 );
670 }
671
672 sub _write_mymeta_data {
673 my $self = shift;
674
675 # If there's no existing META.yml there is nothing we can do
676 return undef unless -f 'META.yml';
677
678 # We need Parse::CPAN::Meta to load the file
679 unless ( eval { require Parse::CPAN::Meta; 1; } ) {
680 return undef;
681 }
682
683 # Merge the perl version into the dependencies
684 my $val = $self->Meta->{values};
685 my $perl = delete $val->{perl_version};
686 if ( $perl ) {
687 $val->{requires} ||= [];
688 my $requires = $val->{requires};
689
690 # Canonize to three-dot version after Perl 5.6
691 if ( $perl >= 5.006 ) {
692 $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e
693 }
694 unshift @$requires, [ perl => $perl ];
695 }
696
697 # Load the advisory META.yml file
698 my @yaml = Parse::CPAN::Meta::LoadFile('META.yml');
699 my $meta = $yaml[0];
700
701 # Overwrite the non-configure dependency hashs
702 delete $meta->{requires};
703 delete $meta->{build_requires};
704 delete $meta->{recommends};
705 if ( exists $val->{requires} ) {
706 $meta->{requires} = { map { @$_ } @{ $val->{requires} } };
707 }
708 if ( exists $val->{build_requires} ) {
709 $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } };
710 }
711
712 return $meta;
713 }
714
715 1;
0 #line 1
1 ##
2 # name: Module::Install::Package
3 # abstract: Module::Install support for Module::Package
4 # author: Ingy döt Net <ingy@cpan.org>
5 # license: perl
6 # copyright: 2011
7 # see:
8 # - Module::Package
9
10 # This module contains the Module::Package logic that must be available to
11 # both the Author and the End User. Author-only logic goes in a
12 # Module::Package::Plugin subclass.
13 package Module::Install::Package;
14 use strict;
15 use Module::Install::Base;
16 use vars qw'@ISA $VERSION';
17 @ISA = 'Module::Install::Base';
18 $VERSION = '0.30';
19
20 #-----------------------------------------------------------------------------#
21 # XXX BOOTBUGHACK
22 # This is here to try to get us out of Module-Package-0.11 cpantesters hell...
23 # Remove this when the situation has blown over.
24 sub pkg {
25 *inc::Module::Package::VERSION = sub { $VERSION };
26 my $self = shift;
27 $self->module_package_internals_init($@);
28 }
29
30 #-----------------------------------------------------------------------------#
31 # We allow the author to specify key/value options after the plugin. These
32 # options need to be available both at author time and install time.
33 #-----------------------------------------------------------------------------#
34 # OO accessor for command line options:
35 sub package_options {
36 @_>1?($_[0]->{package_options}=$_[1]):$_[0]->{package_options}}
37
38 my $default_options = {
39 deps_list => 1,
40 install_bin => 1,
41 install_share => 1,
42 manifest_skip => 1,
43 requires_from => 1,
44 };
45
46 #-----------------------------------------------------------------------------#
47 # Module::Install plugin directives. Use long, ugly names to not pollute the
48 # Module::Install plugin namespace. These are only intended to be called from
49 # Module::Package.
50 #-----------------------------------------------------------------------------#
51
52 # Module::Package starts off life as a normal call to this Module::Install
53 # plugin directive:
54 my $module_install_plugin;
55 my $module_package_plugin;
56 my $module_package_dist_plugin;
57 # XXX ARGVHACK This @argv thing is a temporary fix for an ugly bug somewhere in the
58 # Wikitext module usage.
59 my @argv;
60 sub module_package_internals_init {
61 my $self = $module_install_plugin = shift;
62 my ($plugin_spec, %options) = @_;
63 $self->package_options({%$default_options, %options});
64
65 if ($module_install_plugin->is_admin) {
66 $module_package_plugin = $self->_load_plugin($plugin_spec);
67 $module_package_plugin->mi($module_install_plugin);
68 $module_package_plugin->version_check($VERSION);
69 }
70 else {
71 $module_package_dist_plugin = $self->_load_dist_plugin($plugin_spec);
72 $module_package_dist_plugin->mi($module_install_plugin) if ref $module_package_dist_plugin;
73 }
74 # NOTE - This is the point in time where the body of Makefile.PL runs...
75 return;
76
77 sub INIT {
78 return unless $module_install_plugin;
79 return if $Module::Package::ERROR;
80 eval {
81 if ($module_install_plugin->is_admin) {
82 $module_package_plugin->initial();
83 $module_package_plugin->main();
84 }
85 else {
86 $module_install_plugin->_initial();
87 $module_package_dist_plugin->_initial() if ref $module_package_dist_plugin;
88 $module_install_plugin->_main();
89 $module_package_dist_plugin->_main() if ref $module_package_dist_plugin;
90 }
91 };
92 if ($@) {
93 $Module::Package::ERROR = $@;
94 die $@;
95 }
96 @argv = @ARGV; # XXX ARGVHACK
97 }
98
99 # If this Module::Install plugin was used (by Module::Package) then wrap
100 # up any loose ends. This will get called after Makefile.PL has completed.
101 sub END {
102 @ARGV = @argv; # XXX ARGVHACK
103 return unless $module_install_plugin;
104 return if $Module::Package::ERROR;
105 $module_package_plugin
106 ? do {
107 $module_package_plugin->final;
108 $module_package_plugin->replicate_module_package;
109 }
110 : do {
111 $module_install_plugin->_final;
112 $module_package_dist_plugin->_final() if ref $module_package_dist_plugin;
113 }
114 }
115 }
116
117 # Module::Package, Module::Install::Package and Module::Package::Plugin
118 # must all have the same version. Seems wise.
119 sub module_package_internals_version_check {
120 my ($self, $version) = @_;
121 return if $version < 0.1800001; # XXX BOOTBUGHACK!!
122 die <<"..." unless $version == $VERSION;
123
124 Error! Something has gone awry:
125 Module::Package version=$version is using
126 Module::Install::Package version=$VERSION
127 If you are the author of this module, try upgrading Module::Package.
128 Otherwise, please notify the author of this error.
129
130 ...
131 }
132
133 # Find and load the author side plugin:
134 sub _load_plugin {
135 my ($self, $spec, $namespace) = @_;
136 $spec ||= '';
137 $namespace ||= 'Module::Package';
138 my $version = '';
139 $Module::Package::plugin_version = 0;
140 if ($spec =~ s/\s+(\S+)\s*//) {
141 $version = $1;
142 $Module::Package::plugin_version = $version;
143 }
144 my ($module, $plugin) =
145 not($spec) ? ('Plugin', "Plugin::basic") :
146 ($spec =~ /^\w(\w|::)*$/) ? ($spec, $spec) :
147 ($spec =~ /^:(\w+)$/) ? ('Plugin', "Plugin::$1") :
148 ($spec =~ /^(\S*\w):(\w+)$/) ? ($1, "$1::$2") :
149 die "$spec is invalid";
150 $module = "${namespace}::${module}";
151 $plugin = "${namespace}::${plugin}";
152 eval "use $module $version (); 1" or die $@;
153 return $plugin->new();
154 }
155
156 # Find and load the user side plugin:
157 sub _load_dist_plugin {
158 my ($self, $spec, $namespace) = @_;
159 $spec ||= '';
160 $namespace ||= 'Module::Package::Dist';
161 my $r = eval { $self->_load_plugin($spec, $namespace); };
162 return $r if ref $r;
163 return;
164 }
165
166 #-----------------------------------------------------------------------------#
167 # These are the user side analogs to the author side plugin API calls.
168 # Prefix with '_' to not pollute Module::Install plugin space.
169 #-----------------------------------------------------------------------------#
170 sub _initial {
171 my ($self) = @_;
172 }
173
174 sub _main {
175 my ($self) = @_;
176 }
177
178 # NOTE These must match Module::Package::Plugin::final.
179 sub _final {
180 my ($self) = @_;
181 $self->_all_from;
182 $self->_requires_from;
183 $self->_install_bin;
184 $self->_install_share;
185 $self->_WriteAll;
186 }
187
188 #-----------------------------------------------------------------------------#
189 # This section is where all the useful code bits go. These bits are needed by
190 # both Author and User side runs.
191 #-----------------------------------------------------------------------------#
192
193 my $all_from = 0;
194 sub _all_from {
195 my $self = shift;
196 return if $all_from++;
197 return if $self->name;
198 my $file = shift || "$main::PM" or die "all_from has no file";
199 $self->all_from($file);
200 }
201
202 my $requires_from = 0;
203 sub _requires_from {
204 my $self = shift;
205 return if $requires_from++;
206 return unless $self->package_options->{requires_from};
207 my $file = shift || "$main::PM" or die "requires_from has no file";
208 $self->requires_from($main::PM)
209 }
210
211 my $install_bin = 0;
212 sub _install_bin {
213 my $self = shift;
214 return if $install_bin++;
215 return unless $self->package_options->{install_bin};
216 return unless -d 'bin';
217 my @bin;
218 File::Find::find(sub {
219 return unless -f $_;
220 push @bin, $File::Find::name;
221 }, 'bin');
222 $self->install_script($_) for @bin;
223 }
224
225 my $install_share = 0;
226 sub _install_share {
227 my $self = shift;
228 return if $install_share++;
229 return unless $self->package_options->{install_share};
230 return unless -d 'share';
231 $self->install_share;
232 }
233
234 my $WriteAll = 0;
235 sub _WriteAll {
236 my $self = shift;
237 return if $WriteAll++;
238 $self->WriteAll(@_);
239 }
240
241 # Base package for Module::Package plugin distributed components.
242 package Module::Package::Dist;
243
244 sub new {
245 my ($class, %args) = @_;
246 bless \%args, $class;
247 }
248
249 sub mi {
250 @_ > 1 ? ($_[0]->{mi}=$_[1]) : $_[0]->{mi};
251 }
252
253 sub _initial {
254 my ($self) = @_;
255 }
256
257 sub _main {
258 my ($self) = @_;
259 }
260
261 sub _final {
262 my ($self) = @_;
263 }
264
265 1;
266
267 #-----------------------------------------------------------------------------#
268 # Take a guess at the primary .pm and .pod files for 'all_from', and friends.
269 # Put them in global magical vars in the main:: namespace.
270 #-----------------------------------------------------------------------------#
271 package Module::Package::PM;
272 use overload '""' => sub {
273 $_[0]->guess_pm unless @{$_[0]};
274 return $_[0]->[0];
275 };
276 sub set { $_[0]->[0] = $_[1] }
277 sub guess_pm {
278 my $pm = '';
279 my $self = shift;
280 if (-e 'META.yml') {
281 open META, 'META.yml' or die "Can't open 'META.yml' for input:\n$!";
282 my $meta = do { local $/; <META> };
283 close META;
284 $meta =~ /^module_name: (\S+)$/m
285 or die "Can't get module_name from META.yml";
286 $pm = $1;
287 $pm =~ s!::!/!g;
288 $pm = "lib/$pm.pm";
289 }
290 else {
291 require File::Find;
292 my @array = ();
293 File::Find::find(sub {
294 return unless /\.pm$/;
295 my $name = $File::Find::name;
296 my $num = ($name =~ s!/+!/!g);
297 my $ary = $array[$num] ||= [];
298 push @$ary, $name;
299 }, 'lib');
300 shift @array while @array and not defined $array[0];
301 die "Can't guess main module" unless @array;
302 (($pm) = sort @{$array[0]}) or
303 die "Can't guess main module";
304 }
305 my $pmc = $pm . 'c';
306 $pm = $pmc if -e $pmc;
307 $self->set($pm);
308 }
309 $main::PM = bless [$main::PM ? ($main::PM) : ()], __PACKAGE__;
310
311 package Module::Package::POD;
312 use overload '""' => sub {
313 return $_[0]->[0] if @{$_[0]};
314 (my $pod = "$main::PM") =~ s/\.pm/.pod/
315 or die "Module::Package's \$main::PM value should end in '.pm'";
316 return -e $pod ? $pod : '';
317 };
318 sub set { $_[0][0] = $_[1] }
319 $main::POD = bless [$main::POD ? ($main::POD) : ()], __PACKAGE__;
320
321 1;
322
0 #line 1
1 package Module::Install::TrustMetaYml;
2
3 use 5.008;
4 use constant { FALSE => 0, TRUE => 1 };
5 use strict;
6 use utf8;
7
8 BEGIN {
9 $Module::Install::TrustMetaYml::AUTHORITY = 'cpan:TOBYINK';
10 }
11 BEGIN {
12 $Module::Install::TrustMetaYml::VERSION = '0.001';
13 }
14
15 use base qw(Module::Install::Base);
16
17 sub trust_meta_yml
18 {
19 my ($self, $where) = @_;
20 $where ||= 'META.yml';
21
22 $self->perl_version('5.006') unless defined $self->perl_version;
23
24 $self->include_deps('YAML::Tiny', 0);
25 return $self if $self->is_admin;
26
27 require YAML::Tiny;
28 my $data = YAML::Tiny::LoadFile($where);
29
30 $self->perl_version($data->{requires}{perl} || '5.006');
31
32 KEY: foreach my $key (qw(requires recommends build_requires))
33 {
34 next KEY unless ref $data->{$key} eq 'HASH';
35 my %deps = %{$data->{$key}};
36 DEP: while (my ($pkg, $ver) = each %deps)
37 {
38 next if $pkg eq 'perl';
39 $self->$key($pkg, $ver);
40 }
41 }
42
43 return $self;
44 }
45
46 *trust_meta_yaml = \&trust_meta_yml;
47
48 TRUE;
49
50 __END__
51
0 #line 1
1 package Module::Install::Win32;
2
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.02';
9 @ISA = 'Module::Install::Base';
10 $ISCORE = 1;
11 }
12
13 # determine if the user needs nmake, and download it if needed
14 sub check_nmake {
15 my $self = shift;
16 $self->load('can_run');
17 $self->load('get_file');
18
19 require Config;
20 return unless (
21 $^O eq 'MSWin32' and
22 $Config::Config{make} and
23 $Config::Config{make} =~ /^nmake\b/i and
24 ! $self->can_run('nmake')
25 );
26
27 print "The required 'nmake' executable not found, fetching it...\n";
28
29 require File::Basename;
30 my $rv = $self->get_file(
31 url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe',
32 ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe',
33 local_dir => File::Basename::dirname($^X),
34 size => 51928,
35 run => 'Nmake15.exe /o > nul',
36 check_for => 'Nmake.exe',
37 remove => 1,
38 );
39
40 die <<'END_MESSAGE' unless $rv;
41
42 -------------------------------------------------------------------------------
43
44 Since you are using Microsoft Windows, you will need the 'nmake' utility
45 before installation. It's available at:
46
47 http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe
48 or
49 ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe
50
51 Please download the file manually, save it to a directory in %PATH% (e.g.
52 C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to
53 that directory, and run "Nmake15.exe" from there; that will create the
54 'nmake.exe' file needed by this module.
55
56 You may then resume the installation process described in README.
57
58 -------------------------------------------------------------------------------
59 END_MESSAGE
60
61 }
62
63 1;
0 #line 1
1 package Module::Install::WriteAll;
2
3 use strict;
4 use Module::Install::Base ();
5
6 use vars qw{$VERSION @ISA $ISCORE};
7 BEGIN {
8 $VERSION = '1.02';
9 @ISA = qw{Module::Install::Base};
10 $ISCORE = 1;
11 }
12
13 sub WriteAll {
14 my $self = shift;
15 my %args = (
16 meta => 1,
17 sign => 0,
18 inline => 0,
19 check_nmake => 1,
20 @_,
21 );
22
23 $self->sign(1) if $args{sign};
24 $self->admin->WriteAll(%args) if $self->is_admin;
25
26 $self->check_nmake if $args{check_nmake};
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 }
33
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;
60 }
61
62 1;
0 #line 1
1 package Module::Install;
2
3 # For any maintainers:
4 # The load order for Module::Install is a bit magic.
5 # It goes something like this...
6 #
7 # IF ( host has Module::Install installed, creating author mode ) {
8 # 1. Makefile.PL calls "use inc::Module::Install"
9 # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
10 # 3. The installed version of inc::Module::Install loads
11 # 4. inc::Module::Install calls "require Module::Install"
12 # 5. The ./inc/ version of Module::Install loads
13 # } ELSE {
14 # 1. Makefile.PL calls "use inc::Module::Install"
15 # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
16 # 3. The ./inc/ version of Module::Install loads
17 # }
18
19 use 5.005;
20 use strict 'vars';
21 use Cwd ();
22 use File::Find ();
23 use File::Path ();
24
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.02';
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 }
42
43 sub import {
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 }
154
155 sub autoload {
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 }
228
229 sub new {
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 }
263
264 sub call {
265 my ($self, $method) = @_;
266 my $obj = $self->load($method) or return;
267 splice(@_, 0, 2, $obj);
268 goto &{$obj->can($method)};
269 }
270
271 sub load {
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";
283 The '$method' method does not exist in the '$self->{prefix}' path!
284 Please remove the '$self->{prefix}' directory and run $0 again to load it.
285 END_DIE
286
287 my $obj = $admin->load($method, 1);
288 push @{$self->{extensions}}, $obj;
289
290 $obj;
291 }
292
293 sub load_extensions {
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 }
319
320 sub find_extensions {
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;
465 }
466
467 1;
468
469 # Copyright 2008 - 2011 Adam Kennedy.
0 #line 1
1 package Module::Package::Dist::RDF;
2
3 use 5.008003;
4 BEGIN {
5 $Module::Package::Dist::RDF::AUTHORITY = 'cpan:TOBYINK';
6 $Module::Package::Dist::RDF::VERSION = '0.005';
7 }
8
9 package Module::Package::Dist::RDF::standard;
10
11 use 5.008003;
12 use strict;
13 use base qw[Module::Package::Dist];
14 BEGIN {
15 $Module::Package::Dist::RDF::standard::AUTHORITY = 'cpan:TOBYINK';
16 $Module::Package::Dist::RDF::standard::VERSION = '0.005';
17 }
18
19 sub _main
20 {
21 my ($self) = @_;
22 $self->mi->trust_meta_yml;
23 $self->mi->auto_install;
24 }
25
26 1;
0 #line 1
1 ##
2 # name: Module::Package
3 # abstract: Postmodern Perl Module Packaging
4 # author: Ingy döt Net <ingy@cpan.org>
5 # license: perl
6 # copyright: 2011
7 # see:
8 # - Module::Package::Plugin
9 # - Module::Install::Package
10 # - Module::Package::Tutorial
11
12 package Module::Package;
13 use 5.005;
14 use strict;
15
16 BEGIN {
17 $Module::Package::VERSION = '0.30';
18 $inc::Module::Package::VERSION ||= $Module::Package::VERSION;
19 @inc::Module::Package::ISA = __PACKAGE__;
20 }
21
22 sub import {
23 my $class = shift;
24 $INC{'inc/Module/Install.pm'} = __FILE__;
25 unshift @INC, 'inc' unless $INC[0] eq 'inc';
26 eval "use Module::Install 1.01 (); 1" or $class->error($@);
27
28 package main;
29 Module::Install->import();
30 eval {
31 module_package_internals_version_check($Module::Package::VERSION);
32 module_package_internals_init(@_);
33 };
34 if ($@) {
35 $Module::Package::ERROR = $@;
36 die $@;
37 }
38 }
39
40 # XXX Remove this when things are stable.
41 sub error {
42 my ($class, $error) = @_;
43 if (-e 'inc' and not -e 'inc/.author') {
44 require Data::Dumper;
45 $Data::Dumper::Sortkeys = 1;
46 my $dump1 = Data::Dumper::Dumper(\%INC);
47 my $dump2 = Data::Dumper::Dumper(\@INC);
48 die <<"...";
49 This should not have happened. Hopefully this dump will explain the problem:
50
51 inc::Module::Package: $inc::Module::Package::VERSION
52 Module::Package: $Module::Package::VERSION
53 inc::Module::Install: $inc::Module::Install::VERSION
54 Module::Install: $Module::Install::VERSION
55
56 Error: $error
57
58 %INC:
59 $dump1
60 \@INC:
61 $dump2
62 ...
63 }
64 else {
65 die $error;
66 }
67 }
68
69 1;
70
0 #line 1
1 # Scalar::Util::PP.pm
2 #
3 # Copyright (c) 1997-2009 Graham Barr <gbarr@pobox.com>. All rights reserved.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the same terms as Perl itself.
6 #
7 # This module is normally only loaded if the XS module is not available
8
9 package Scalar::Util::PP;
10
11 use strict;
12 use warnings;
13 use vars qw(@ISA @EXPORT $VERSION $recurse);
14 require Exporter;
15 use B qw(svref_2object);
16
17 @ISA = qw(Exporter);
18 @EXPORT = qw(blessed reftype tainted readonly refaddr looks_like_number);
19 $VERSION = "1.23";
20 $VERSION = eval $VERSION;
21
22 sub blessed ($) {
23 return undef unless length(ref($_[0]));
24 my $b = svref_2object($_[0]);
25 return undef unless $b->isa('B::PVMG');
26 my $s = $b->SvSTASH;
27 return $s->isa('B::HV') ? $s->NAME : undef;
28 }
29
30 sub refaddr($) {
31 return undef unless length(ref($_[0]));
32
33 my $addr;
34 if(defined(my $pkg = blessed($_[0]))) {
35 $addr .= bless $_[0], 'Scalar::Util::Fake';
36 bless $_[0], $pkg;
37 }
38 else {
39 $addr .= $_[0]
40 }
41
42 $addr =~ /0x(\w+)/;
43 local $^W;
44 no warnings 'portable';
45 hex($1);
46 }
47
48 {
49 my %tmap = qw(
50 B::NULL SCALAR
51
52 B::HV HASH
53 B::AV ARRAY
54 B::CV CODE
55 B::IO IO
56 B::GV GLOB
57 B::REGEXP REGEXP
58 );
59
60 sub reftype ($) {
61 my $r = shift;
62
63 return undef unless length(ref($r));
64
65 my $t = ref(svref_2object($r));
66
67 return
68 exists $tmap{$t} ? $tmap{$t}
69 : length(ref($$r)) ? 'REF'
70 : 'SCALAR';
71 }
72 }
73
74 sub tainted {
75 local($@, $SIG{__DIE__}, $SIG{__WARN__});
76 local $^W = 0;
77 no warnings;
78 eval { kill 0 * $_[0] };
79 $@ =~ /^Insecure/;
80 }
81
82 sub readonly {
83 return 0 if tied($_[0]) || (ref(\($_[0])) ne "SCALAR");
84
85 local($@, $SIG{__DIE__}, $SIG{__WARN__});
86 my $tmp = $_[0];
87
88 !eval { $_[0] = $tmp; 1 };
89 }
90
91 sub looks_like_number {
92 local $_ = shift;
93
94 # checks from perlfaq4
95 return 0 if !defined($_);
96 if (ref($_)) {
97 require overload;
98 return overload::Overloaded($_) ? defined(0 + $_) : 0;
99 }
100 return 1 if (/^[+-]?[0-9]+$/); # is a +/- integer
101 return 1 if (/^([+-]?)(?=[0-9]|\.[0-9])[0-9]*(\.[0-9]*)?([Ee]([+-]?[0-9]+))?$/); # a C float
102 return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i) or ($] >= 5.006001 and /^Inf$/i);
103
104 0;
105 }
106
107
108 1;
0 #line 1
1 # Scalar::Util.pm
2 #
3 # Copyright (c) 1997-2007 Graham Barr <gbarr@pobox.com>. All rights reserved.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the same terms as Perl itself.
6
7 package Scalar::Util;
8
9 use strict;
10 use vars qw(@ISA @EXPORT_OK $VERSION @EXPORT_FAIL);
11 require Exporter;
12 require List::Util; # List::Util loads the XS
13
14 @ISA = qw(Exporter);
15 @EXPORT_OK = qw(blessed dualvar reftype weaken isweak tainted readonly openhandle refaddr isvstring looks_like_number set_prototype);
16 $VERSION = "1.23";
17 $VERSION = eval $VERSION;
18
19 unless (defined &dualvar) {
20 # Load Pure Perl version if XS not loaded
21 require Scalar::Util::PP;
22 Scalar::Util::PP->import;
23 push @EXPORT_FAIL, qw(weaken isweak dualvar isvstring set_prototype);
24 }
25
26 sub export_fail {
27 if (grep { /dualvar/ } @EXPORT_FAIL) { # no XS loaded
28 my $pat = join("|", @EXPORT_FAIL);
29 if (my ($err) = grep { /^($pat)$/ } @_ ) {
30 require Carp;
31 Carp::croak("$err is only available with the XS version of Scalar::Util");
32 }
33 }
34
35 if (grep { /^(weaken|isweak)$/ } @_ ) {
36 require Carp;
37 Carp::croak("Weak references are not implemented in the version of perl");
38 }
39
40 if (grep { /^(isvstring)$/ } @_ ) {
41 require Carp;
42 Carp::croak("Vstrings are not implemented in the version of perl");
43 }
44
45 @_;
46 }
47
48 sub openhandle ($) {
49 my $fh = shift;
50 my $rt = reftype($fh) || '';
51
52 return defined(fileno($fh)) ? $fh : undef
53 if $rt eq 'IO';
54
55 if (reftype(\$fh) eq 'GLOB') { # handle openhandle(*DATA)
56 $fh = \(my $tmp=$fh);
57 }
58 elsif ($rt ne 'GLOB') {
59 return undef;
60 }
61
62 (tied(*$fh) or defined(fileno($fh)))
63 ? $fh : undef;
64 }
65
66 1;
67
68 __END__
69
70 #line 283
0 #line 1
1 package YAML::Tiny;
2
3 use strict;
4 use Carp 'croak';
5
6 # UTF Support?
7 sub HAVE_UTF8 () { $] >= 5.007003 }
8 BEGIN {
9 if ( HAVE_UTF8 ) {
10 # The string eval helps hide this from Test::MinimumVersion
11 eval "require utf8;";
12 die "Failed to load UTF-8 support" if $@;
13 }
14
15 # Class structure
16 require 5.004;
17 require Exporter;
18 $YAML::Tiny::VERSION = '1.41';
19 @YAML::Tiny::ISA = qw{ Exporter };
20 @YAML::Tiny::EXPORT = qw{ Load Dump };
21 @YAML::Tiny::EXPORT_OK = qw{ LoadFile DumpFile freeze thaw };
22
23 # Error storage
24 $YAML::Tiny::errstr = '';
25 }
26
27 # The character class of all characters we need to escape
28 # NOTE: Inlined, since it's only used once
29 # my $RE_ESCAPE = '[\\x00-\\x08\\x0b-\\x0d\\x0e-\\x1f\"\n]';
30
31 # Printed form of the unprintable characters in the lowest range
32 # of ASCII characters, listed by ASCII ordinal position.
33 my @UNPRINTABLE = qw(
34 z x01 x02 x03 x04 x05 x06 a
35 x08 t n v f r x0e x0f
36 x10 x11 x12 x13 x14 x15 x16 x17
37 x18 x19 x1a e x1c x1d x1e x1f
38 );
39
40 # Printable characters for escapes
41 my %UNESCAPES = (
42 z => "\x00", a => "\x07", t => "\x09",
43 n => "\x0a", v => "\x0b", f => "\x0c",
44 r => "\x0d", e => "\x1b", '\\' => '\\',
45 );
46
47 # Special magic boolean words
48 my %QUOTE = map { $_ => 1 } qw{
49 null Null NULL
50 y Y yes Yes YES n N no No NO
51 true True TRUE false False FALSE
52 on On ON off Off OFF
53 };
54
55
56
57
58
59 #####################################################################
60 # Implementation
61
62 # Create an empty YAML::Tiny object
63 sub new {
64 my $class = shift;
65 bless [ @_ ], $class;
66 }
67
68 # Create an object from a file
69 sub read {
70 my $class = ref $_[0] ? ref shift : shift;
71
72 # Check the file
73 my $file = shift or return $class->_error( 'You did not specify a file name' );
74 return $class->_error( "File '$file' does not exist" ) unless -e $file;
75 return $class->_error( "'$file' is a directory, not a file" ) unless -f _;
76 return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _;
77
78 # Slurp in the file
79 local $/ = undef;
80 local *CFG;
81 unless ( open(CFG, $file) ) {
82 return $class->_error("Failed to open file '$file': $!");
83 }
84 my $contents = <CFG>;
85 unless ( close(CFG) ) {
86 return $class->_error("Failed to close file '$file': $!");
87 }
88
89 $class->read_string( $contents );
90 }
91
92 # Create an object from a string
93 sub read_string {
94 my $class = ref $_[0] ? ref shift : shift;
95 my $self = bless [], $class;
96 my $string = $_[0];
97 unless ( defined $string ) {
98 return $self->_error("Did not provide a string to load");
99 }
100
101 # Byte order marks
102 # NOTE: Keeping this here to educate maintainers
103 # my %BOM = (
104 # "\357\273\277" => 'UTF-8',
105 # "\376\377" => 'UTF-16BE',
106 # "\377\376" => 'UTF-16LE',
107 # "\377\376\0\0" => 'UTF-32LE'
108 # "\0\0\376\377" => 'UTF-32BE',
109 # );
110 if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) {
111 return $self->_error("Stream has a non UTF-8 BOM");
112 } else {
113 # Strip UTF-8 bom if found, we'll just ignore it
114 $string =~ s/^\357\273\277//;
115 }
116
117 # Try to decode as utf8
118 utf8::decode($string) if HAVE_UTF8;
119
120 # Check for some special cases
121 return $self unless length $string;
122 unless ( $string =~ /[\012\015]+\z/ ) {
123 return $self->_error("Stream does not end with newline character");
124 }
125
126 # Split the file into lines
127 my @lines = grep { ! /^\s*(?:\#.*)?\z/ }
128 split /(?:\015{1,2}\012|\015|\012)/, $string;
129
130 # Strip the initial YAML header
131 @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines;
132
133 # A nibbling parser
134 while ( @lines ) {
135 # Do we have a document header?
136 if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) {
137 # Handle scalar documents
138 shift @lines;
139 if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) {
140 push @$self, $self->_read_scalar( "$1", [ undef ], \@lines );
141 next;
142 }
143 }
144
145 if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) {
146 # A naked document
147 push @$self, undef;
148 while ( @lines and $lines[0] !~ /^---/ ) {
149 shift @lines;
150 }
151
152 } elsif ( $lines[0] =~ /^\s*\-/ ) {
153 # An array at the root
154 my $document = [ ];
155 push @$self, $document;
156 $self->_read_array( $document, [ 0 ], \@lines );
157
158 } elsif ( $lines[0] =~ /^(\s*)\S/ ) {
159 # A hash at the root
160 my $document = { };
161 push @$self, $document;
162 $self->_read_hash( $document, [ length($1) ], \@lines );
163
164 } else {
165 croak("YAML::Tiny failed to classify the line '$lines[0]'");
166 }
167 }
168
169 $self;
170 }
171
172 # Deparse a scalar string to the actual scalar
173 sub _read_scalar {
174 my ($self, $string, $indent, $lines) = @_;
175
176 # Trim trailing whitespace
177 $string =~ s/\s*\z//;
178
179 # Explitic null/undef
180 return undef if $string eq '~';
181
182 # Single quote
183 if ( $string =~ /^\'(.*?)\'\z/ ) {
184 return '' unless defined $1;
185 $string = $1;
186 $string =~ s/\'\'/\'/g;
187 return $string;
188 }
189
190 # Double quote.
191 # The commented out form is simpler, but overloaded the Perl regex
192 # engine due to recursion and backtracking problems on strings
193 # larger than 32,000ish characters. Keep it for reference purposes.
194 # if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) {
195 if ( $string =~ /^\"([^\\"]*(?:\\.[^\\"]*)*)\"\z/ ) {
196 # Reusing the variable is a little ugly,
197 # but avoids a new variable and a string copy.
198 $string = $1;
199 $string =~ s/\\"/"/g;
200 $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex;
201 return $string;
202 }
203
204 # Special cases
205 if ( $string =~ /^[\'\"!&]/ ) {
206 croak("YAML::Tiny does not support a feature in line '$lines->[0]'");
207 }
208 return {} if $string eq '{}';
209 return [] if $string eq '[]';
210
211 # Regular unquoted string
212 return $string unless $string =~ /^[>|]/;
213
214 # Error
215 croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines;
216
217 # Check the indent depth
218 $lines->[0] =~ /^(\s*)/;
219 $indent->[-1] = length("$1");
220 if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) {
221 croak("YAML::Tiny found bad indenting in line '$lines->[0]'");
222 }
223
224 # Pull the lines
225 my @multiline = ();
226 while ( @$lines ) {
227 $lines->[0] =~ /^(\s*)/;
228 last unless length($1) >= $indent->[-1];
229 push @multiline, substr(shift(@$lines), length($1));
230 }
231
232 my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n";
233 my $t = (substr($string, 1, 1) eq '-') ? '' : "\n";
234 return join( $j, @multiline ) . $t;
235 }
236
237 # Parse an array
238 sub _read_array {
239 my ($self, $array, $indent, $lines) = @_;
240
241 while ( @$lines ) {
242 # Check for a new document
243 if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
244 while ( @$lines and $lines->[0] !~ /^---/ ) {
245 shift @$lines;
246 }
247 return 1;
248 }
249
250 # Check the indent level
251 $lines->[0] =~ /^(\s*)/;
252 if ( length($1) < $indent->[-1] ) {
253 return 1;
254 } elsif ( length($1) > $indent->[-1] ) {
255 croak("YAML::Tiny found bad indenting in line '$lines->[0]'");
256 }
257
258 if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) {
259 # Inline nested hash
260 my $indent2 = length("$1");
261 $lines->[0] =~ s/-/ /;
262 push @$array, { };
263 $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines );
264
265 } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) {
266 # Array entry with a value
267 shift @$lines;
268 push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines );
269
270 } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) {
271 shift @$lines;
272 unless ( @$lines ) {
273 push @$array, undef;
274 return 1;
275 }
276 if ( $lines->[0] =~ /^(\s*)\-/ ) {
277 my $indent2 = length("$1");
278 if ( $indent->[-1] == $indent2 ) {
279 # Null array entry
280 push @$array, undef;
281 } else {
282 # Naked indenter
283 push @$array, [ ];
284 $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines );
285 }
286
287 } elsif ( $lines->[0] =~ /^(\s*)\S/ ) {
288 push @$array, { };
289 $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines );
290
291 } else {
292 croak("YAML::Tiny failed to classify line '$lines->[0]'");
293 }
294
295 } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) {
296 # This is probably a structure like the following...
297 # ---
298 # foo:
299 # - list
300 # bar: value
301 #
302 # ... so lets return and let the hash parser handle it
303 return 1;
304
305 } else {
306 croak("YAML::Tiny failed to classify line '$lines->[0]'");
307 }
308 }
309
310 return 1;
311 }
312
313 # Parse an array
314 sub _read_hash {
315 my ($self, $hash, $indent, $lines) = @_;
316
317 while ( @$lines ) {
318 # Check for a new document
319 if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
320 while ( @$lines and $lines->[0] !~ /^---/ ) {
321 shift @$lines;
322 }
323 return 1;
324 }
325
326 # Check the indent level
327 $lines->[0] =~ /^(\s*)/;
328 if ( length($1) < $indent->[-1] ) {
329 return 1;
330 } elsif ( length($1) > $indent->[-1] ) {
331 croak("YAML::Tiny found bad indenting in line '$lines->[0]'");
332 }
333
334 # Get the key
335 unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) {
336 if ( $lines->[0] =~ /^\s*[?\'\"]/ ) {
337 croak("YAML::Tiny does not support a feature in line '$lines->[0]'");
338 }
339 croak("YAML::Tiny failed to classify line '$lines->[0]'");
340 }
341 my $key = $1;
342
343 # Do we have a value?
344 if ( length $lines->[0] ) {
345 # Yes
346 $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines );
347 } else {
348 # An indent
349 shift @$lines;
350 unless ( @$lines ) {
351 $hash->{$key} = undef;
352 return 1;
353 }
354 if ( $lines->[0] =~ /^(\s*)-/ ) {
355 $hash->{$key} = [];
356 $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines );
357 } elsif ( $lines->[0] =~ /^(\s*)./ ) {
358 my $indent2 = length("$1");
359 if ( $indent->[-1] >= $indent2 ) {
360 # Null hash entry
361 $hash->{$key} = undef;
362 } else {
363 $hash->{$key} = {};
364 $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines );
365 }
366 }
367 }
368 }
369
370 return 1;
371 }
372
373 # Save an object to a file
374 sub write {
375 my $self = shift;
376 my $file = shift or return $self->_error('No file name provided');
377
378 # Write it to the file
379 open( CFG, '>' . $file ) or return $self->_error(
380 "Failed to open file '$file' for writing: $!"
381 );
382 print CFG $self->write_string;
383 close CFG;
384
385 return 1;
386 }
387
388 # Save an object to a string
389 sub write_string {
390 my $self = shift;
391 return '' unless @$self;
392
393 # Iterate over the documents
394 my $indent = 0;
395 my @lines = ();
396 foreach my $cursor ( @$self ) {
397 push @lines, '---';
398
399 # An empty document
400 if ( ! defined $cursor ) {
401 # Do nothing
402
403 # A scalar document
404 } elsif ( ! ref $cursor ) {
405 $lines[-1] .= ' ' . $self->_write_scalar( $cursor, $indent );
406
407 # A list at the root
408 } elsif ( ref $cursor eq 'ARRAY' ) {
409 unless ( @$cursor ) {
410 $lines[-1] .= ' []';
411 next;
412 }
413 push @lines, $self->_write_array( $cursor, $indent, {} );
414
415 # A hash at the root
416 } elsif ( ref $cursor eq 'HASH' ) {
417 unless ( %$cursor ) {
418 $lines[-1] .= ' {}';
419 next;
420 }
421 push @lines, $self->_write_hash( $cursor, $indent, {} );
422
423 } else {
424 croak("Cannot serialize " . ref($cursor));
425 }
426 }
427
428 join '', map { "$_\n" } @lines;
429 }
430
431 sub _write_scalar {
432 my $string = $_[1];
433 return '~' unless defined $string;
434 return "''" unless length $string;
435 if ( $string =~ /[\x00-\x08\x0b-\x0d\x0e-\x1f\"\'\n]/ ) {
436 $string =~ s/\\/\\\\/g;
437 $string =~ s/"/\\"/g;
438 $string =~ s/\n/\\n/g;
439 $string =~ s/([\x00-\x1f])/\\$UNPRINTABLE[ord($1)]/g;
440 return qq|"$string"|;
441 }
442 if ( $string =~ /(?:^\W|\s)/ or $QUOTE{$string} ) {
443 return "'$string'";
444 }
445 return $string;
446 }
447
448 sub _write_array {
449 my ($self, $array, $indent, $seen) = @_;
450 if ( $seen->{refaddr($array)}++ ) {
451 die "YAML::Tiny does not support circular references";
452 }
453 my @lines = ();
454 foreach my $el ( @$array ) {
455 my $line = (' ' x $indent) . '-';
456 my $type = ref $el;
457 if ( ! $type ) {
458 $line .= ' ' . $self->_write_scalar( $el, $indent + 1 );
459 push @lines, $line;
460
461 } elsif ( $type eq 'ARRAY' ) {
462 if ( @$el ) {
463 push @lines, $line;
464 push @lines, $self->_write_array( $el, $indent + 1, $seen );
465 } else {
466 $line .= ' []';
467 push @lines, $line;
468 }
469
470 } elsif ( $type eq 'HASH' ) {
471 if ( keys %$el ) {
472 push @lines, $line;
473 push @lines, $self->_write_hash( $el, $indent + 1, $seen );
474 } else {
475 $line .= ' {}';
476 push @lines, $line;
477 }
478
479 } else {
480 die "YAML::Tiny does not support $type references";
481 }
482 }
483
484 @lines;
485 }
486
487 sub _write_hash {
488 my ($self, $hash, $indent, $seen) = @_;
489 if ( $seen->{refaddr($hash)}++ ) {
490 die "YAML::Tiny does not support circular references";
491 }
492 my @lines = ();
493 foreach my $name ( sort keys %$hash ) {
494 my $el = $hash->{$name};
495 my $line = (' ' x $indent) . "$name:";
496 my $type = ref $el;
497 if ( ! $type ) {
498 $line .= ' ' . $self->_write_scalar( $el, $indent + 1 );
499 push @lines, $line;
500
501 } elsif ( $type eq 'ARRAY' ) {
502 if ( @$el ) {
503 push @lines, $line;
504 push @lines, $self->_write_array( $el, $indent + 1, $seen );
505 } else {
506 $line .= ' []';
507 push @lines, $line;
508 }
509
510 } elsif ( $type eq 'HASH' ) {
511 if ( keys %$el ) {
512 push @lines, $line;
513 push @lines, $self->_write_hash( $el, $indent + 1, $seen );
514 } else {
515 $line .= ' {}';
516 push @lines, $line;
517 }
518
519 } else {
520 die "YAML::Tiny does not support $type references";
521 }
522 }
523
524 @lines;
525 }
526
527 # Set error
528 sub _error {
529 $YAML::Tiny::errstr = $_[1];
530 undef;
531 }
532
533 # Retrieve error
534 sub errstr {
535 $YAML::Tiny::errstr;
536 }
537
538
539
540
541
542 #####################################################################
543 # YAML Compatibility
544
545 sub Dump {
546 YAML::Tiny->new(@_)->write_string;
547 }
548
549 sub Load {
550 my $self = YAML::Tiny->read_string(@_);
551 unless ( $self ) {
552 croak("Failed to load YAML document from string");
553 }
554 if ( wantarray ) {
555 return @$self;
556 } else {
557 # To match YAML.pm, return the last document
558 return $self->[-1];
559 }
560 }
561
562 BEGIN {
563 *freeze = *Dump;
564 *thaw = *Load;
565 }
566
567 sub DumpFile {
568 my $file = shift;
569 YAML::Tiny->new(@_)->write($file);
570 }
571
572 sub LoadFile {
573 my $self = YAML::Tiny->read($_[0]);
574 unless ( $self ) {
575 croak("Failed to load YAML document from '" . ($_[0] || '') . "'");
576 }
577 if ( wantarray ) {
578 return @$self;
579 } else {
580 # Return only the last document to match YAML.pm,
581 return $self->[-1];
582 }
583 }
584
585
586
587
588
589 #####################################################################
590 # Use Scalar::Util if possible, otherwise emulate it
591
592 BEGIN {
593 eval {
594 require Scalar::Util;
595 };
596 if ( $@ ) {
597 # Failed to load Scalar::Util
598 eval <<'END_PERL';
599 sub refaddr {
600 my $pkg = ref($_[0]) or return undef;
601 if (!!UNIVERSAL::can($_[0], 'can')) {
602 bless $_[0], 'Scalar::Util::Fake';
603 } else {
604 $pkg = undef;
605 }
606 "$_[0]" =~ /0x(\w+)/;
607 my $i = do { local $^W; hex $1 };
608 bless $_[0], $pkg if defined $pkg;
609 $i;
610 }
611 END_PERL
612 } else {
613 Scalar::Util->import('refaddr');
614 }
615 }
616
617 1;
618
619 __END__
620
621 #line 1132
0 package PerlX::Maybe;
1
2 use 5.008;
3 use strict;
4
5 our (@EXPORT, @ISA);
6 BEGIN {
7 $PerlX::Maybe::AUTHORITY = 'cpan:TOBYINK';
8 $PerlX::Maybe::VERSION = '0.002';
9
10 require Exporter;
11 @ISA = qw/Exporter/;
12 @EXPORT = qw/maybe/;
13 }
14
15 sub maybe ($$@)
16 {
17 if (defined $_[0] and defined $_[1])
18 {
19 @_
20 }
21 else
22 {
23 (scalar @_ > 1) ? @_[2 .. $#_] : qw()
24 }
25 }
26
27 __FILE__
28 __END__
29
30 =head1 NAME
31
32 PerlX::Maybe - return a pair only if they are both defined
33
34 =head1 SYNOPSIS
35
36 You once wrote:
37
38 my $bob = Person->new(
39 defined $name ? (name => $name) : (),
40 defined $age ? (age => $age) : (),
41 );
42
43 Now you can write:
44
45 my $bob = Person->new(
46 maybe name => $name,
47 maybe age => $age,
48 );
49
50 =head1 DESCRIPTION
51
52 Moose classes (and some other classes) distinguish between an attribute
53 being unset and the attribute being set to undef. Supplying a constructor
54 arguments like this:
55
56 my $bob = Person->new(
57 name => $name,
58 age => $age,
59 );
60
61 Will result in the C<name> and C<age> attributes possibly being set to
62 undef (if the corresponding C<$name> and C<$age> variables are not defined),
63 which may violate the Person class' type constraints.
64
65 (Note: if you are the I<author> of the class in question, you can solve
66 this using L<MooseX::UndefTolerant>. However, some of us are stuck using
67 non-UndefTolerant classes written by third parties.)
68
69 To ensure that the Person constructor does not try to set a name or age
70 at all when they are undefined, ugly looking code like this is often used:
71
72 my $bob = Person->new(
73 defined $name ? (name => $name) : (),
74 defined $age ? (age => $age) : (),
75 );
76
77 or:
78
79 my $bob = Person->new(
80 (name => $name) x!!(defined $name),
81 (age => $age) x!!(defined $age),
82 );
83
84 A slightly more elegant solution is the C<maybe> function:
85
86 =head2 C<< maybe $x => $y, @rest >>
87
88 This function checks that C<< $x >> and C<< $y >> are both defined. If they
89 are, it returns them both as a list; otherwise it returns the empty list.
90
91 If C<< @rest >> is provided, it is unconditionally appended to the end of
92 whatever list is returned.
93
94 The combination of these behaviours allows the following very sugary syntax
95 to "just work".
96
97 my $bob = Person->new(
98 name => $name,
99 address => $addr,
100 maybe phone => $tel,
101 maybe email => $email,
102 unique_id => $id,
103 );
104
105 This function is exported by default.
106
107 =head1 BUGS
108
109 Please report any bugs to
110 L<http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe>.
111
112 =head1 SEE ALSO
113
114 L<Syntax::Feature::Maybe>.
115
116 L<MooseX::UndefTolerant>, L<PerlX::Perform>, L<Exporter>.
117
118 =head1 AUTHOR
119
120 Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
121
122 =head1 COPYRIGHT AND LICENCE
123
124 This software is copyright (c) 2012 by Toby Inkster.
125
126 This is free software; you can redistribute it and/or modify it under
127 the same terms as the Perl 5 programming language system itself.
128
129 =head1 DISCLAIMER OF WARRANTIES
130
131 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
132 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
133 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
134
0 package Syntax::Feature::Maybe;
1
2 use 5.008;
3 use strict;
4 use PerlX::Maybe qw//;
5
6 BEGIN {
7 $Syntax::Feature::Maybe::AUTHORITY = 'cpan:TOBYINK';
8 $Syntax::Feature::Maybe::VERSION = '0.002';
9 }
10
11 sub install
12 {
13 my ($class, %args) = @_;
14 my $into = delete $args{into};
15
16 foreach my $f (qw/maybe/)
17 {
18 no strict 'refs';
19 *{"$into\::$f"} = \&{"PerlX::Maybe::$f"};
20 }
21 }
22
23 __FILE__
24 __END__
25
26 =head1 NAME
27
28 Syntax::Feature::Maybe - use syntax qw/maybe/
29
30 =head1 DESCRIPTION
31
32 Tiny shim between L<PerlX::Maybe> and L<syntax>.
33
34 =head1 BUGS
35
36 Please report any bugs to
37 L<http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe>.
38
39 =head1 SEE ALSO
40
41 L<PerlX::Maybe>, L<syntax>.
42
43 =head1 AUTHOR
44
45 Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
46
47 =head1 COPYRIGHT AND LICENCE
48
49 This software is copyright (c) 2012 by Toby Inkster.
50
51 This is free software; you can redistribute it and/or modify it under
52 the same terms as the Perl 5 programming language system itself.
53
54 =head1 DISCLAIMER OF WARRANTIES
55
56 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
57 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
58 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
59
0 # This file acts as the project's changelog.
1
2 @prefix : <http://usefulinc.com/ns/doap#> .
3 @prefix dcs: <http://ontologi.es/doap-changeset#> .
4 @prefix dc: <http://purl.org/dc/terms/> .
5 @prefix dist: <http://purl.org/NET/cpan-uri/dist/PerlX-Maybe/> .
6 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
7 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
8
9 dist:project :release dist:v_0-001 .
10 dist:v_0-001
11 a :Version ;
12 dc:issued "2012-02-15"^^xsd:date ;
13 :revision "0.001"^^xsd:string ;
14 :file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/PerlX-Maybe-0.001.tar.gz> ;
15 rdfs:label "Initial release" .
16
17 dist:project :release dist:v_0-002 .
18 dist:v_0-002
19 a :Version ;
20 dc:issued "2012-05-03"^^xsd:date ;
21 :revision "0.002"^^xsd:string ;
22 :file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/PerlX-Maybe-0.002.tar.gz> ;
23 dcs:changeset [
24 dcs:versus dist:v_0-001 ;
25 dcs:item [ rdfs:label "Faster implementation. Tested on Perl 5.10.1 on Linux, the new version is 60% faster. (Not that it was slow to begin with - 'maybe' is a pretty simple function.)"@en ] ;
26 ] .
27
0 # This file contains general metadata about the project.
1
2 @prefix : <http://usefulinc.com/ns/doap#> .
3 @prefix dc: <http://purl.org/dc/terms/> .
4 @prefix foaf: <http://xmlns.com/foaf/0.1/> .
5 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
6 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
7
8 <http://purl.org/NET/cpan-uri/dist/PerlX-Maybe/project>
9 a :Project ;
10 :programming-language "Perl" ;
11 :name "PerlX-Maybe" ;
12 :shortdesc "return a given list only if they are all defined" ;
13 :homepage <https://metacpan.org/release/PerlX-Maybe> ;
14 :download-page <https://metacpan.org/release/PerlX-Maybe> ;
15 :repository [ a :HgRepository ; :browse <https://bitbucket.org/tobyink/p5-perlx-maybe> ] ;
16 :bug-database <http://rt.cpan.org/Dist/Display.html?Queue=PerlX-Maybe> ;
17 :created "2012-02-15"^^xsd:date ;
18 :license <http://dev.perl.org/licenses/> ;
19 :developer [ a foaf:Person ; foaf:name "Toby Inkster" ; foaf:mbox <mailto:tobyink@cpan.org> ] .
20
21 <http://dev.perl.org/licenses/>
22 dc:title "the same terms as the perl 5 programming language system itself" .
0 # This file provides instructions for packaging.
1
2 @prefix : <http://purl.org/NET/cpan-uri/terms#> .
3
4 <http://purl.org/NET/cpan-uri/dist/PerlX-Maybe/project>
5 :perl_version_from _:main ;
6 :version_from _:main ;
7 :readme_from _:main ;
8 :test_requires "Test::More 0.61" ;
9 :requires "strict","Exporter".
10
11 _:main <http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName> "lib/PerlX/Maybe.pm" .
12
0 use Test::More tests => 1;
1 BEGIN { use_ok('PerlX::Maybe') };
2
0 use Test::More tests => 3;
1 use PerlX::Maybe;
2
3 is_deeply(
4 [ maybe foo => undef, maybe bar => 0, maybe baz => 1, undef ],
5 [ bar => 0, baz => 1, undef ],
6 );
7
8 is_deeply(
9 [ 3, maybe foo => undef, 4, maybe bar => 0, 5, maybe baz => 1 ],
10 [ 3, 4, bar => 0, 5, baz => 1 ],
11 );
12
13 is_deeply(
14 [ 3, maybe foo => {quux=>1}, undef, 4, maybe bar => 0, 5, maybe baz => 1 ],
15 [ 3, foo => {quux=>1}, undef, 4, bar => 0, 5, baz => 1 ],
16 );
17