File Coverage

blib/lib/Dist/Zilla/Plugin/if.pm
Criterion Covered Total %
statement 32 32 100.0
branch n/a
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 43 43 100.0


line stmt bran cond sub pod time code
1 8     8   16271735 use 5.010; # _Pulp__5010_qr_m_propagate_properly
  8         25  
2 8     8   40 use strict;
  8         12  
  8         206  
3 8     8   33 use warnings;
  8         12  
  8         290  
4 8     8   533 use utf8;
  8         20  
  8         76  
5              
6             package Dist::Zilla::Plugin::if;
7              
8             our $VERSION = '0.002002';
9              
10             # ABSTRACT: Load a plugin only if a condition is true
11              
12             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
13              
14 8     8   1062 use Moose qw( has around with );
  8         292847  
  8         60  
15 8     8   35379 use Dist::Zilla::Util qw();
  8         9380  
  8         162  
16 8     8   34 use Eval::Closure qw( eval_closure );
  8         9  
  8         3661  
17              
18             with 'Dist::Zilla::Role::PluginLoader::Configurable';
19              
20             around dump_config => sub {
21             my ( $orig, $self, @args ) = @_;
22             my $config = $self->$orig(@args);
23             my $localconf = $config->{ +__PACKAGE__ } = {};
24              
25             $localconf->{conditions} = $self->conditions;
26              
27             $localconf->{ q[$] . __PACKAGE__ . '::VERSION' } = $VERSION
28             unless __PACKAGE__ eq ref $self;
29              
30             return $config;
31             };
32              
33             around mvp_aliases => sub {
34             my ( $orig, $self, @rest ) = @_;
35             my $hash = $self->$orig(@rest);
36             $hash = {
37             %{$hash},
38             q{?} => 'conditions',
39             q[condition] => 'conditions',
40             };
41             return $hash;
42             };
43              
44             around mvp_multivalue_args => sub {
45             my ( $orig, $self, @args ) = @_;
46             return ( qw( conditions ), $self->$orig(@args) );
47             };
48              
49             has conditions => ( is => 'ro', lazy_build => 1 );
50 5     5   134 sub _build_conditions { return [] }
51              
52             sub check_conditions {
53 7     7 1 10 my ($self) = @_;
54              
55 7         13 my $env = {};
56             ## no critic (ValuesAndExpressions::RequireInterpolationOfMetachars)
57 7         199 $env->{q[$root]} = \$self->zilla->root;
58 7         419 $env->{q[$zilla]} = \$self->zilla;
59 7         40 my $code = join q[ and ], @{ $self->conditions }, q[1];
  7         199  
60 7         43 my $closure = eval_closure(
61             source => qq[sub { \n] . $code . qq[}\n],
62             environment => $env,
63             );
64             ## use critic;
65 7         1728 return $closure->();
66             }
67              
68             around 'load_plugins' => sub {
69             my ( $orig, $self, $loader ) = @_;
70             return unless $self->check_conditions;
71             return $self->$orig($loader);
72             };
73              
74             __PACKAGE__->meta->make_immutable;
75 8     8   43 no Moose;
  8         12  
  8         54  
76              
77             1;
78              
79             __END__
80              
81             =pod
82              
83             =encoding UTF-8
84              
85             =head1 NAME
86              
87             Dist::Zilla::Plugin::if - Load a plugin only if a condition is true
88              
89             =head1 VERSION
90              
91             version 0.002002
92              
93             =head1 SYNOPSIS
94              
95             [if / FooLoader]
96             dz_plugin = Git::Contributors
97             dz_plugin_name = KNL/Git::Contributors
98             dz_plugin_minversion = 0.010
99             ?= -e $root . '.git'
100             ?= -e $root . '.git/config'
101             >= include_authors = 1
102             >= include_releaser = 0
103             >= order_by = name
104              
105             =head1 DESCRIPTION
106              
107             C<if> is intended to be a similar utility to L<< perl C<if>|if >>.
108              
109             It will execute all of C<condition> in turn, and only when all return true, will the plugin
110             be added to C<Dist::Zilla>
111              
112             =head1 METHODS
113              
114             =head2 C<mvp_aliases>
115              
116             =over 4
117              
118             =item * C<dz_plugin_arguments=> can be written as C<< >= >> or C<< dz_plugin_argument= >>
119              
120             =item * C<conditions=> can be written as C<< ?= >> or C<< condition= >>
121              
122             =back
123              
124             =head2 C<mvp_multivalue_args>
125              
126             All of the following support multiple declaration:
127              
128             =over 4
129              
130             =item * C<dz_plugin_arguments>
131              
132             =item * C<prereq_to>
133              
134             =item * C<conditions>
135              
136             =back
137              
138             =head2 C<register_prereqs>
139              
140             By default, registers L</dz_plugin_package> version L</dz_plugin_minimumversion>
141             as C<develop.requires> ( as per L</prereq_to> ).
142              
143             =head2 check_conditions
144              
145             Compiles C<conditions> into a single sub and executes it.
146              
147             conditions = y and foo
148             conditions = x blah
149              
150             Compiles as
151              
152             sub { y and foo and x blah and 1 }
153              
154             But with C<$root> and C<$zilla> in scope.
155              
156             =head1 ATTRIBUTES
157              
158             =head2 C<dz_plugin>
159              
160             B<REQUIRED>
161              
162             The C<plugin> identifier.
163              
164             For instance, C<[GatherDir / Foo]> and C<[GatherDir]> approximation would both set this field to
165              
166             dz_plugin => 'GatherDir'
167              
168             =head2 C<dz_plugin_name>
169              
170             The "Name" for the C<plugin>.
171              
172             For instance, C<[GatherDir / Foo]> would set this value as
173              
174             dz_plugin_name => "Foo"
175              
176             and C<[GatherDir]> approximation would both set this field to
177              
178             dz_plugin_name => "Foo"
179              
180             In C<Dist::Zilla>, C<[GatherDir]> is equivalent to C<[GatherDir / GatherDir]>.
181              
182             Likewise, if you do not specify C<dz_plugin_name>, the value of C<dz_plugin> will be used.
183              
184             =head2 C<dz_plugin_minversion>
185              
186             The minimum version of C<dz_plugin> to use.
187              
188             At present, this B<ONLY> affects C<prereq> generation.
189              
190             =head2 C<conditions>
191              
192             A C<mvp_multivalue_arg> attribute that creates an array of conditions
193             that must all evaluate to true for the C<dz_plugin> to be injected.
194              
195             These values are internally simply joined with C<and> and executed in an C<Eval::Closure>
196              
197             Two variables are defined in scope for your convenience:
198              
199             =over 4
200              
201             =item * C<$zilla> - The Dist::Zilla builder object itself
202              
203             =item * C<$root> - The same as C<< $zilla->root >> only more convenient.
204              
205             =back
206              
207             For added convenience, this attribute has an alias of '?' ( mnemonic "Test" ), so the following are equivalent:
208              
209             [if]
210             dz_plugin_name = Foo
211             ?= exists $ENV{loadfoo}
212             ?= !!$ENV{loadfoo}
213              
214             [if]
215             dz_plugin_name = Foo
216             condition = exists $ENV{loadfoo}
217             condition = !!$ENV{loadfoo}
218              
219             [if]
220             dz_plugin_name = Foo
221             conditions = exists $ENV{loadfoo}
222             conditions = !!$ENV{loadfoo}
223              
224             =head2 C<dz_plugin_arguments>
225              
226             A C<mvp_multivalue_arg> attribute that creates an array of arguments
227             to pass on to the created plugin.
228              
229             For convenience, this attribute has an alias of '>' ( mnemonic "Forward" ), so that the following example:
230              
231             [GatherDir]
232             include_dotfiles = 1
233             exclude_file = bad
234             exclude_file = bad2
235              
236             Would be written
237              
238             [if]
239             dz_plugin = GatherDir
240             ?= $ENV{dogatherdir}
241             >= include_dotfiles = 1
242             >= exclude_file = bad
243             >= exclude_file = bad2
244              
245             Or in crazy long form
246              
247             [if]
248             dz_plugin = GatherDir
249             condtion = $ENV{dogatherdir}
250             dz_plugin_argument = include_dotfiles = 1
251             dz_plugin_argument = exclude_file = bad
252             dz_plugin_argument = exclude_file = bad2
253              
254             =head2 C<prereq_to>
255              
256             This determines where dependencies get injected.
257              
258             Default is:
259              
260             develop.requires
261              
262             And a special value
263              
264             none
265              
266             Prevents dependency injection.
267              
268             This attribute may be specified multiple times.
269              
270             =head2 C<dz_plugin_package>
271              
272             This is an implementation detail which returns the expanded name of C<dz_plugin>
273              
274             You could probably find some evil use for this, but I doubt it.
275              
276             =head1 AUTHOR
277              
278             Kent Fredric <kentnl@cpan.org>
279              
280             =head1 COPYRIGHT AND LICENSE
281              
282             This software is copyright (c) 2017 by Kent Fredric <kentfredric@gmail.com>.
283              
284             This is free software; you can redistribute it and/or modify it under
285             the same terms as the Perl 5 programming language system itself.
286              
287             =cut