File Coverage

blib/lib/Dist/Zilla/App/Command/dumpwith.pm
Criterion Covered Total %
statement 85 94 90.4
branch 12 14 85.7
condition 5 7 71.4
subroutine 16 19 84.2
pod 4 4 100.0
total 122 138 88.4


line stmt bran cond sub pod time code
1 4     4   608686 use 5.006;
  4         13  
2 4     4   24 use strict;
  4         14  
  4         128  
3 4     4   36 use warnings;
  4         8  
  4         416  
4              
5             package Dist::Zilla::App::Command::dumpwith;
6              
7             our $VERSION = '0.003002';
8              
9             # ABSTRACT: Dump all plugins that 'do' a certain role
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13              
14              
15              
16              
17              
18              
19              
20              
21              
22              
23              
24              
25 4     4   699 use Dist::Zilla::App '-command';
  4         34646  
  4         42  
26 4     4   12733 use Try::Tiny qw( try catch );
  4         7  
  4         4964  
27              
28             ## no critic ( ProhibitAmbiguousNames)
29 0     0 1 0 sub abstract { return 'Dump all plugins that "do" a specific role' }
30             ## use critic
31              
32             sub opt_spec {
33 6     6 1 397075 return ( [ 'color-theme=s', 'color theme to use, ( eg: basic::blue )' ] );
34             }
35              
36             sub _has_module {
37 1     1   2 my ( undef, $module ) = @_;
38 1         11 require Module::Runtime;
39 1         5 require Try::Tiny;
40 1     1   61 Try::Tiny::try { Module::Runtime::require_module($module) }
41             Try::Tiny::catch {
42 0     0   0 require Carp;
43 0         0 Carp::cluck("The module $module seems invalid, did you type it right? Is it installed?");
44             ## no critic (RequireCarping)
45 0         0 die $_;
46 1         14 };
47 1         51 return;
48             }
49              
50             sub _has_dz_role {
51 3     3   12 my ( undef, $role ) = @_;
52 3         28 require Module::Runtime;
53 3         20 my $module = Module::Runtime::compose_module_name( 'Dist::Zilla::Role', $role );
54 3         303 require Try::Tiny;
55             Try::Tiny::try {
56 3     3   162 Module::Runtime::require_module($module);
57             }
58             Try::Tiny::catch {
59 0     0   0 require Carp;
60 0         0 Carp::cluck("The role -$role seems invalid, did you type it right? Is it installed?");
61             ## no critic (RequireCarping)
62 0         0 die $_;
63 3         50 };
64 3         619954 return;
65             }
66              
67             sub validate_args {
68 6     6 1 3431 my ( $self, $opt, $args ) = @_;
69 6         13 for my $arg ( @{$args} ) {
  6         18  
70 7 100       25 next if q[--] eq $arg;
71 4 100       27 if ( $arg =~ /\A-(.*)\z/msx ) {
72 3         24 $self->_has_dz_role($1);
73             }
74             else {
75 1         6 $self->_has_module($arg);
76             }
77             }
78 6   100     31 my $theme = $opt->color_theme || 'basic::blue';
79             try {
80 6     6   275 $self->_load_color_theme($theme);
81             }
82             catch {
83 1     1   436 my $error = shift;
84 1         8 require Carp;
85 1         4 my $message = $error . qq[\n\n];
86 1         7 $message .= sprintf "^ Was seen attempting to load theme <%s>\n", $theme;
87 1         5 $message .= sprintf 'available themes are: %s', ( join q{, }, $self->_available_themes );
88 1         327 Carp::croak($message);
89 6         136 };
90 5         130 return 1;
91             }
92              
93             sub _available_themes {
94 1     1   4 my (undef) = @_;
95 1         728 require Path::ScanINC;
96 1         5848 my (@theme_dirs) = Path::ScanINC->new()->all_dirs( 'Dist', 'Zilla', 'dumpphases', 'Theme' );
97 1 50       722 if ( not @theme_dirs ) {
98 0         0 require Carp;
99             ## no critic (ValuesAndExpressions::RequireInterpolationOfMetachars)
100 0         0 Carp::cluck('Found no theme dirs in @INC matching Dist/Zilla/dumpphases/Theme/');
101             }
102 1         18 my (%themes);
103 1         11 require Path::Tiny;
104 1         3 for my $dir (@theme_dirs) {
105 1         7 my $it = Path::Tiny->new($dir)->iterator(
106             {
107             recurse => 1,
108             follow_symlinks => 0,
109             },
110             );
111 1         61 while ( my $item = $it->() ) {
112 5 100       814 next unless $item =~ /[.]pm\z/msx;
113 4 50       37 next if -d $item;
114 4         123 my $theme_name = $item->relative($dir);
115 4         690 $theme_name =~ s{[.]pm\z}{}msx;
116 4         52 $theme_name =~ s{/}{::}msxg;
117 4         20 $themes{$theme_name} = 1;
118             }
119             }
120             ## no critic (Variables::ProhibitUnusedVarsStricter)
121 1         57 return ( my (@list) = sort keys %themes );
122             }
123              
124             sub _load_color_theme {
125 11     11   93 my ( undef, $color_theme ) = @_;
126 11         89 require Module::Runtime;
127 11         49 my $theme_module = Module::Runtime::compose_module_name( 'Dist::Zilla::dumpphases::Theme', $color_theme );
128 11         595 Module::Runtime::require_module($theme_module);
129 10         137905 return $theme_module;
130             }
131              
132             sub execute {
133 5     5 1 29 my ( $self, $opt, $args ) = @_;
134 5   100     38 my $theme_module = $self->_load_color_theme( $opt->color_theme || 'basic::blue' );
135 5         56 my $theme = $theme_module->new();
136              
137 5         146 require Scalar::Util;
138 5         11 my $zilla;
139 5         9 for my $arg ( @{$args} ) {
  5         18  
140 7 100       27 next if q[--] eq $arg;
141 4         23 $theme->print_section_prelude( 'role: ', $arg );
142 4   33     15667 $zilla ||= $self->zilla;
143 4         3996390 my $seen = 0;
144 4         13 for my $plugin ( @{ $zilla->plugins_with($arg) } ) {
  4         36  
145 3         1898 $theme->print_star_assoc( $plugin->plugin_name, Scalar::Util::blessed($plugin) );
146 3         535 $seen++;
147             }
148 4 100       876 if ( not $seen ) {
149 1         11 require Carp;
150 1         306 Carp::carp("No plugins matching $arg found");
151             }
152             }
153              
154 5         422 return 0;
155             }
156              
157             1;
158              
159             __END__
160              
161             =pod
162              
163             =encoding UTF-8
164              
165             =head1 NAME
166              
167             Dist::Zilla::App::Command::dumpwith - Dump all plugins that 'do' a certain role
168              
169             =head1 VERSION
170              
171             version 0.003002
172              
173             =head1 SYNOPSIS
174              
175             cd $PROJECT;
176             dzil dumpwith -- -VersionProvider
177              
178             dzil dumpwith --color-theme=basic::plain -- -FileGatherer # plain text
179             dzil dumpwith --color-theme=basic::green -- -BeforeRelease # green text
180              
181             If you are using an HTML-enabled POD viewer, you should see a screenshot of this in action:
182              
183             ( Everyone else can visit L<http://kentnl.github.io/screenshots/Dist-Zilla-App-Command-dumpwith/0.003000/example_01.png> )
184              
185             =for html <center>
186             <img src="http://kentnl.github.io/screenshots/Dist-Zilla-App-Command-dumpwith/0.003000/example_01.png"
187             alt="Screenshot"
188             width="740"
189             height="586"/>
190             </center>
191              
192             =head1 DESCRIPTION
193              
194             This command, like its sibling L<< C<dumpphases>|Dist::Zilla::App::Command::dumpphases >>, exists to help make understanding
195             what is going on in C<Dist::Zilla> a little easier.
196              
197             At least, having this command means debugging certain kinds of problems is more obvious.
198              
199             If you want to see all plugins that are adding files to your dist?
200              
201             dzil dumpwith -- -FileGatherer
202              
203             Though, of course, this requires some knowledge of what roles are applicable.
204              
205             If you want to turn colors off, use L<< C<Term::ANSIcolor>'s environment variable|Term::ANSIColor >>
206             C<ANSI_COLORS_DISABLED>. E.g.,
207              
208             ANSI_COLORS_DISABLED=1 dzil dumpphases
209              
210             Alternatively, specify a color-free theme:
211              
212             dzil dumpwith --color-theme=basic::plain -- -VersionProvider
213              
214             =begin MetaPOD::JSON v1.1.0
215              
216             {
217             "namespace":"Dist::Zilla::App::Command::dumpwith",
218             "inherits":"Dist::Zilla::App::Command",
219             "interface":"class"
220             }
221              
222              
223             =end MetaPOD::JSON
224              
225             =head1 KNOWN ISSUES
226              
227             Prior to C<Dist::Zilla 6.0>, the format
228              
229             dzil dumpwith -VersionProvider
230              
231             Was fine.
232              
233             However, since L<< C<Dist::Zilla 6.0>|https://metacpan.org/changes/release/RJBS/Dist-Zilla-6.000-TRIAL#L9-11 >>,
234             C<Dist::Zilla> maps L<< C<-V> to C<verbose>|https://github.com/rjbs/Dist-Zilla/commit/98f9fb8b60cc645ffd401d08f3014675166ad32c#diff-99ae7353049f6c64733828dfcfe4ffdfR16 >>.
235              
236             To work around this problem on C<Dist::Zilla 6.0> or later, you need to either not use short-hands for roles,
237              
238             # dzil dumpwith -VersionProvider
239             dzil dumpwith Dist::Zilla::Role::VersionProvider
240              
241             Or place all the role names (and only role names) after a C<-->
242              
243             dzil dumpwith --color=... -- -VersionProvider -OtherRole --color-ThisIsAlsoARoleBTWSoDontDoThis
244              
245             Any suggestions welcome for how I can detect this problem case happening and report it,
246             but the data appears now outside of a scope I can probe.
247              
248             =head1 AUTHOR
249              
250             Kent Fredric <kentnl@cpan.org>
251              
252             =head1 COPYRIGHT AND LICENSE
253              
254             This software is copyright (c) 2017 by Kent Fredric <kentfredric@gmail.com>.
255              
256             This is free software; you can redistribute it and/or modify it under
257             the same terms as the Perl 5 programming language system itself.
258              
259             =cut