File Coverage

blib/lib/Dist/Iller/DocType/Dist.pm
Criterion Covered Total %
statement 50 50 100.0
branch 7 10 70.0
condition n/a
subroutine 14 14 100.0
pod 0 6 0.0
total 71 80 88.7


line stmt bran cond sub pod time code
1 2     2   1407 use 5.10.0;
  2         8  
2 2     2   12 use strict;
  2         8  
  2         56  
3 2     2   11 use warnings;
  2         3  
  2         138  
4              
5             package Dist::Iller::DocType::Dist;
6              
7             our $AUTHORITY = 'cpan:CSSON'; # AUTHORITY
8             # ABSTRACT: Turn the Dist::Iller config into a dist.ini file
9             our $VERSION = '0.1409';
10              
11 2     2   13 use Dist::Iller::Elk;
  2         5  
  2         29  
12             with qw/
13             Dist::Iller::DocType
14             Dist::Iller::Role::HasPrereqs
15             Dist::Iller::Role::HasPlugins
16             /;
17              
18 2     2   4853 use Types::Standard qw/HashRef ArrayRef Str Int Bool/;
  2         6  
  2         28  
19 2     2   3206 use PerlX::Maybe qw/maybe provided/;
  2         2653  
  2         19  
20 2     2   170 use List::Util qw/any/;
  2         5  
  2         4337  
21              
22              
23             has name => (
24             is => 'rw',
25             isa => Str,
26             predicate => 1,
27             init_arg => undef,
28             documentation => q{Since 0.1409, consider using 'distribution_name' in doctype:global instead.},
29             );
30             has author => (
31             is => 'rw',
32             isa => (ArrayRef[Str])->plus_coercions(Str, sub { [$_] }),
33             init_arg => undef,
34             traits => ['Array'],
35             default => sub { [ ] },
36             coerce => 1,
37             handles => {
38             all_authors => 'elements',
39             map_authors => 'map',
40             add_author => 'push',
41             has_author => 'count',
42             },
43             );
44             has license => (
45             is => 'rw',
46             isa => Str,
47             predicate => 1,
48             init_arg => undef,
49             );
50             has copyright_holder => (
51             is => 'rw',
52             isa => Str,
53             predicate => 1,
54             init_arg => undef,
55             );
56             has copyright_year => (
57             is => 'rw',
58             isa => Int,
59             predicate => 1,
60             init_arg => undef,
61             );
62             has add_prereqs_as_authordeps => (
63             is => 'rw',
64             isa => Bool,
65             default => 0,
66             );
67              
68              
69 6     6 0 71 sub filename { 'dist.ini' }
70              
71 9     9 0 58 sub phase { 'before' }
72              
73 6     6 0 39 sub comment_start { ';' }
74              
75             sub parse {
76             my $self = shift;
77             my $yaml = shift;
78             if(exists $yaml->{'add_prereqs_as_authordeps'}) {
79             $self->add_prereqs_as_authordeps(delete $yaml->{'add_prereqs_as_authordeps'});
80             }
81             $self->parse_header($yaml->{'header'});
82             $self->parse_default_prereq_versions($yaml->{'default_prereq_versions'});
83             $self->parse_prereqs($yaml->{'prereqs'});
84             $self->parse_plugins($yaml->{'plugins'});
85             }
86              
87             around qw/parse_header parse_prereqs parse_default_prereq_versions/ => sub {
88             my $next = shift;
89             my $self = shift;
90             my $yaml = shift;
91              
92             return if !defined $yaml;
93             $self->$next($yaml);
94             };
95              
96             sub parse_header {
97             my $self = shift;
98             my $yaml = shift;
99              
100             foreach my $setting (qw/name author license copyright_holder copyright_year/) {
101             my $value = $yaml->{ $setting };
102             my $predicate = "has_$setting";
103              
104             if(!$self->$predicate && $value) {
105             $self->$setting($value);
106             }
107             }
108             if (!$self->has_name && $self->global && $self->global->has_distribution_name) {
109             $self->name($self->global->distribution_name);
110             }
111             }
112              
113             sub parse_default_prereq_versions {
114             my $self = shift;
115             my $yaml = shift;
116              
117             # prereqs added from this point forward checks defaults
118             foreach my $default (@{ $yaml }) {
119             $self->set_default_prereq_version((keys %$default)[0], (values %$default)[0]);
120             }
121             # check prereqs already added
122             foreach my $prereq ($self->all_prereqs) {
123             my $default_version = $self->get_default_prereq_version($prereq->module);
124             if($default_version && !$prereq->version) {
125             $prereq->version($default_version);
126             }
127             }
128             }
129              
130             sub parse_prereqs {
131             my $self = shift;
132             my $yaml = shift;
133              
134             foreach my $phase (qw/build configure develop runtime test/) {
135             foreach my $relation (qw/requires recommends suggests conflicts/) {
136              
137             MODULE:
138             foreach my $module (@{ $yaml->{ $phase }{ $relation } }) {
139             my $module_name = ref $module eq 'HASH' ? (keys %$module)[0] : $module;
140             my $version = ref $module eq 'HASH' ? (values %$module)[0] : 0;
141              
142             $self->add_prereq(Dist::Iller::Prereq->new(
143             module => $module_name,
144             phase => $phase,
145             relation => $relation,
146             version => $version,
147             ));
148             }
149             }
150             }
151             }
152              
153             # to_hash does not translate prereqs into [Prereqs / *Phase*Requires] plugins
154             sub to_hash {
155 1     1 0 3 my $self = shift;
156              
157 1         39 my $header = {
158             provided $self->has_author, author => $self->author,
159             maybe name => $self->name,
160             maybe license => $self->license,
161             maybe copyright_holder => $self->copyright_holder,
162             maybe copyright_year => $self->copyright_year,
163              
164             };
165             my $hash = {
166             header => $header,
167             prereqs => $self->prereqs_to_hash,
168 1         6 default_prereq_versions => [ map { +{ $_->[0] => $_->[1] } } $self->all_default_prereq_versions ],
  3         14  
169             plugins => $self->plugins_to_hash,
170             };
171              
172 1         16 return $hash;
173             }
174              
175             sub packages_for_plugin {
176             return sub {
177 73     73   108 my $plugin = shift;
178              
179 73 100       2132 my $name = $plugin->has_base ? $plugin->base : $plugin->plugin_name;
180 73         185 $name =~ m{^(.)};
181 73         140 my $first = $1;
182              
183 73         113 my $clean_name = $name;
184 73         151 $clean_name =~ s{^[-%=@]}{};
185              
186 73         151 my $packages = [];
187 73 50       110 push @{ $packages } => $first eq '%' ? { version => $plugin->version, package => sprintf 'Dist::Zilla::Stash::%s', $clean_name }
  73 50       2018  
    50          
188             : $first eq '@' ? { version => $plugin->version, package => sprintf 'Dist::Zilla::PluginBundle::%s', $clean_name }
189             : $first eq '=' ? { version => $plugin->version, package => sprintf $clean_name }
190             : { version => $plugin->version, package => sprintf 'Dist::Zilla::Plugin::%s', $clean_name }
191             ;
192 73         183 return $packages;
193 4     4 0 207 };
194             }
195              
196             sub add_plugins_as_prereqs {
197 8     8 0 18 my $self = shift;
198 8         16 my $packages_for_plugin = shift;
199 8         36 my @plugins = @_;
200              
201 8         24 for my $plugin (@plugins) {
202 135 100       4814 if($plugin->has_prereqs) {
203 4         154 $self->add_prereq($_) for $plugin->all_prereqs;
204             }
205 135         330 my $packages = $packages_for_plugin->($plugin);
206              
207 135         201 for my $package (@{ $packages }) {
  135         251  
208             $self->add_prereq(Dist::Iller::Prereq->new(
209             module => $package->{'package'},
210             phase => 'develop',
211             relation => 'requires',
212 137         3677 version => $package->{'version'},
213             ));
214             }
215             }
216 8         223 $self->add_prereq(Dist::Iller::Prereq->new(
217             module => 'Dist::Zilla::Plugin::Prereqs',
218             phase => 'develop',
219             relation => 'requires',
220             version => '0',
221             ));
222             }
223              
224             sub to_string {
225             my $self = shift;
226              
227             for my $phase (qw/build configure develop runtime test/) {
228             RELATION:
229             for my $relation (qw/requires recommends suggests conflicts/) {
230              
231             my $plugin_name = sprintf '%s%s', ucfirst $phase, ucfirst $relation;
232              
233             # in case to_string is called twice, don't add this again
234             next RELATION if $self->find_plugin(sub { $_->plugin_name eq $plugin_name });
235              
236             my @prereqs = $self->filter_prereqs(sub { $_->phase eq $phase && $_->relation eq $relation });
237             next RELATION if !scalar @prereqs;
238              
239             $self->add_plugin({
240             plugin_name => $plugin_name,
241             base => 'Prereqs',
242             parameters => { map { $_->module => $_->version } @prereqs },
243             });
244             }
245             }
246              
247             my @strings = ();
248             push @strings => sprintf 'name = %s', $self->name if $self->name;
249              
250             if($self->has_author) {
251             push @strings => $self->map_authors(sub { qq{author = $_} });
252             }
253             push @strings => sprintf 'license = %s', $self->license if $self->has_license;
254             push @strings => sprintf 'copyright_holder = %s', $self->copyright_holder if $self->has_copyright_holder;
255             push @strings => sprintf 'copyright_year = %s', $self->copyright_year if $self->has_copyright_year;
256             push @strings => '' if scalar @strings;
257              
258             foreach my $plugin ($self->all_plugins) {
259             push @strings => $plugin->to_string, '';
260             }
261              
262             {
263             my $has_author_deps = 0;
264             my $previous_module = '';
265              
266             my @phases = ('develop', $self->add_prereqs_as_authordeps ? (qw/runtime test/) : ());
267             my @filtered_prereqs = $self->filter_prereqs(sub {
268             my $prereq = $_;
269             $prereq->relation eq 'requires' && $prereq->module ne 'perl' && (any { $prereq->phase eq $_ } @phases);
270             });
271              
272             AUTHORDEP:
273             foreach my $authordep (sort { $a->module cmp $b->module } @filtered_prereqs) {
274             next AUTHORDEP if $authordep->module eq $previous_module;
275             push @strings => sprintf '; authordep %s = %s', $authordep->module, $authordep->version;
276             $has_author_deps = 1;
277             $previous_module = $authordep->module;
278             }
279             push @strings => '' if $has_author_deps;
280             }
281              
282             return join "\n" => @strings;
283              
284             }
285              
286             __PACKAGE__->meta->make_immutable;
287              
288             1;
289              
290             __END__
291              
292             =pod
293              
294             =encoding UTF-8
295              
296             =head1 NAME
297              
298             Dist::Iller::DocType::Dist - Turn the Dist::Iller config into a dist.ini file
299              
300             =head1 VERSION
301              
302             Version 0.1409, released 2020-12-27.
303              
304             =head1 SOURCE
305              
306             L<https://github.com/Csson/p5-Dist-Iller>
307              
308             =head1 HOMEPAGE
309              
310             L<https://metacpan.org/release/Dist-Iller>
311              
312             =head1 AUTHOR
313              
314             Erik Carlsson <info@code301.com>
315              
316             =head1 COPYRIGHT AND LICENSE
317              
318             This software is copyright (c) 2016 by Erik Carlsson.
319              
320             This is free software; you can redistribute it and/or modify it under
321             the same terms as the Perl 5 programming language system itself.
322              
323             =cut