File Coverage

blib/lib/Dist/Zilla/App/Command/listdeps.pm
Criterion Covered Total %
statement 49 74 66.2
branch 15 30 50.0
condition n/a
subroutine 6 8 75.0
pod 3 6 50.0
total 73 118 61.8


line stmt bran cond sub pod time code
1             package Dist::Zilla::App::Command::listdeps 6.037;
2             # ABSTRACT: print your distribution's prerequisites
3              
4 4     4   3386 use Dist::Zilla::Pragmas;
  4         10  
  4         209  
5              
6 4     4   47 use Dist::Zilla::App -command;
  4         10  
  4         34  
7              
8             #pod =head1 SYNOPSIS
9             #pod
10             #pod $ dzil listdeps | cpan
11             #pod
12             #pod =head1 DESCRIPTION
13             #pod
14             #pod This is a command plugin for L<Dist::Zilla>. It provides the C<listdeps>
15             #pod command, which prints your distribution's prerequisites. You could pipe that
16             #pod list to a CPAN client like L<cpan> to install all of the dependencies in one
17             #pod quick go.
18             #pod
19             #pod =head1 OPTIONS
20             #pod
21             #pod =head2 --author (or --develop)
22             #pod
23             #pod Include author dependencies (those listed under C<develop_requires>).
24             #pod
25             #pod =head2 --missing
26             #pod
27             #pod List only dependencies which are unsatisfied.
28             #pod
29             #pod =head2 --requires / --no-requires
30             #pod
31             #pod Add required dependencies to the list (or don't).
32             #pod
33             #pod Default: on.
34             #pod
35             #pod =head2 --recommends / --no-recommends
36             #pod
37             #pod Add recommended dependencies to the list (or don't).
38             #pod
39             #pod Default: on.
40             #pod
41             #pod =head2 --suggests / --no-suggests
42             #pod
43             #pod Add suggested dependencies to the list (or don't).
44             #pod
45             #pod Default: off.
46             #pod
47             #pod =head2 --versions
48             #pod
49             #pod Also display the required versions of listed modules.
50             #pod
51             #pod =head2 --cpanm-versions
52             #pod
53             #pod Also display the required versions of listed modules, but in a format suitable
54             #pod for piping into F<cpanm>.
55             #pod
56             #pod =head2 --json
57             #pod
58             #pod Lists all prerequisites in JSON format, as they would appear in META.json
59             #pod (broken out into phases and types)
60             #pod
61             #pod =head1 ACKNOWLEDGEMENTS
62             #pod
63             #pod This code was originally more or less a direct copy of Marcel Gruenauer (hanekomu)
64             #pod Dist::Zilla::App::Command::prereqs, updated to work with the Dist::Zilla v2
65             #pod API.
66             #pod
67             #pod =cut
68              
69 0     0 1 0 sub abstract { "print your distribution's prerequisites" }
70              
71             sub opt_spec {
72 18     18 1 79266 [ 'develop|author', 'include author/develop dependencies' ],
73             [ 'missing', 'list only the missing dependencies' ],
74             [ 'requires!', 'list the required dependencies', { default => 1 } ],
75             [ 'recommends!', 'list the recommended dependencies', { default => 1 } ],
76             [ 'suggests!', 'list the suggested dependencies', {default => 0 } ],
77             [ 'versions', 'include required version numbers in listing' ],
78             [ 'cpanm-versions', 'format versions for consumption by cpanm' ],
79             [ 'json', 'list dependencies by phase, in JSON format' ],
80             [ 'omit-core=s', 'Omit dependencies that are shipped with the specified version of perl' ],
81             }
82              
83             sub prereqs {
84 18     18 0 49 my ($self, $zilla) = @_;
85              
86 18         37 $_->before_build for @{ $zilla->plugins_with(-BeforeBuild) };
  18         90  
87 18         46 $_->gather_files for @{ $zilla->plugins_with(-FileGatherer) };
  18         87  
88 18         75 $_->set_file_encodings for @{ $zilla->plugins_with(-EncodingProvider) };
  18         147  
89 18         47 $_->prune_files for @{ $zilla->plugins_with(-FilePruner) };
  18         105  
90 18         48 $_->munge_files for @{ $zilla->plugins_with(-FileMunger) };
  18         82  
91 18         53 $_->register_prereqs for @{ $zilla->plugins_with(-PrereqSource) };
  18         84  
92              
93 18         786 my $prereqs = $zilla->prereqs;
94             }
95              
96             my @phases = qw/configure build test runtime develop/;
97             my @relationships = qw/requires recommends suggests/;
98              
99             sub filter_core {
100 0     0 0 0 my ($prereqs, $core_version) = @_;
101 0 0       0 $core_version = sprintf '%7.6f', $core_version if $core_version >= 5.010;
102 0 0       0 $prereqs = $prereqs->clone if $prereqs->is_finalized;
103 0         0 require Module::CoreList;
104 0         0 for my $phase (@phases) {
105 0         0 for my $relation (@relationships) {
106 0         0 my $req = $prereqs->requirements_for($phase, $relation);
107 0 0       0 $req->clear_requirement('perl') if $req->accepts_module('perl', $core_version);
108 0         0 for my $module ($req->required_modules) {
109 0 0       0 next if not exists $Module::CoreList::version{$core_version}{$module};
110 0 0       0 $req->clear_requirement($module) if $req->accepts_module($module, $Module::CoreList::version{$core_version}{$module});
111             }
112             }
113             }
114 0         0 return $prereqs;
115             }
116              
117             sub extract_dependencies {
118 18     18 0 60 my ($self, $zilla, $phases, $opt) = @_;
119              
120 18         91 my $prereqs = $self->prereqs($zilla);
121 18 50       128 $prereqs = filter_core($prereqs, $opt->omit_core) if $opt->omit_core;
122              
123 18         270 require CPAN::Meta::Requirements;
124 18         84 my $req = CPAN::Meta::Requirements->new;
125              
126 18         371 for my $phase (@$phases) {
127 78 100       1136 $req->add_requirements( $prereqs->requirements_for($phase, 'requires') ) if $opt->requires;
128 78 100       30797 $req->add_requirements( $prereqs->requirements_for($phase, 'recommends') ) if $opt->recommends;
129 78 100       7657 $req->add_requirements( $prereqs->requirements_for($phase, 'suggests') ) if $opt->suggests;
130             }
131              
132 18         556 my @required = grep { $_ ne 'perl' } $req->required_modules;
  369         992  
133 18 50       123 if ($opt->missing) {
134 0         0 require Module::Runtime;
135             @required =
136             grep {
137             # Keep modules that can't be loaded or that don't have a $VERSION
138             # matching our requirements
139 0         0 ! eval {
  0         0  
140 0         0 my $m = $_;
141             # Will die if module is not installed
142 0         0 Module::Runtime::require_module($m);
143             # Returns true if $VERSION matches, so we will exclude the module
144 0         0 $req->accepts_module($m => $m->VERSION)
145             }
146             } @required;
147             }
148              
149 18         125 my $versions = $req->as_string_hash;
150 18         12721 return map { $_ => $versions->{$_} } @required;
  354         1143  
151             }
152              
153             sub execute {
154 18     18 1 50020 my ($self, $opt, $arg) = @_;
155              
156 18         124 $self->app->chrome->logger->mute;
157              
158 18         219 my @phases = qw(build test configure runtime);
159 18 100       98 push @phases, 'develop' if $opt->develop;
160              
161 18         206 my $omit_core = $opt->omit_core;
162 18 50       94 if($opt->json) {
163 0         0 my $prereqs = $self->prereqs($self->zilla);
164 0 0       0 $prereqs = filter_core($prereqs, $omit_core) if $omit_core;
165 0         0 my $output = $prereqs->as_string_hash;
166              
167 0         0 require JSON::MaybeXS;
168 0         0 print JSON::MaybeXS->new(ascii => 1, canonical => 1, pretty => 1)->encode($output), "\n";
169 0         0 return 1;
170             }
171              
172 18         165 my %modules = $self->extract_dependencies($self->zilla, \@phases, $opt);
173              
174 18         265 my @names = sort { lc $a cmp lc $b } keys %modules;
  1198         2446  
175 18 100       148 if ($opt->versions) {
    100          
176 6         2744 print "$_ = $modules{$_}\n" for @names;
177             } elsif ($opt->cpanm_versions) {
178 6         2756 print "$_~$modules{$_}\n" for @names;
179             } else {
180 6         2834 print "$_\n" for @names;
181             }
182             }
183              
184             1;
185              
186             __END__
187              
188             =pod
189              
190             =encoding UTF-8
191              
192             =head1 NAME
193              
194             Dist::Zilla::App::Command::listdeps - print your distribution's prerequisites
195              
196             =head1 VERSION
197              
198             version 6.037
199              
200             =head1 SYNOPSIS
201              
202             $ dzil listdeps | cpan
203              
204             =head1 DESCRIPTION
205              
206             This is a command plugin for L<Dist::Zilla>. It provides the C<listdeps>
207             command, which prints your distribution's prerequisites. You could pipe that
208             list to a CPAN client like L<cpan> to install all of the dependencies in one
209             quick go.
210              
211             =head1 PERL VERSION
212              
213             This module should work on any version of perl still receiving updates from
214             the Perl 5 Porters. This means it should work on any version of perl
215             released in the last two to three years. (That is, if the most recently
216             released version is v5.40, then this module should work on both v5.40 and
217             v5.38.)
218              
219             Although it may work on older versions of perl, no guarantee is made that the
220             minimum required version will not be increased. The version may be increased
221             for any reason, and there is no promise that patches will be accepted to
222             lower the minimum required perl.
223              
224             =head1 OPTIONS
225              
226             =head2 --author (or --develop)
227              
228             Include author dependencies (those listed under C<develop_requires>).
229              
230             =head2 --missing
231              
232             List only dependencies which are unsatisfied.
233              
234             =head2 --requires / --no-requires
235              
236             Add required dependencies to the list (or don't).
237              
238             Default: on.
239              
240             =head2 --recommends / --no-recommends
241              
242             Add recommended dependencies to the list (or don't).
243              
244             Default: on.
245              
246             =head2 --suggests / --no-suggests
247              
248             Add suggested dependencies to the list (or don't).
249              
250             Default: off.
251              
252             =head2 --versions
253              
254             Also display the required versions of listed modules.
255              
256             =head2 --cpanm-versions
257              
258             Also display the required versions of listed modules, but in a format suitable
259             for piping into F<cpanm>.
260              
261             =head2 --json
262              
263             Lists all prerequisites in JSON format, as they would appear in META.json
264             (broken out into phases and types)
265              
266             =head1 ACKNOWLEDGEMENTS
267              
268             This code was originally more or less a direct copy of Marcel Gruenauer (hanekomu)
269             Dist::Zilla::App::Command::prereqs, updated to work with the Dist::Zilla v2
270             API.
271              
272             =head1 AUTHOR
273              
274             Ricardo SIGNES 😏 <cpan@semiotic.systems>
275              
276             =head1 COPYRIGHT AND LICENSE
277              
278             This software is copyright (c) 2026 by Ricardo SIGNES.
279              
280             This is free software; you can redistribute it and/or modify it under
281             the same terms as the Perl 5 programming language system itself.
282              
283             =cut