File Coverage

blib/lib/Dist/Zilla/Plugin/ModuleBuild/Custom.pm
Criterion Covered Total %
statement 40 45 88.8
branch 5 8 62.5
condition 1 3 33.3
subroutine 11 13 84.6
pod 3 7 42.8
total 60 76 78.9


line stmt bran cond sub pod time code
1             #---------------------------------------------------------------------
2             package Dist::Zilla::Plugin::ModuleBuild::Custom;
3             #
4             # Copyright 2010 Christopher J. Madsen
5             #
6             # Author: Christopher J. Madsen <perl@cjmweb.net>
7             # Created: 11 Mar 2010
8             #
9             # This program is free software; you can redistribute it and/or modify
10             # it under the same terms as Perl itself.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
15             # GNU General Public License or the Artistic License for more details.
16             #
17             # ABSTRACT: Allow a dist to have a custom Build.PL
18             #---------------------------------------------------------------------
19              
20             our $VERSION = '4.26';
21             # This file is part of Dist-Zilla-Plugins-CJM 4.27 (August 29, 2015)
22              
23              
24 2     2   841459 use Moose;
  2         3  
  2         14  
25             extends 'Dist::Zilla::Plugin::ModuleBuild';
26             with qw(Dist::Zilla::Role::FilePruner
27             Dist::Zilla::Role::HashDumper);
28              
29 2     2   11132 use List::Util ();
  2         4  
  2         1324  
30              
31             # We're trying to make the template executable before it's filled in,
32             # so we want delimiters that look like comments:
33             has '+delim' => (
34             default => sub { [ '##{', '##}' ] },
35             );
36              
37             has distmeta1 => (
38             is => 'ro',
39             isa => 'HashRef',
40             init_arg => undef,
41             lazy => 1,
42             builder => '_build_distmeta1',
43             );
44              
45             sub _build_distmeta1
46             {
47 3     3   9 my $self = shift;
48              
49 3         31 require CPAN::Meta::Converter;
50 3         92 CPAN::Meta::Converter->VERSION(2.101550); # improved downconversion
51              
52 3         144 my $converter = CPAN::Meta::Converter->new($self->zilla->distmeta);
53 3         316 return $converter->convert(version => '1.4');
54             } # end _build_distmeta1
55              
56             # Get rid of any META.yml we may have picked up from Module::Build:
57             sub prune_files {
58 3     3 0 2815 my ($self) = @_;
59              
60 3         108 my $files = $self->zilla->files;
61 3   33     82 @$files = grep { not($_->name =~ /^META\.(?:yml|json)$/ and
  18         531  
62             $_->isa('Dist::Zilla::File::OnDisk')) } @$files;
63              
64 3         138 return;
65             } # end prune_files
66              
67              
68             sub get_meta
69             {
70 2     2 1 4 my $self = shift;
71              
72             # Extract the wanted keys from distmeta:
73 2         81 return $self->extract_keys(distmeta1 => $self->distmeta1, @_);
74             } # end get_meta
75             #---------------------------------------------------------------------
76              
77              
78             sub get_prereqs
79             {
80 3     3 1 2431 my ($self, $api_version) = @_;
81              
82 3 100       14 if ($api_version) {
83 1 50       7 $self->log_fatal("api_version $api_version is not supported")
84             unless $api_version == 1;
85 1         4 local $@;
86             $self->log(["WARNING: Dist::Zilla %s does not support api_version %d",
87             Dist::Zilla->VERSION, $api_version ])
88 1 50       4 unless eval { Dist::Zilla::Plugin::ModuleBuild->VERSION( 4.300032 ) };
  1         36  
89              
90 1         9 return $self->get_default(qw(build_requires configure_requires requires
91             test_requires recommends conflicts));
92             }
93              
94 2         10 $self->get_meta(qw(build_requires configure_requires requires recommends
95             conflicts));
96             } # end get_prereqs
97              
98             #---------------------------------------------------------------------
99              
100              
101             has _default_mb_args => (
102             is => 'ro',
103             isa => 'HashRef',
104             init_arg => undef,
105             lazy => 1,
106             builder => 'module_build_args',
107             );
108              
109             sub get_default
110             {
111 1     1 1 3 my $self = shift;
112              
113 1         62 return $self->extract_keys(module_build => $self->_default_mb_args, @_);
114             } # end get_default
115              
116       3 0   sub add_file {} # Don't let parent class add any files
117              
118             #---------------------------------------------------------------------
119             sub setup_installer
120             {
121 3     3 0 63547 my $self = shift;
122              
123 6     6   403 my $file = List::Util::first { $_->name eq 'Build.PL' }
124 3 50       20 @{ $self->zilla->files }
  3         132  
125             or $self->log_fatal("No Build.PL found in dist");
126              
127             # Process Build.PL through Text::Template:
128 3         320 my %data = (
129             dist => $self->zilla->name,
130             meta => $self->distmeta1,
131             meta2 => $self->zilla->distmeta,
132             plugin => \$self,
133             version => $self->zilla->version,
134             zilla => \$self->zilla,
135             );
136              
137             # The STRICT option hasn't been implemented in a released version of
138             # Text::Template, but you can apply Template_strict.patch. Since
139             # Text::Template ignores unknown options, this code will still work
140             # even if you don't apply the patch; you just won't get strict checking.
141             my %parms = (
142             STRICT => 1,
143 0     0   0 BROKEN => sub { $self->template_error(@_) },
144 3         586 );
145              
146 3         27 $self->log_debug("Processing Build.PL as template");
147 3         741 $file->content($self->fill_in_string($file->content, \%data, \%parms));
148              
149 3         1303 return;
150             } # end setup_installer
151              
152             sub template_error
153             {
154 0     0 0   my ($self, %e) = @_;
155              
156             # Put the filename into the error message:
157 0           my $err = $e{error};
158 0           $err =~ s/ at template line (?=\d)/ at Build.PL line /g;
159              
160 0           $self->log_fatal($err);
161             } # end template_error
162              
163             #---------------------------------------------------------------------
164 2     2   12 no Moose;
  2         6  
  2         12  
165             __PACKAGE__->meta->make_immutable;
166             1;
167              
168             __END__
169              
170             =head1 NAME
171              
172             Dist::Zilla::Plugin::ModuleBuild::Custom - Allow a dist to have a custom Build.PL
173              
174             =head1 VERSION
175              
176             This document describes version 4.26 of
177             Dist::Zilla::Plugin::ModuleBuild::Custom, released August 29, 2015
178             as part of Dist-Zilla-Plugins-CJM version 4.27.
179              
180             =head1 SYNOPSIS
181              
182             In F<dist.ini>:
183              
184             [ModuleBuild::Custom]
185             mb_version = 0.34 ; the default comes from the ModuleBuild plugin
186              
187             In your F<Build.PL>:
188              
189             use Module::Build;
190              
191             my %module_build_args = (
192             module_name => 'Foo::Bar',
193             ##{ $plugin->get_prereqs(1) ##}
194             ##{ $plugin->get_default('share_dir') ##}
195             );
196              
197             unless ( eval { Module::Build->VERSION(0.4004) } ) {
198             my $tr = delete $module_build_args{test_requires};
199             my $br = $module_build_args{build_requires};
200             for my $mod ( keys %$tr ) {
201             if ( exists $br->{$mod} ) {
202             $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
203             }
204             else {
205             $br->{$mod} = $tr->{$mod};
206             }
207             }
208             } # end unless Module::Build is 0.4004 or newer
209              
210             my $builder = Module::Build->new(%module_build_args);
211             $builder->create_build_script;
212              
213             Of course, your F<Build.PL> doesn't need to look exactly like this.
214             If you can require Module::Build 0.4004, then you can remove the
215             C<unless eval> section. If you're not using C<share_dir>,
216             you can remove that line.
217              
218             And if you're not adding your own code to F<Build.PL>,
219             you don't need this plugin.
220              
221             =head1 DESCRIPTION
222              
223             This plugin is for people who need something more complex than the
224             auto-generated F<Makefile.PL> or F<Build.PL> generated by the
225             L<MakeMaker|Dist::Zilla::Plugin::MakeMaker> or
226             L<ModuleBuild|Dist::Zilla::Plugin::ModuleBuild> plugins.
227              
228             It is a subclass of the L<ModuleBuild plugin|Dist::Zilla::Plugin::ModuleBuild>,
229             but it does not write a F<Build.PL> for you. Instead, you write your
230             own F<Build.PL>, which may do anything L<Module::Build> is capable of
231             (except generate a compatibility F<Makefile.PL>).
232              
233             This plugin will process F<Build.PL> as a template (using
234             L<Text::Template>), which allows you to add data from Dist::Zilla to
235             the version you distribute (if you want). The template delimiters are
236             C<##{> and C<##}>, because that makes them look like comments.
237             That makes it easier to have a F<Build.PL> that works both before and
238             after it is processed as a template.
239              
240             This is particularly useful for XS-based modules, because it can allow
241             you to build and test the module without the overhead of S<C<dzil build>>
242             after every small change.
243              
244             The template may use the following variables:
245              
246             =over
247              
248             =item C<$dist>
249              
250             The name of the distribution.
251              
252             =item C<$meta>
253              
254             The hash of metadata (in META 1.4 format) that will be stored in F<META.yml>.
255              
256             =item C<$meta2>
257              
258             The hash of metadata (in META 2 format) that will be stored in F<META.json>.
259              
260             =item C<$plugin>
261              
262             The ModuleBuild::Custom object that is processing the template.
263              
264             =item C<$version>
265              
266             The distribution's version number.
267              
268             =item C<$zilla>
269              
270             The Dist::Zilla object that is creating the distribution.
271              
272             =back
273              
274             =head2 Using ModuleBuild::Custom with AutoPrereqs
275              
276             If you are using the L<AutoPrereqs|Dist::Zilla::Plugin::AutoPrereqs>
277             plugin, then you will probably want to set its C<configure_finder> to
278             a FileFinder that includes F<Build.PL>. You may also want to set
279             this plugin's C<mb_version> parameter to 0 and allow AutoPrereqs to
280             get the version from your S<C<use Module::Build>> line.
281              
282             Example F<dist.ini> configuration:
283              
284             [ModuleBuild::Custom]
285             mb_version = 0 ; AutoPrereqs gets actual version from Build.PL
286              
287             [FileFinder::ByName / :BuildPL]
288             file = Build.PL
289              
290             [AutoPrereqs]
291             :version = 4.300005 ; need configure_finder
292             configure_finder = :BuildPL
293             ; Add next line if your Build.PL uses modules you ship in inc/
294             configure_finder = :IncModules
295              
296             Then in your F<Build.PL> you'd say:
297              
298             use Module::Build 0.28; # or whatever version you need
299              
300             =head1 METHODS
301              
302             =head2 get_default
303              
304             $plugin->get_default(qw(key1 key2 ...))
305              
306             A template can call this method to extract the specified key(s) from
307             the default Module::Build arguments created by the normal ModuleBuild
308             plugin and have them formatted into a comma-separated list suitable
309             for a hash constructor or a method's parameter list.
310              
311             If any key has no value (or its value is an empty hash or array ref)
312             it will be omitted from the list. If all keys are omitted, the empty
313             string is returned. Otherwise, the result always ends with a comma.
314              
315             The most common usage would be
316              
317             ##{ $plugin->get_default('share_dir') ##}
318              
319              
320             =head2 get_meta
321              
322             $plugin->get_meta(qw(key1 key2 ...))
323              
324             A template can call this method to extract the specified key(s) from
325             C<distmeta> and have them formatted into a comma-separated list
326             suitable for a hash constructor or a method's parameter list. The
327             keys (and the returned values) are from the META 1.4 spec, because
328             that's what Module::Build uses in its API.
329              
330             If any key has no value (or its value is an empty hash or array ref)
331             it will be omitted from the list. If all keys are omitted, the empty
332             string is returned. Otherwise, the result always ends with a comma.
333              
334              
335             =head2 get_prereqs
336              
337             $plugin->get_prereqs($api_version)
338              
339             This returns all the keys that describe the distribution's
340             prerequisites. The C<$api_version> indicates what keys
341             the template can handle. The currently defined values are:
342              
343             =over 8
344              
345             =item C<0> (or undef)
346              
347             This is equivalent to
348              
349             $plugin->get_meta(qw(build_requires configure_requires requires
350             recommends conflicts))
351              
352             =item C<1>
353              
354             This adds C<test_requires> as a separate key (which requires
355             Dist::Zilla 4.300032 or later). It's equivalent to
356              
357             $plugin->get_default(qw(build_requires configure_requires requires
358             test_requires recommends conflicts))
359              
360             Your F<Build.PL> should either require Module::Build 0.4004, or
361             fold test_requires into build_requires if an older version is used (as
362             shown in the SYNOPSIS).
363              
364             =back
365              
366             =head1 SEE ALSO
367              
368             The L<MakeMaker::Custom|Dist::Zilla::Plugin::MakeMaker::Custom>
369             plugin does basically the same thing as this plugin, but for
370             F<Makefile.PL> (if you prefer L<ExtUtils::MakeMaker>).
371              
372              
373             =for Pod::Coverage
374             add_file
375             prune_files
376             setup_installer
377             template_error
378              
379             =head1 DEPENDENCIES
380              
381             ModuleBuild::Custom requires L<Dist::Zilla> (4.300009 or later) and
382             L<Text::Template>. I also recommend applying F<Template_strict.patch>
383             to Text::Template. This will add support for the STRICT option, which
384             will help catch errors in your templates.
385              
386             =head1 INCOMPATIBILITIES
387              
388             You must not use this in conjunction with the
389             L<ModuleBuild|Dist::Zilla::Plugin::ModuleBuild> plugin.
390              
391             =head1 BUGS AND LIMITATIONS
392              
393             No bugs have been reported.
394              
395             =head1 AUTHOR
396              
397             Christopher J. Madsen S<C<< <perl AT cjmweb.net> >>>
398              
399             Please report any bugs or feature requests
400             to S<C<< <bug-Dist-Zilla-Plugins-CJM AT rt.cpan.org> >>>
401             or through the web interface at
402             L<< http://rt.cpan.org/Public/Bug/Report.html?Queue=Dist-Zilla-Plugins-CJM >>.
403              
404             You can follow or contribute to Dist-Zilla-Plugins-CJM's development at
405             L<< https://github.com/madsen/dist-zilla-plugins-cjm >>.
406              
407             =head1 COPYRIGHT AND LICENSE
408              
409             This software is copyright (c) 2015 by Christopher J. Madsen.
410              
411             This is free software; you can redistribute it and/or modify it under
412             the same terms as the Perl 5 programming language system itself.
413              
414             =head1 DISCLAIMER OF WARRANTY
415              
416             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
417             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
418             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
419             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
420             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
421             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
422             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
423             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
424             NECESSARY SERVICING, REPAIR, OR CORRECTION.
425              
426             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
427             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
428             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
429             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
430             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
431             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
432             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
433             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
434             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
435             SUCH DAMAGES.
436              
437             =cut