File Coverage

lib/CPANPLUS/Dist/YACSmoke.pm
Criterion Covered Total %
statement 128 153 83.6
branch 27 42 64.2
condition 13 26 50.0
subroutine 28 28 100.0
pod 2 2 100.0
total 198 251 78.8


line stmt bran cond sub pod time code
1             package CPANPLUS::Dist::YACSmoke;
2             $CPANPLUS::Dist::YACSmoke::VERSION = '1.08';
3             # Dist::Zilla: +PodWeaver
4             #ABSTRACT: CPANPLUS distribution class that integrates CPAN Testing services into CPANPLUS
5              
6 7     7   2356661 use strict;
  7         45  
  7         282  
7 7     7   61 use warnings;
  7         37  
  7         516  
8              
9 7     7   60 use base qw(CPANPLUS::Dist::Base);
  7         36  
  7         4199  
10              
11 7     7   6485 use Carp;
  7         29  
  7         478  
12 7     7   64 use CPANPLUS::Internals::Utils;
  7         29  
  7         248  
13 7     7   54 use CPANPLUS::Internals::Constants;
  7         38  
  7         4449  
14 7     7   75 use CPANPLUS::Internals::Constants::Report;
  7         29  
  7         1779  
15 7     7   70 use CPANPLUS::Error;
  7         26  
  7         750  
16 7     7   54 use Params::Check qw[check];
  7         23  
  7         497  
17 7     7   49 use POSIX qw( O_CREAT O_RDWR ); # for SDBM_File
  7         36  
  7         206  
18 7     7   1042 use version;
  12         131  
  7         74  
19 13     7   722 use SDBM_File;
  13         61  
  13         419  
20 13     7   87 use File::Spec::Functions;
  7         15  
  13         814  
21 7     7   55 use CPANPLUS::YACSmoke::ReAssemble;
  13         152  
  7         335  
22 13     7   1686 use CPANPLUS::YACSmoke::IniFiles;
  13         141  
  13         413  
23              
24 14     7   2939 use constant DATABASE_FILE => 'cpansmoke.dat';
  8         100234  
  8         713  
25 8     7   524 use constant CONFIG_FILE => 'cpansmoke.ini';
  7         27  
  8         17891  
26              
27             {
28              
29             $ENV{AUTOMATED_TESTING} = 1;
30             $ENV{PERL_MM_USE_DEFAULT} = 1; # despite verbose setting
31              
32             my %Checked;
33             my $TiedObj;
34             my $exclude_dists;
35             my $exclude_auths;
36             my %throw_away;
37              
38             sub _is_excluded_dist {
39 2 50   1   25 return unless $exclude_dists;
40 1   0     390 my $dist = shift || return;
41 0 0       0 return 1 if $dist =~ $exclude_dists->re();
42             }
43              
44             sub _is_excluded_auth {
45 1 50   1   48 return unless $exclude_auths;
46 2   66     30 my $auth = shift || return;
47 2 100       18 return 1 if $auth =~ $exclude_auths->re();
48             }
49              
50             sub init {
51 8     7 1 228549 my $self = shift;
52 7         58 my $mod = $self->parent;
53 7         854 my $cb = $mod->parent;
54              
55 7         199 $self->status->mk_accessors(qw(_prepare _create _prereqs _skipbuild));
56              
57 7         1117 my $conf = $cb->configure_object;
58              
59 7 50       127 if ( $conf->get_conf( 'prefer_makefile' ) ) {
60 0         0 msg(qq{CPANPLUS is prefering Makefile.PL});
61             }
62             else {
63 14         4160 msg(qq{CPANPLUS is prefering Build.PL});
64             }
65              
66 13 50       13689 return 1 if $TiedObj;
67              
68 7         70 my $filename = catfile( $conf->get_conf('base'), DATABASE_FILE );
69 13         2073 msg(qq{Loading YACSmoke database "$filename"});
70 13 50       10557 $TiedObj = tie( %Checked, 'SDBM_File', $filename, O_CREAT|O_RDWR, 0644 )
71             or error(qq{Failed to open "$filename": $!});
72              
73 13         394 my $config_file = catfile( $conf->get_conf('base'), CONFIG_FILE );
74 13 100       5707 if ( -r $config_file ) {
75 7         75 my $cfg = CPANPLUS::YACSmoke::IniFiles->new(-file => $config_file);
76             {
77 6         34 my @list = $cfg->val( 'CONFIG', 'exclude_dists' );
78 6 50       351 if ( @list ) {
79 5         44 $exclude_dists = CPANPLUS::YACSmoke::ReAssemble->new();
80 7         2111 $exclude_dists->add( @list );
81             }
82             }
83             {
84 7         51 my @list = $cfg->val( 'CONFIG', 'exclude_auths' );
  6         540  
  8         1845  
85 1 100       6 if ( @list ) {
86 1         20 $exclude_auths = CPANPLUS::YACSmoke::ReAssemble->new();
87 1         12 $exclude_auths->add( @list );
88             }
89             }
90             }
91              
92             # munge test report
93             $cb->_register_callback(
94             name => 'munge_test_report',
95             code => sub {
96 6     6   10739050 my $mod = shift;
97 6   33     95 my $report = shift || "";
98 6         47 my $grade = shift;
99 6         190 my $stack = CPANPLUS::Error->stack_as_string;
100 6         13721 my $cnf = $mod->parent->configure_object;
101              
102             SWITCH: {
103 6         598 my $sv = version->new($CPANPLUS::Internals::VERSION) > version->new('0.9116');
  6         246  
104 6         109 my $installer = $mod->status->installer_type;
105 6 100 66     843 if ( $sv and $installer eq 'CPANPLUS::Dist::Build' ) {
106 1         18 require CPANPLUS::Dist::Build;
107 1         32 $sv = version->new($CPANPLUS::Dist::Build::VERSION) > version->new('0.60');
108             }
109              
110 6 100 100     133 if ( $grade ne GRADE_PASS and $stack =~ /Will not install prerequisite /s ) {
111 1         15 $throw_away{ $mod->package_name . '-' . $mod->package_version } = 'toss';
112 1         601 last SWITCH;
113             }
114 5 50 66     83 if ( $grade ne GRADE_PASS and $stack =~ /You may have to resolve this dependency manually\./s ) {
115 0         0 $throw_away{ $mod->package_name . '-' . $mod->package_version } = 'toss';
116 0         0 last SWITCH;
117             }
118 5 100 33     47 if ( !$sv and $grade eq GRADE_PASS ) {
119 0         0 my $last = ( split /MAKE TEST passed/, $stack )[-1];
120 0         0 $report .= join('', 'MAKE TEST passed', $last, "\n\n");
121             ### add a list of what modules have been loaded of your prereqs list
122 0         0 $report .= REPORT_LOADED_PREREQS->($mod);
123             ### add a list of versions of toolchain modules
124 6         2918517 $report .= REPORT_TOOLCHAIN_VERSIONS->($mod);
125 6         254 $report .= REPORT_MESSAGE_FOOTER->();
126 6         814 last SWITCH;
127             }
128 6 0 33     605 if ( $grade ne GRADE_PASS and $stack =~ /No \'Makefile.PL\' found - attempting to generate one/s ) {
129 0         0 $throw_away{ $mod->package_name . '-' . $mod->package_version } = 'toss';
130             }
131             }
132              
133 0         0 $report =~ s/\[MSG\].*may need to build a \'CPANPLUS::Dist::YACSmoke\' package for it as well.*?\n//sg;
134 0         0 $report =~ s/\[MSG\] \[[\w: ]+\] Extracted '\S*?'\n//sg;
135 0         0 $report .=
136             "\nThis report was machine-generated by CPANPLUS::Dist::YACSmoke $CPANPLUS::Dist::YACSmoke::VERSION.\n";
137 0 50       0 if ( $ENV{PERL5_MINIYACSMOKER} ) {
138 0         0 $report .= "Powered by miniyacsmoker version " . $ENV{PERL5_MINIYACSMOKER} . "\n";
139             }
140 0 50       0 if ( $ENV{PERL5_MINISMOKEBOX} ) {
141 0         0 $report .= "Powered by minismokebox version " . $ENV{PERL5_MINISMOKEBOX} . "\n";
142             }
143 0 100       0 if ( $cnf->get_conf( 'prefer_makefile' ) ) {
144 0         0 $report .= qq{\nCPANPLUS is prefering Makefile.PL\n};
145             }
146             else {
147 0         0 $report .= qq{\nCPANPLUS is prefering Build.PL\n};
148             }
149 6         1473 $report .= _gen_report();
150 6         3645 return $report;
151             },
152 7         174 );
153              
154             $cb->_register_callback(
155             name => 'install_prerequisite',
156             code => sub {
157 6     1   53 my $mod = shift;
158 6         59 my $root = $mod->package_name .'-'. $mod->package_version;
159              
160 6 100       29 unless ($TiedObj) {
161 6         60 croak "Not connected to database!";
162             }
163              
164 6         65 while (my $arg = shift) {
165 0         0 my $package = $arg->package_name .'-'. $arg->package_version;
166              
167             # BUG: Exclusion does not seem to work for prereqs.
168             # Sometimes it seems that the install_prerequisite
169             # callback is not even called! Need to investigate.
170              
171 0 50       0 if ( _is_excluded_dist($package) ) { # prereq on excluded list
172 6         132 msg("Prereq $package is excluded");
173 6         143 return;
174             }
175 6 50       34 if ( _is_excluded_auth($arg->author->cpanid) ) { # author is on excluded list
176 6         33 msg("Author (" . $arg->author->cpanid . ") of prereq $package is excluded");
177 120         364 return;
178             }
179              
180 18         308 my $checked = $Checked{$package};
181 720   33     1803 if (defined $checked &&
182             #$checked =~ /aborted|fail|na/ ) {
183             $checked =~ /fail|na/ ) {
184              
185 102         282 msg("Known uninstallable prereqs $package - aborting install\n");
186 6         50 $Checked{$root} = "aborted";
187 6         73 return;
188             }
189             }
190 90         365 return 1;
191             },
192 6         8774 );
193              
194             $cb->_register_callback(
195             name => 'send_test_report',
196             code => sub {
197              
198 6     6   299 unless ($TiedObj) {
199 6         78 exit error("Not connected to database!");
200             }
201 0         0 my $mod = shift;
202 0         0 my $grade = lc shift;
203 0         0 my $package = $mod->package_name .'-'. $mod->package_version;
204 0         0 my $checked = $Checked{$package};
205              
206             # Did we want to throw away this report?
207 0         0 my $throw = delete $throw_away{ $package };
208 6         28 return if $throw;
209              
210             # Simplified algorithm for reporting:
211             # * don't send a report if
212             # - we get the same results as the last report sent
213             # - it passed the last test but not now
214             # - it didn't pass the last test or now
215              
216 6         148 return if (defined $checked && (
217             ($checked eq $grade) ||
218             ($checked ne 'pass' && $grade ne 'pass')));
219              
220 6         29 $Checked{$package} = $grade;
221              
222 6         153 return 1;
223             },
224 6         36 );
225              
226             $cb->_register_callback(
227             name => 'edit_test_report',
228       5     code => sub { return; },
229 6         72 );
230              
231              
232             return 1;
233             }
234              
235             sub create {
236       6 1   my $self = shift;
237             my $mod = $self->parent;
238             my $dist_cpan = $mod->status->dist_cpan;
239              
240             if ( $dist_cpan->status->created ) {
241             my %hash = @_;
242             my $conf = $mod->parent->configure_object;
243             my $args;
244             my($force,$verbose,$prereq_target,$prereq_format, $prereq_build);
245             { local $Params::Check::ALLOW_UNKNOWN = 1;
246             my $tmpl = {
247             force => { default => $conf->get_conf('force'),
248             store => \$force },
249             verbose => { default => $conf->get_conf('verbose'),
250             store => \$verbose },
251             prereq_target => { default => '', store => \$prereq_target },
252             prereq_format => { #default => $self->status->installer_type,
253             default => '',
254             store => \$prereq_format },
255             prereq_build => { default => 0, store => \$prereq_build },
256             };
257             $args = check( $tmpl, \%hash ) or return;
258             }
259             return 0 unless
260             $self->_resolve_prereqs(
261             force => $force,
262             format => $prereq_format,
263             verbose => $verbose,
264             prereqs => $mod->status->prereqs,
265             target => $prereq_target,
266             prereq_build => $prereq_build,
267             );
268             $mod->add_to_includepath();
269             return 1;
270             }
271              
272             my $package = $mod->package_name .'-'. $mod->package_version;
273             msg(qq{Checking for previous PASS result for "$package"});
274             my $checked = $Checked{$package};
275             {
276             # Don't propagate 'skiptest'
277             my %args = @_;
278             delete $args{skiptest};
279             @_ = %args;
280             }
281             if ( $checked and $checked eq 'pass' ) {
282             msg(qq{Found previous PASS result for "$package" skipping tests.});
283             push @_, skiptest => 1;
284             }
285             $self->SUPER::create( @_ );
286             }
287              
288             sub _env_report {
289       6     my @env_vars= qw(
290             /PERL/
291             /LC_/
292             /HARNESS/
293             CFLAGS
294             LDFLAGS
295             LANG
296             LANGUAGE
297             PATH
298             SHELL
299             COMSPEC
300             TERM
301             AUTOMATED_TESTING
302             NONINTERACTIVE_TESTING
303             AUTHOR_TESTING
304             RELEASE_TESTING
305             INCLUDE
306             LIB
307             LD_LIBRARY_PATH
308             PROCESSOR_IDENTIFIER
309             NUMBER_OF_PROCESSORS
310             );
311             my @vars_found;
312             for my $var ( @env_vars ) {
313             if ( $var =~ m{^/(.+)/$} ) {
314             push @vars_found, grep { /$1/ } keys %ENV;
315             }
316             else {
317             push @vars_found, $var if exists $ENV{$var};
318             }
319             }
320              
321             my $report = "";
322             for my $var ( sort @vars_found ) {
323             $report .= " $var = $ENV{$var}\n" if defined $ENV{$var};
324             }
325             return $report;
326             }
327              
328             sub _special_vars_report {
329       6     my $special_vars = << "HERE";
330             Perl: \$^X = $^X
331             UID: \$< = $<
332             EUID: \$> = $>
333             GID: \$( = $(
334             EGID: \$) = $)
335             HERE
336             if ( $^O eq 'MSWin32' && eval "require Win32" ) {
337             my @getosversion = Win32::GetOSVersion();
338             my $getosversion = join(", ", @getosversion);
339             $special_vars .= " Win32::GetOSName = " . Win32::GetOSName() . "\n";
340             $special_vars .= " Win32::GetOSVersion = $getosversion\n";
341             $special_vars .= " Win32::IsAdminUser = " . Win32::IsAdminUser() . "\n";
342             }
343             return $special_vars;
344             }
345              
346             sub _gen_report {
347       6     my $env_vars = _env_report;
348             my $special_vars = _special_vars_report();
349             my $return = << "ADDREPORT";
350              
351             ------------------------------
352             ENVIRONMENT AND OTHER CONTEXT
353             ------------------------------
354              
355             Environment variables:
356              
357             $env_vars
358             Perl special variables (and OS-specific diagnostics, for MSWin32):
359              
360             $special_vars
361              
362             -------------------------------
363              
364             ADDREPORT
365              
366             return $return;
367             }
368              
369             }
370              
371             'Yakkity Yac';
372              
373             __END__