File Coverage

blib/lib/Dist/Iller/DocType/Dist.pm
Criterion Covered Total %
statement 53 53 100.0
branch 7 10 70.0
condition n/a
subroutine 15 15 100.0
pod 0 6 0.0
total 75 84 89.2


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