File Coverage

blib/lib/Dist/Zilla/Plugin/Run/Role/Runner.pm
Criterion Covered Total %
statement 120 126 95.2
branch 57 64 89.0
condition 16 21 76.1
subroutine 24 24 100.0
pod 0 2 0.0
total 217 237 91.5


line stmt bran cond sub pod time code
1 12     12   121991 use strict;
  12         41  
  12         400  
2 12     12   81 use warnings;
  12         28  
  12         839  
3             package Dist::Zilla::Plugin::Run::Role::Runner;
4             # vim: set ts=8 sts=4 sw=4 tw=115 et :
5              
6             our $VERSION = '0.048';
7              
8 12     12   94 use Moose::Role;
  12         27  
  12         126  
9 12     12   62788 use namespace::autoclean;
  12         34  
  12         102  
10 12     12   862 use File::Spec (); # core
  12         32  
  12         504  
11 12     12   82 use Config (); # core
  12         29  
  12         312  
12 12     12   78 use Moose::Util 'find_meta';
  12         33  
  12         106  
13              
14             has perlpath => (
15             is => 'ro',
16             isa => 'Str',
17             lazy => 1,
18             builder => 'current_perl_path',
19             );
20              
21             has censor_commands => (
22             is => 'ro',
23             isa => 'Bool',
24             default => 0,
25             );
26              
27             has [ qw(run run_if_trial run_no_trial run_if_release run_no_release) ] => (
28             is => 'ro',
29             isa => 'ArrayRef[Str]',
30             default => sub { [] },
31             );
32              
33             has eval => (
34             is => 'ro',
35             isa => 'ArrayRef[Str]',
36             default => sub { [] },
37             );
38              
39             has fatal_errors => (
40             is => 'ro',
41             isa => 'Bool',
42             default => 1,
43             );
44              
45             has quiet => (
46             is => 'ro',
47             isa => 'Bool',
48             default => 0,
49             );
50              
51             around dump_config => sub
52             {
53             my ($orig, $self) = @_;
54             my $config = $self->$orig;
55              
56             $config->{+__PACKAGE__} = {
57             version => $VERSION,
58             (map { $_ => $self->$_ ? 1 : 0 } qw(fatal_errors quiet)),
59             map {
60             @{ $self->$_ }
61             # look for user:password URIs
62             ? ( $_ => [ map { $self->censor_commands || /\b\w+:[^@]+@\b/ ? 'REDACTED' : $_ } @{ $self->$_ } ] )
63             : ()
64             }
65             qw(run run_if_trial run_no_trial run_if_release run_no_release eval),
66             };
67              
68             return $config;
69             };
70              
71             around BUILDARGS => sub {
72             my ( $orig, $class, @args ) = @_;
73             my $built = $class->$orig(@args);
74              
75             foreach my $dep (qw( notexist_fatal )) {
76             if ( exists $built->{$dep} ) {
77             warn(" !\n ! $class attribute '$dep' is deprecated and has no effect.\n !\n");
78             delete $built->{$dep};
79             }
80             }
81             return $built;
82             };
83              
84             sub _is_trial {
85 28     28   108 my $self = shift;
86              
87             # we want to avoid provoking other plugins prematurely, but also be as
88             # accurate as we can with this status
89              
90 28         976 my $release_status_attr = find_meta($self->zilla)->find_attribute_by_name('release_status');
91              
92 28 100 66     8426 return ( $self->zilla->is_trial ? 1 : 0 ) if
    100          
93             not $release_status_attr # legacy (before Dist::Zilla 5.035)
94             or $release_status_attr->has_value($self->zilla);
95              
96             # otherwise, only use the logic that does not require zilla->version
97             # before Dist::Zilla 5.035, this is what $zilla->is_trial returned
98 8 100       1103 return eval { $self->zilla->_release_status_from_env =~ /\A(?:testing|unstable)\z/ } ? 1 : 0;
  8         319  
99             }
100              
101             sub _call_script {
102 52     52   606 my ( $self, $params ) = @_;
103              
104 52         172 foreach my $run_cmd (@{$self->run}) {
  52         2526  
105 43         1379 $self->_run_cmd($run_cmd, $params);
106             }
107              
108 47         42442 foreach my $run_cmd (@{$self->run_if_trial}) {
  47         3228  
109 4 100       59 if ($self->_is_trial) {
110 2         203 $self->_run_cmd($run_cmd, $params);
111             } else {
112 2         183 $self->log_debug([ 'not executing, because no trial: %s', $run_cmd ]);
113             }
114             }
115              
116 47         4651 foreach my $run_cmd (@{$self->run_no_trial}) {
  47         2898  
117 6 100       92 if ($self->_is_trial) {
118 3         611 $self->log_debug([ 'not executing, because trial: %s', $run_cmd ]);
119             } else {
120 3         385 $self->_run_cmd($run_cmd, $params);
121             }
122             }
123              
124 47 100 66     6237 my $is_release = defined $ENV{'DZIL_RELEASING'} && $ENV{'DZIL_RELEASING'} == 1 ? 1 : 0;
125              
126 47         250 foreach my $run_cmd (@{$self->run_if_release}) {
  47         2659  
127 0 0       0 if ($is_release) {
128 0         0 $self->_run_cmd($run_cmd, $params);
129             } else {
130 0         0 $self->log_debug([ 'not executing, because no release: %s', $run_cmd ]);
131             }
132             }
133              
134 47         202 foreach my $run_cmd (@{$self->run_no_release}) {
  47         2436  
135 0 0       0 if ($is_release) {
136 0         0 $self->log_debug([ 'not executing, because release: %s', $run_cmd ]);
137             } else {
138 0         0 $self->_run_cmd($run_cmd, $params);
139             }
140             }
141              
142 47 100       165 if (my @code = @{ $self->eval }) {
  47         2471  
143 18         137 my $code = join "\n", @code;
144              
145 18         137 $self->_eval_cmd($code, $params);
146             }
147             }
148              
149             sub _run_cmd {
150 50     50   334 my ( $self, $run_cmd, $params, $dry_run ) = @_;
151              
152 50 100       303 if ($dry_run) {
153 1         7 $self->log_debug([ 'dry run, would run: %s', $run_cmd ]);
154 1         517 return;
155             }
156              
157 49 50       304 return if not $run_cmd;
158              
159 49         5988 require IPC::Open3; # core
160              
161 49         27505 my $command = $self->build_formatter($params)->format($run_cmd);
162 49 100       9870 $self->${ $self->quiet ? \'log_debug' : \'log' }([ 'executing: %s', $command ]);
  49         2397  
163              
164             # autoflush STDOUT so we can see command output right away
165 49         20344 local $| = 1;
166             # combine STDOUT and STDERR for ease of proxying through the logger
167 49         371 my $pid = IPC::Open3::open3(my ($in, $out), undef, $command);
168 49 50       331315 binmode $out, ':crlf' if $^O eq 'MSWin32';
169 49         938990 while(defined(my $line = <$out>)){
170 8         58 chomp($line); # logger appends its own newline
171 8 100       70 $self->${ $self->quiet ? \'log_debug' : \'log' }($line);
  8         1019  
172             }
173              
174             # zombie repellent
175 49         7524 waitpid($pid, 0);
176              
177 49 100       1325 if (my $status = ($? >> 8)) {
178 10 100       189 $self->${ $self->fatal_errors ? \'log_fatal' : $self->quiet ? \'log_debug' : \'log'}
  10 100       1143  
179             ([ 'command exited with status %s (%s)', $status, $? ]);
180             }
181             else {
182 39         1308 $self->log_debug('command executed successfully');
183             }
184             }
185              
186             sub _eval_cmd {
187 20     20   99 my ( $self, $code, $params, $dry_run ) = @_;
188              
189 20 100       88 if ($dry_run) {
190 1         7 $self->log_debug([ 'dry run, would evaluate: %s', $code ]);
191 1         319 return;
192             }
193              
194 19         180 $code = $self->build_formatter($params)->format($code);
195 19 100       4201 $self->${ $self->quiet ? \'log_debug' : \'log' }([ 'evaluating: %s', $code ]);
  19         938  
196              
197 19         6909 my $sub = __eval_wrapper($code);
198 19         117 $sub->($self);
199 19         3220 my $error = $@;
200              
201 19 100 66     518 if (defined $error and $error ne '') {
202 8 100 100     383 if ($self->fatal_errors and $self->quiet and not $self->zilla->logger->get_debug) {
      66        
203 1         214 $self->log([ 'evaluated: %s', $code]);
204             }
205              
206 8 100       468 $self->${ $self->fatal_errors ? \'log_fatal' : $self->quiet ? \'log_debug' : \'log'}
  8 100       410  
207             ([ 'evaluation died: %s', $error ]);
208             }
209             }
210              
211             sub __eval_wrapper {
212 19     19   76 my $code = shift;
213 19     19   231 sub { eval $code };
  19     1   2334  
  1         18  
  1         9  
  1         206  
214             }
215              
216             around mvp_multivalue_args => sub {
217             my ($original, $self) = @_;
218              
219             my @res = $self->$original();
220              
221             push @res, qw( run run_no_trial run_if_trial run_if_release run_no_release eval );
222              
223             @res;
224             };
225              
226             my $path_separator = (File::Spec->catfile(qw(a b)) =~ m/^a(.+?)b$/)[0];
227              
228             sub build_formatter {
229 70     70 0 84440 my ( $self, $params ) = @_;
230              
231 70         6357 require String::Formatter;
232 70         38022 String::Formatter->VERSION(0.102082);
233              
234             my $codes = {
235             # not always available
236             # explicitly pass a string (not an object) [rt-72008]
237             a => sub {
238 26 100   26   2019 return "$params->{archive}" if defined $params->{archive};
239 12         105 $self->log('attempting to use %a in a non-Release plugin');
240 12         4204 '';
241             },
242              
243             # source dir
244             o => sub {
245 64   66 64   7107 my $dir = $params->{source_dir} || $self->zilla->root;
246 64 50       3383 return $dir ? "$dir" : '';
247             },
248              
249             # build dir or mint dir
250             d => sub {
251 36     36   2005 require Path::Tiny;
252             # stringify build directory
253 36   100     939 my $dir = $params->{dir} || $self->zilla->built_in;
254 36 100       1649 return Path::Tiny::path($dir)->canonpath if $dir;
255 4         35 $self->log('attempting to use %d in before_build');
256 4         1825 '';
257             },
258              
259             # distribution name
260 30     30   2180 n => sub { $self->zilla->name },
261              
262             # backward compatibility (don't error)
263             s => '',
264              
265             # portability
266             p => $path_separator,
267 58     58   17877 x => sub { $self->perlpath },
268 70         3044 };
269              
270             # available during build, not mint
271 70 100       428 unless( $params->{minting} ){
272 68     33   871 $codes->{v} = sub { $self->zilla->version };
  33         6078  
273 68 100   18   673 $codes->{t} = sub { $self->_is_trial ? '-TRIAL' : '' };
  18         4816  
274             }
275              
276             # positional replacement of %s (backward compatible)
277 70 100       218 if( my @pos = @{ $params->{pos} || [] } ){
  70 100       671  
278             # where are you defined-or // operator?
279             $codes->{s} = sub {
280 41     41   2362 my $s = shift(@pos);
281 41 100       204 $s = $s->() if ref $s eq 'CODE';
282 41 100       7872 defined($s) ? $s : '';
283 61         523 };
284             }
285              
286 70         1031 return String::Formatter->new({ codes => $codes });
287             }
288              
289 37     37 0 4234 sub current_perl_path { $^X }
290              
291             1;