| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # TODO: several resources per client? | 
| 2 |  |  |  |  |  |  | package CPAN::Testers::Common::Client; | 
| 3 | 4 |  |  | 4 |  | 43024 | use warnings; | 
|  | 4 |  |  |  |  | 7 |  | 
|  | 4 |  |  |  |  | 113 |  | 
| 4 | 4 |  |  | 4 |  | 14 | use strict; | 
|  | 4 |  |  |  |  | 3 |  | 
|  | 4 |  |  |  |  | 66 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 4 |  |  | 4 |  | 1861 | use Devel::Platform::Info; | 
|  | 4 |  |  |  |  | 1299 |  | 
|  | 4 |  |  |  |  | 92 |  | 
| 7 | 4 |  |  | 4 |  | 1561 | use Probe::Perl; | 
|  | 4 |  |  |  |  | 4602 |  | 
|  | 4 |  |  |  |  | 89 |  | 
| 8 | 4 |  |  | 4 |  | 1790 | use Config::Perl::V; | 
|  | 4 |  |  |  |  | 6495 |  | 
|  | 4 |  |  |  |  | 160 |  | 
| 9 | 4 |  |  | 4 |  | 49 | use Carp (); | 
|  | 4 |  |  |  |  | 4 |  | 
|  | 4 |  |  |  |  | 56 |  | 
| 10 | 4 |  |  | 4 |  | 13 | use File::Spec; | 
|  | 4 |  |  |  |  | 3 |  | 
|  | 4 |  |  |  |  | 66 |  | 
| 11 | 4 |  |  | 4 |  | 1501 | use Capture::Tiny qw(capture); | 
|  | 4 |  |  |  |  | 65411 |  | 
|  | 4 |  |  |  |  | 207 |  | 
| 12 | 4 |  |  | 4 |  | 1613 | use CPAN::Testers::Common::Client::PrereqCheck; | 
|  | 4 |  |  |  |  | 10 |  | 
|  | 4 |  |  |  |  | 125 |  | 
| 13 | 4 |  |  | 4 |  | 1374 | use CPAN::Testers::Common::Client::History; | 
|  | 4 |  |  |  |  | 13 |  | 
|  | 4 |  |  |  |  | 122 |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 | 4 |  |  | 4 |  | 19 | use constant MAX_OUTPUT_LENGTH => 1_000_000; | 
|  | 4 |  |  |  |  | 4 |  | 
|  | 4 |  |  |  |  | 9454 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | our $VERSION = '0.13'; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | #================================== | 
| 21 |  |  |  |  |  |  | #  CONSTRUCTOR | 
| 22 |  |  |  |  |  |  | #================================== | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | sub new { | 
| 25 | 2 |  |  | 2 | 1 | 2231 | my ($class, %params) = @_; | 
| 26 | 2 |  |  |  |  | 6 | my $self  = bless {}, $class; | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 2 | 50 |  |  |  | 6 | Carp::croak q[Please specify a distname]           unless $params{distname}; | 
| 29 | 2 | 50 |  |  |  | 5 | Carp::croak q[Please specify the dist's author]    unless $params{author}; | 
| 30 | 2 | 50 |  |  |  | 5 | Carp::croak q[Please specify a grade for the dist] unless $params{grade}; | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 2 |  |  |  |  | 10 | $self->_init( %params ); | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 2 |  |  |  |  | 9 | return $self; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | sub _init { | 
| 38 | 2 |  |  | 2 |  | 6 | my ($self, %params) = @_; | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 2 |  |  |  |  | 6 | $self->grade( $params{grade} ); | 
| 41 | 2 |  |  |  |  | 5 | $self->distname( $params{distname} ); | 
| 42 | 2 |  |  |  |  | 3 | $self->author( $params{author} ); | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | $self->via( exists $params{via} | 
| 45 |  |  |  |  |  |  | ? $params{via} | 
| 46 | 2 | 100 |  |  |  | 11 | : "your friendly CPAN Testers client version $VERSION" | 
| 47 |  |  |  |  |  |  | ); | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | $self->comments( exists $params{comments} | 
| 50 |  |  |  |  |  |  | ? $params{comments} | 
| 51 |  |  |  |  |  |  | : $ENV{AUTOMATED_TESTING} | 
| 52 | 2 | 50 |  |  |  | 9 | ? "this report is from an automated smoke testing program\nand was not reviewed by a human for accuracy" | 
|  |  | 100 |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | : 'none provided' | 
| 54 |  |  |  |  |  |  | ); | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 2 | 100 |  |  |  | 6 | $self->command( $params{command} ) if exists $params{command}; | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 2 | 100 |  |  |  | 7 | if ( $params{prereqs} ) { | 
|  |  | 50 |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | $self->{_meta}{prereqs} = $params{prereqs} | 
| 60 | 1 |  |  |  |  | 3 | } | 
| 61 |  |  |  |  |  |  | elsif ( $params{build_dir} ) { | 
| 62 | 0 |  |  |  |  | 0 | $self->_get_prereqs( $params{build_dir} ); | 
| 63 |  |  |  |  |  |  | } | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 2 |  |  |  |  | 5 | foreach my $output ( qw( configure build test ) ) { | 
| 66 | 6 |  |  |  |  | 4 | my $key = $output . '_output'; | 
| 67 | 6 | 100 |  |  |  | 13 | if (exists $params{$key}) { | 
| 68 | 3 |  |  |  |  | 8 | $self->{_output}{$output} = $params{$key}; | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 2 |  |  |  |  | 4 | return; | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | #====================================== | 
| 77 |  |  |  |  |  |  | #  ACCESSORS | 
| 78 |  |  |  |  |  |  | #====================================== | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | sub comments { | 
| 81 | 7 |  |  | 7 | 1 | 10 | my ($self, $comment) = @_; | 
| 82 | 7 | 100 |  |  |  | 16 | $self->{_comment} = $comment if $comment; | 
| 83 | 7 |  |  |  |  | 35 | return $self->{_comment}; | 
| 84 |  |  |  |  |  |  | } | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | sub via { | 
| 87 | 5 |  |  | 5 | 1 | 6 | my ($self, $via) = @_; | 
| 88 | 5 | 100 |  |  |  | 15 | $self->{_via} = $via if $via; | 
| 89 | 5 |  |  |  |  | 12 | return $self->{_via}; | 
| 90 |  |  |  |  |  |  | } | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | sub author { | 
| 93 | 5 |  |  | 5 | 1 | 611 | my ($self, $author) = @_; | 
| 94 | 5 | 100 |  |  |  | 15 | $self->{_author} = $author if $author; | 
| 95 | 5 |  |  |  |  | 13 | return $self->{_author}; | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | #FIXME? the distname in CPAN::Reporter is validated | 
| 100 |  |  |  |  |  |  | # under a specific regex in line 368. We should | 
| 101 |  |  |  |  |  |  | # move that logic here. | 
| 102 |  |  |  |  |  |  | sub distname { | 
| 103 | 7 |  |  | 7 | 1 | 7 | my ($self, $distname) = @_; | 
| 104 | 7 | 100 |  |  |  | 18 | $self->{_distname} = $distname if $distname; | 
| 105 |  |  |  |  |  |  |  | 
| 106 | 7 |  |  |  |  | 19 | return $self->{_distname}; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | sub grade { | 
| 110 | 11 |  |  | 11 | 1 | 20 | my ($self, $grade) = @_; | 
| 111 | 11 | 100 |  |  |  | 36 | $self->{_grade} = lc $grade if $grade; | 
| 112 | 11 |  |  |  |  | 78 | return $self->{_grade}; | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | sub command { | 
| 116 | 4 |  |  | 4 | 1 | 8 | my ($self, $command) = @_; | 
| 117 | 4 | 100 |  |  |  | 11 | $self->{_command} = $command if $command; | 
| 118 | 4 |  | 100 |  |  | 37 | return $self->{_command} || ''; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | #==================================== | 
| 122 |  |  |  |  |  |  | #  PUBLIC METHODS | 
| 123 |  |  |  |  |  |  | #==================================== | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | sub is_duplicate { | 
| 126 | 1 |  |  | 1 | 1 | 2 | my ($self) = @_; | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 1 |  |  |  |  | 2 | my $grade     = $self->grade; | 
| 129 | 1 |  |  |  |  | 3 | my $dist_name = $self->distname; | 
| 130 | 1 | 50 | 33 |  |  | 6 | return 0 unless $grade && $dist_name; | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | #FIXME: CPAN::Reporter allows for 3 phases: 'PL', 'make' or 'test'. | 
| 133 |  |  |  |  |  |  | # Until this is properly ported, we'll only use the 'test' phase. | 
| 134 | 1 |  |  |  |  | 5 | return CPAN::Testers::Common::Client::History::is_duplicate({ | 
| 135 |  |  |  |  |  |  | phase     => 'test', | 
| 136 |  |  |  |  |  |  | grade     => $grade, | 
| 137 |  |  |  |  |  |  | dist_name => $dist_name, | 
| 138 |  |  |  |  |  |  | }); | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | sub record_history { | 
| 142 | 1 |  |  | 1 | 1 | 1 | my ($self) = @_; | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 1 |  |  |  |  | 2 | my $grade     = $self->grade; | 
| 145 | 1 |  |  |  |  | 3 | my $dist_name = $self->distname; | 
| 146 | 1 | 50 | 33 |  |  | 5 | return unless $grade && $dist_name; | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | #FIXME: CPAN::Reporter allows for 3 phases: 'PL', 'make' or 'test'. | 
| 149 |  |  |  |  |  |  | # Until this is properly ported, we'll only use the 'test' phase. | 
| 150 | 1 |  |  |  |  | 5 | return CPAN::Testers::Common::Client::History::record_history({ | 
| 151 |  |  |  |  |  |  | phase     => 'test', | 
| 152 |  |  |  |  |  |  | grade     => $grade, | 
| 153 |  |  |  |  |  |  | dist_name => $dist_name, | 
| 154 |  |  |  |  |  |  | }); | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | sub populate { | 
| 158 | 2 |  |  | 2 | 1 | 2 | my $self = shift; | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | # some data is repeated between facts, so we keep a 'cache' | 
| 161 | 2 |  |  |  |  | 11 | $self->{_config}   = Config::Perl::V::myconfig(); | 
| 162 | 2 |  |  |  |  | 1098 | $self->{_platform} = Devel::Platform::Info->new->get_info(); | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | # LegacyReport creates the email, therefore it must | 
| 165 |  |  |  |  |  |  | # be set last so all other data is already in place. | 
| 166 | 2 |  |  |  |  | 170741 | my @facts = qw( | 
| 167 |  |  |  |  |  |  | TestSummary TestOutput TesterComment | 
| 168 |  |  |  |  |  |  | Prereqs InstalledModules | 
| 169 |  |  |  |  |  |  | PlatformInfo PerlConfig TestEnvironment | 
| 170 |  |  |  |  |  |  | LegacyReport | 
| 171 |  |  |  |  |  |  | ); | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 2 |  |  |  |  | 8 | foreach my $fact ( @facts ) { | 
| 174 | 18 |  |  |  |  | 31 | my $populator = '_populate_' . lc $fact; | 
| 175 | 18 |  |  |  |  | 67 | $self->{_data}{$fact} = $self->$populator; | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  |  | 
| 178 | 2 |  |  |  |  | 6 | return $self->metabase_data; | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  |  | 
| 181 | 7 |  |  | 7 | 1 | 2469 | sub metabase_data { return shift->{_data} } | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | sub email { | 
| 184 | 2 |  |  | 2 | 1 | 3 | my $self = shift; | 
| 185 | 2 |  | 66 |  |  | 3 | my $metabase_data = $self->metabase_data || $self->populate; | 
| 186 |  |  |  |  |  |  |  | 
| 187 | 2 |  |  |  |  | 14 | return $metabase_data->{LegacyReport}{textreport}; | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | #=================================================== | 
| 192 |  |  |  |  |  |  | # POPULATORS -- these functions populate | 
| 193 |  |  |  |  |  |  | # the object with data, triggered by the | 
| 194 |  |  |  |  |  |  | # populate() method. | 
| 195 |  |  |  |  |  |  | #=================================================== | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | sub _populate_platforminfo { | 
| 198 | 2 |  |  | 2 |  | 5 | my $self = shift; | 
| 199 | 2 |  |  |  |  | 8 | return $self->{_platform}; | 
| 200 |  |  |  |  |  |  | } | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | sub _populate_perlconfig { | 
| 204 | 2 |  |  | 2 |  | 5 | my $self = shift; | 
| 205 | 2 |  |  |  |  | 3 | return @{ $self->{_config} }{qw(build config)}; | 
|  | 2 |  |  |  |  | 12 |  | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | sub _populate_testenvironment { | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | return { | 
| 211 | 2 |  |  | 2 |  | 10 | environment_vars => _get_env_vars(), | 
| 212 |  |  |  |  |  |  | special_vars     => _get_special_vars(), | 
| 213 |  |  |  |  |  |  | }; | 
| 214 |  |  |  |  |  |  | } | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | sub _populate_prereqs { | 
| 217 | 2 |  |  | 2 |  | 3 | my $self = shift; | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | # TODO: update Fact::Prereqs to use the new meta::spec for prereqs | 
| 220 |  |  |  |  |  |  | # TODO: add the 'test' prereqs? | 
| 221 |  |  |  |  |  |  | return $self->{_meta}{prereqs} | 
| 222 |  |  |  |  |  |  | || { | 
| 223 | 2 |  | 100 |  |  | 29 | runtime   => { requires => {} }, | 
| 224 |  |  |  |  |  |  | build     => { requires => {} }, | 
| 225 |  |  |  |  |  |  | configure => { requires => {} }, | 
| 226 |  |  |  |  |  |  | }; | 
| 227 |  |  |  |  |  |  | #{ | 
| 228 |  |  |  |  |  |  | #    configure_requires => $self->{_meta}{configure_requires} || {}, | 
| 229 |  |  |  |  |  |  | #    build_requires     => $self->{_meta}{build_requires}     || {}, | 
| 230 |  |  |  |  |  |  | #    requires           => $self->{_meta}{requires}           || {}, | 
| 231 |  |  |  |  |  |  | #}; | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | sub _populate_testercomment { | 
| 235 | 2 |  |  | 2 |  | 56 | my $self = shift; | 
| 236 | 2 |  |  |  |  | 11 | return $self->comments; | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | sub _populate_installedmodules { | 
| 240 | 2 |  |  | 2 |  | 3 | my $self = shift; | 
| 241 |  |  |  |  |  |  |  | 
| 242 | 2 |  |  |  |  | 15 | my @toolchain_mods= qw( | 
| 243 |  |  |  |  |  |  | CPAN | 
| 244 |  |  |  |  |  |  | CPAN::Meta | 
| 245 |  |  |  |  |  |  | Cwd | 
| 246 |  |  |  |  |  |  | ExtUtils::CBuilder | 
| 247 |  |  |  |  |  |  | ExtUtils::Command | 
| 248 |  |  |  |  |  |  | ExtUtils::Install | 
| 249 |  |  |  |  |  |  | ExtUtils::MakeMaker | 
| 250 |  |  |  |  |  |  | ExtUtils::Manifest | 
| 251 |  |  |  |  |  |  | ExtUtils::ParseXS | 
| 252 |  |  |  |  |  |  | File::Spec | 
| 253 |  |  |  |  |  |  | JSON | 
| 254 |  |  |  |  |  |  | JSON::PP | 
| 255 |  |  |  |  |  |  | Module::Build | 
| 256 |  |  |  |  |  |  | Module::Signature | 
| 257 |  |  |  |  |  |  | Parse::CPAN::Meta | 
| 258 |  |  |  |  |  |  | Test::Harness | 
| 259 |  |  |  |  |  |  | Test::More | 
| 260 |  |  |  |  |  |  | YAML | 
| 261 |  |  |  |  |  |  | YAML::Syck | 
| 262 |  |  |  |  |  |  | version | 
| 263 |  |  |  |  |  |  | ); | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 2 |  |  |  |  | 7 | my $results = _version_finder( map { $_ => 0 } @toolchain_mods ); | 
|  | 40 |  |  |  |  | 46 |  | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 2 |  |  |  |  | 18 | my %toolchain = map { $_ => $results->{$_}{have} } @toolchain_mods; | 
|  | 40 |  |  |  |  | 58 |  | 
| 268 | 2 |  |  |  |  | 9 | my %prereqs = (); | 
| 269 |  |  |  |  |  |  |  | 
| 270 | 2 |  |  |  |  | 35 | return { prereqs => \%prereqs, toolchain => \%toolchain }; | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | sub _populate_legacyreport { | 
| 275 | 2 |  |  | 2 |  | 4 | my $self = shift; | 
| 276 |  |  |  |  |  |  | return { | 
| 277 | 2 |  |  |  |  | 6 | %{ $self->_populate_testsummary }, | 
|  | 2 |  |  |  |  | 8 |  | 
| 278 |  |  |  |  |  |  | textreport => $self->_create_email, | 
| 279 |  |  |  |  |  |  | } | 
| 280 |  |  |  |  |  |  | } | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | sub _populate_testsummary { | 
| 283 | 4 |  |  | 4 |  | 10 | my $self = shift; | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | return { | 
| 286 |  |  |  |  |  |  | grade        => $self->grade, | 
| 287 |  |  |  |  |  |  | osname       => $self->{_platform}{osname}, | 
| 288 |  |  |  |  |  |  | osversion    => $self->{_platform}{osvers}, | 
| 289 |  |  |  |  |  |  | archname     => $self->{_platform}{archname}, | 
| 290 |  |  |  |  |  |  | perl_version => $self->{_config}{config}{version}, | 
| 291 |  |  |  |  |  |  | } | 
| 292 | 4 |  |  |  |  | 25 | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | sub _populate_testoutput { | 
| 295 | 2 |  |  | 2 |  | 5 | my $self = shift; | 
| 296 | 2 |  |  |  |  | 11 | return $self->{_output}; | 
| 297 |  |  |  |  |  |  | } | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | #===================================================== | 
| 301 |  |  |  |  |  |  | #  FORMATTERS -- functions to aid email formatting | 
| 302 |  |  |  |  |  |  | #===================================================== | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | sub _format_vars_report { | 
| 305 | 4 |  |  | 4 |  | 3 | my $variables = shift; | 
| 306 |  |  |  |  |  |  |  | 
| 307 | 4 |  |  |  |  | 5 | my $report = ""; | 
| 308 | 4 |  |  |  |  | 22 | foreach my $var ( sort keys %$variables ) { | 
| 309 | 30 |  |  |  |  | 27 | my $value = $variables->{$var}; | 
| 310 | 30 | 50 |  |  |  | 33 | $value = '[undef]' if ! defined $value; | 
| 311 | 30 |  |  |  |  | 37 | $report .= "    $var = $value\n"; | 
| 312 |  |  |  |  |  |  | } | 
| 313 | 4 |  |  |  |  | 13 | return $report; | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  |  | 
| 316 | 124 | 100 |  | 124 |  | 221 | sub _fix_unknown { defined $_[0] ? $_[0] : 'unknown' } | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | sub _format_toolchain_report { | 
| 319 | 3 |  |  | 3 |  | 950 | my $installed = shift; | 
| 320 | 3 |  |  |  |  | 33 | my $mod_width = _max_length( keys %$installed ); | 
| 321 |  |  |  |  |  |  | my $ver_width = _max_length( | 
| 322 | 3 |  |  |  |  | 11 | map { _fix_unknown( $installed->{$_} ) } keys %$installed | 
|  | 44 |  |  |  |  | 40 |  | 
| 323 |  |  |  |  |  |  | ); | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 3 |  |  |  |  | 13 | my $format = "    \%-${mod_width}s \%-${ver_width}s\n"; | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 3 |  |  |  |  | 4 | my $report = ""; | 
| 328 | 3 |  |  |  |  | 16 | $report .= sprintf( $format, "Module", "Have" ); | 
| 329 | 3 |  |  |  |  | 14 | $report .= sprintf( $format, "-" x $mod_width, "-" x $ver_width ); | 
| 330 |  |  |  |  |  |  |  | 
| 331 | 3 |  |  |  |  | 21 | for my $var ( sort keys %$installed ) { | 
| 332 |  |  |  |  |  |  | $report .= sprintf("    \%-${mod_width}s \%-${ver_width}s\n", | 
| 333 | 44 |  |  |  |  | 62 | $var, _fix_unknown($installed->{$var}) ); | 
| 334 |  |  |  |  |  |  | } | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 3 |  |  |  |  | 44 | return $report; | 
| 337 |  |  |  |  |  |  | } | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | sub _format_prereq_report { | 
| 340 | 4 |  |  | 4 |  | 1470 | my $prereqs = shift; | 
| 341 | 4 |  |  |  |  | 6 | my (%have, %prereq_met, $report); | 
| 342 |  |  |  |  |  |  |  | 
| 343 | 4 |  |  |  |  | 13 | my @prereq_sections = qw( runtime build configure ); | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | # see what prereqs are satisfied in subprocess | 
| 346 | 4 |  |  |  |  | 9 | foreach my $section ( @prereq_sections ) { | 
| 347 | 12 |  |  |  |  | 30 | my $requires = $prereqs->{$section}{requires}; | 
| 348 | 12 | 100 | 66 |  |  | 86 | next unless $requires and ref $requires eq 'HASH' and keys %$requires > 0; | 
|  |  |  | 100 |  |  |  |  | 
| 349 |  |  |  |  |  |  |  | 
| 350 | 5 |  |  |  |  | 28 | my $results = _version_finder( %$requires ); | 
| 351 |  |  |  |  |  |  |  | 
| 352 | 5 |  |  |  |  | 32 | foreach my $mod ( keys %$results ) { | 
| 353 | 11 |  |  |  |  | 28 | $have{$section}{$mod} = $results->{$mod}{have}; | 
| 354 | 11 |  |  |  |  | 34 | $prereq_met{$section}{$mod} = $results->{$mod}{met}; | 
| 355 |  |  |  |  |  |  | } | 
| 356 |  |  |  |  |  |  | } | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | # find formatting widths | 
| 359 | 4 |  |  |  |  | 14 | my ($name_width, $need_width, $have_width) = (6, 4, 4); | 
| 360 | 4 |  |  |  |  | 8 | foreach my $section ( @prereq_sections ) { | 
| 361 | 12 |  |  |  |  | 19 | my $requires = $prereqs->{$section}{requires}; | 
| 362 | 12 | 100 | 66 |  |  | 56 | next unless $requires and ref $requires eq 'HASH'; | 
| 363 |  |  |  |  |  |  |  | 
| 364 | 8 |  |  |  |  | 21 | foreach my $module ( keys %$requires ) { | 
| 365 | 18 |  |  |  |  | 17 | my $name_length = length $module; | 
| 366 | 18 |  |  |  |  | 30 | my $need_length = length $requires->{$module}; | 
| 367 | 18 |  |  |  |  | 38 | my $have_length = length _fix_unknown( $have{$section}{$module} ); | 
| 368 | 18 | 100 |  |  |  | 32 | $name_width = $name_length if $name_length > $name_width; | 
| 369 | 18 | 50 |  |  |  | 28 | $need_width = $need_length if $need_length > $need_width; | 
| 370 | 18 | 100 |  |  |  | 33 | $have_width = $have_length if $have_length > $have_width; | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  | } | 
| 373 |  |  |  |  |  |  |  | 
| 374 | 4 |  |  |  |  | 16 | my $format_str = | 
| 375 |  |  |  |  |  |  | "  \%1s \%-${name_width}s \%-${need_width}s \%-${have_width}s\n"; | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | # generate the report | 
| 378 | 4 |  |  |  |  | 6 | foreach my $section ( @prereq_sections ) { | 
| 379 | 12 |  |  |  |  | 16 | my $requires = $prereqs->{$section}{requires}; | 
| 380 | 12 | 100 | 66 |  |  | 62 | next unless $requires and ref $requires eq 'HASH' and keys %$requires; | 
|  |  |  | 100 |  |  |  |  | 
| 381 |  |  |  |  |  |  |  | 
| 382 | 5 |  |  |  |  | 40 | $report .= "$section:\n\n" | 
| 383 |  |  |  |  |  |  | .  sprintf( $format_str, " ", qw/Module Need Have/ ) | 
| 384 |  |  |  |  |  |  | .  sprintf( $format_str, " ", | 
| 385 |  |  |  |  |  |  | "-" x $name_width, | 
| 386 |  |  |  |  |  |  | "-" x $need_width, | 
| 387 |  |  |  |  |  |  | "-" x $have_width | 
| 388 |  |  |  |  |  |  | ); | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 5 |  |  |  |  | 25 | foreach my $module ( sort {lc $a cmp lc $b} keys %$requires ) { | 
|  | 29 |  |  |  |  | 36 |  | 
| 391 | 18 |  |  |  |  | 21 | my $need = $requires->{$module}; | 
| 392 | 18 |  |  |  |  | 32 | my $have = _fix_unknown( $have{$section}{$module} ); | 
| 393 | 18 | 100 |  |  |  | 40 | my $bad = $prereq_met{$section}{$module} ? " " : "!"; | 
| 394 | 18 |  |  |  |  | 50 | $report .= sprintf( $format_str, $bad, $module, $need, $have); | 
| 395 |  |  |  |  |  |  | } | 
| 396 | 5 |  |  |  |  | 8 | $report .= "\n"; | 
| 397 |  |  |  |  |  |  | } | 
| 398 |  |  |  |  |  |  |  | 
| 399 | 4 |  | 100 |  |  | 56 | return $report || "    No requirements found\n"; | 
| 400 |  |  |  |  |  |  | } | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | #============================================== | 
| 404 |  |  |  |  |  |  | # AUXILIARY (PRIVATE) METHODS AND FUNCTIONS | 
| 405 |  |  |  |  |  |  | #============================================== | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | sub _get_env_vars { | 
| 408 |  |  |  |  |  |  | # Entries bracketed with "/" are taken to be a regex; otherwise literal | 
| 409 | 2 |  |  | 2 |  | 14 | my @env_vars= qw( | 
| 410 |  |  |  |  |  |  | /HARNESS/ | 
| 411 |  |  |  |  |  |  | /LC_/ | 
| 412 |  |  |  |  |  |  | /PERL/ | 
| 413 |  |  |  |  |  |  | /_TEST/ | 
| 414 |  |  |  |  |  |  | CCFLAGS | 
| 415 |  |  |  |  |  |  | COMSPEC | 
| 416 |  |  |  |  |  |  | INCLUDE | 
| 417 |  |  |  |  |  |  | INSTALL_BASE | 
| 418 |  |  |  |  |  |  | LANG | 
| 419 |  |  |  |  |  |  | LANGUAGE | 
| 420 |  |  |  |  |  |  | LD_LIBRARY_PATH | 
| 421 |  |  |  |  |  |  | LDFLAGS | 
| 422 |  |  |  |  |  |  | LIB | 
| 423 |  |  |  |  |  |  | NON_INTERACTIVE | 
| 424 |  |  |  |  |  |  | NUMBER_OF_PROCESSORS | 
| 425 |  |  |  |  |  |  | PATH | 
| 426 |  |  |  |  |  |  | PREFIX | 
| 427 |  |  |  |  |  |  | PROCESSOR_IDENTIFIER | 
| 428 |  |  |  |  |  |  | SHELL | 
| 429 |  |  |  |  |  |  | TERM | 
| 430 |  |  |  |  |  |  | TEMP | 
| 431 |  |  |  |  |  |  | TMPDIR | 
| 432 |  |  |  |  |  |  | ); | 
| 433 |  |  |  |  |  |  |  | 
| 434 | 2 |  |  |  |  | 6 | my %env_found = (); | 
| 435 | 2 |  |  |  |  | 6 | foreach my $var ( @env_vars ) { | 
| 436 | 44 | 100 |  |  |  | 68 | if ( $var =~ m{^/(.+)/$} ) { | 
| 437 | 8 |  |  |  |  | 15 | my $re = $1; | 
| 438 | 8 |  |  |  |  | 31 | foreach my $found ( grep { /$re/ } keys %ENV ) { | 
|  | 176 |  |  |  |  | 234 |  | 
| 439 | 18 | 50 |  |  |  | 46 | $env_found{$found} = $ENV{$found} if exists $ENV{$found}; | 
| 440 |  |  |  |  |  |  | } | 
| 441 |  |  |  |  |  |  | } | 
| 442 |  |  |  |  |  |  | else { | 
| 443 | 36 | 100 |  |  |  | 57 | $env_found{$var} = $ENV{$var} if exists $ENV{$var}; | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  |  | 
| 447 | 2 |  |  |  |  | 10 | return \%env_found; | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | sub _get_special_vars { | 
| 451 | 2 |  |  | 2 |  | 42 | my %special_vars = ( | 
| 452 |  |  |  |  |  |  | EXECUTABLE_NAME => $^X, | 
| 453 |  |  |  |  |  |  | UID             => $<, | 
| 454 |  |  |  |  |  |  | EUID            => $>, | 
| 455 |  |  |  |  |  |  | GID             => $(, | 
| 456 |  |  |  |  |  |  | EGID            => $), | 
| 457 |  |  |  |  |  |  | ); | 
| 458 |  |  |  |  |  |  |  | 
| 459 | 2 | 50 | 33 |  |  | 11 | if ( $^O eq 'MSWin32' && eval 'require Win32' ) { ## no critic | 
| 460 | 0 |  |  |  |  | 0 | $special_vars{'Win32::GetOSName'}    = Win32::GetOSName(); | 
| 461 | 0 |  |  |  |  | 0 | $special_vars{'Win32::GetOSVersion'} = join( ', ', Win32::GetOSVersion() ); | 
| 462 | 0 |  |  |  |  | 0 | $special_vars{'Win32::FsType'}       = Win32::FsType(); | 
| 463 | 0 |  |  |  |  | 0 | $special_vars{'Win32::IsAdminUser'}  = Win32::IsAdminUser(); | 
| 464 |  |  |  |  |  |  | } | 
| 465 | 2 |  |  |  |  | 10 | return \%special_vars; | 
| 466 |  |  |  |  |  |  | } | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | sub _get_prereqs { | 
| 469 | 0 |  |  | 0 |  | 0 | my ($self, $dir) = @_; | 
| 470 | 0 |  |  |  |  | 0 | my $meta; | 
| 471 |  |  |  |  |  |  |  | 
| 472 | 0 |  |  |  |  | 0 | foreach my $meta_file ( qw( META.json META.yml META.yaml ) ) { | 
| 473 | 0 |  |  |  |  | 0 | my $meta_path = File::Spec->catfile( $dir, $meta_file ); | 
| 474 | 0 | 0 |  |  |  | 0 | if (-e $meta_path) { | 
| 475 | 0 |  |  |  |  | 0 | $meta = eval { Parse::CPAN::Meta->load_file( $dir ) }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 476 | 0 | 0 |  |  |  | 0 | last if $meta; | 
| 477 |  |  |  |  |  |  | } | 
| 478 |  |  |  |  |  |  | } | 
| 479 |  |  |  |  |  |  |  | 
| 480 | 0 | 0 | 0 |  |  | 0 | if ($meta and $meta->{'meta-spec'}{version} < 2) { | 
| 481 | 0 |  |  |  |  | 0 | $self->{_meta}{prereqs} = $meta->{prereqs}; | 
| 482 |  |  |  |  |  |  | } | 
| 483 | 0 |  |  |  |  | 0 | return; | 
| 484 |  |  |  |  |  |  | } | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | sub _max_length { | 
| 487 | 6 |  |  | 6 |  | 24 | my ($first, @rest) = @_; | 
| 488 | 6 |  |  |  |  | 9 | my $max = length $first; | 
| 489 | 6 |  |  |  |  | 15 | for my $term ( @rest ) { | 
| 490 | 82 | 100 |  |  |  | 163 | $max = length $term if length $term > $max; | 
| 491 |  |  |  |  |  |  | } | 
| 492 | 6 |  |  |  |  | 12 | return $max; | 
| 493 |  |  |  |  |  |  | } | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 496 |  |  |  |  |  |  | # _temp_filename -- stand-in for File::Temp for backwards compatibility | 
| 497 |  |  |  |  |  |  | # | 
| 498 |  |  |  |  |  |  | # takes an optional prefix, adds 8 random chars and returns | 
| 499 |  |  |  |  |  |  | # an absolute pathname | 
| 500 |  |  |  |  |  |  | # | 
| 501 |  |  |  |  |  |  | # NOTE -- manual unlink required | 
| 502 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | sub _temp_filename { | 
| 505 | 6 |  |  | 6 |  | 11 | my ($prefix) = @_; | 
| 506 |  |  |  |  |  |  | # @CHARS from File::Temp | 
| 507 | 6 |  |  |  |  | 88 | my @CHARS = (qw/ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | 
| 508 |  |  |  |  |  |  | a b c d e f g h i j k l m n o p q r s t u v w x y z | 
| 509 |  |  |  |  |  |  | 0 1 2 3 4 5 6 7 8 9 _ | 
| 510 |  |  |  |  |  |  | /); | 
| 511 |  |  |  |  |  |  |  | 
| 512 | 6 | 50 |  |  |  | 20 | $prefix = q{} unless defined $prefix; | 
| 513 | 6 |  |  |  |  | 99 | $prefix .= $CHARS[ int( rand(@CHARS) ) ] for 0 .. 7; | 
| 514 | 6 |  |  |  |  | 216 | return File::Spec->catfile(File::Spec->tmpdir(), $prefix); | 
| 515 |  |  |  |  |  |  | } | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 519 |  |  |  |  |  |  | # _version_finder | 
| 520 |  |  |  |  |  |  | # | 
| 521 |  |  |  |  |  |  | # module => version pairs | 
| 522 |  |  |  |  |  |  | # | 
| 523 |  |  |  |  |  |  | # This is done via an external program to show installed versions exactly | 
| 524 |  |  |  |  |  |  | # the way they would be found when test programs are run.  This means that | 
| 525 |  |  |  |  |  |  | # any updates to PERL5LIB will be reflected in the results. | 
| 526 |  |  |  |  |  |  | # | 
| 527 |  |  |  |  |  |  | # File-finding logic taken from CPAN::Module::inst_file().  Logic to | 
| 528 |  |  |  |  |  |  | # handle newer Module::Build prereq syntax is taken from | 
| 529 |  |  |  |  |  |  | # CPAN::Distribution::unsat_prereq() | 
| 530 |  |  |  |  |  |  | # | 
| 531 |  |  |  |  |  |  | #--------------------------------------------------------------------------# | 
| 532 |  |  |  |  |  |  | my $version_finder = $INC{'CPAN/Testers/Common/Client/PrereqCheck.pm'}; | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | sub _version_finder { | 
| 535 | 6 |  |  | 6 |  | 63 | my %prereqs = @_; | 
| 536 |  |  |  |  |  |  |  | 
| 537 | 6 |  |  |  |  | 81 | my $perl = Probe::Perl->find_perl_interpreter(); | 
| 538 | 6 |  |  |  |  | 135 | my @prereq_results; | 
| 539 |  |  |  |  |  |  |  | 
| 540 | 6 |  |  |  |  | 21 | my $prereq_input = _temp_filename( 'CTCC-' ); | 
| 541 | 6 | 50 |  |  |  | 698 | open my $fh, '>', $prereq_input | 
| 542 |  |  |  |  |  |  | or die "Could not create temporary '$prereq_input' for prereq analysis: $!"; | 
| 543 | 6 |  |  |  |  | 16 | print {$fh} map { "$_ $prereqs{$_}\n" } keys %prereqs; | 
|  | 6 |  |  |  |  | 26 |  | 
|  | 51 |  |  |  |  | 127 |  | 
| 544 | 6 |  |  |  |  | 231 | close $fh; | 
| 545 |  |  |  |  |  |  |  | 
| 546 | 6 |  |  | 6 |  | 348 | my ( $prereq_result, $error, $exit ) = capture { system( $perl, $version_finder, $prereq_input ) }; | 
|  | 6 |  |  |  |  | 1317318 |  | 
| 547 | 6 |  |  |  |  | 4956 | unlink $prereq_input; | 
| 548 |  |  |  |  |  |  |  | 
| 549 | 6 | 50 |  |  |  | 37 | if ( length $error ) { | 
| 550 | 0 |  |  |  |  | 0 | print STDERR $error; | 
| 551 |  |  |  |  |  |  | } | 
| 552 | 6 | 50 |  |  |  | 24 | if ( not length $prereq_result) { | 
| 553 | 0 |  |  |  |  | 0 | warn "Got no output from CPAN::Testers::Common::Client::PrereqCheck"; | 
| 554 |  |  |  |  |  |  | } | 
| 555 | 6 |  |  |  |  | 10 | my %result; | 
| 556 | 6 |  |  |  |  | 43 | for my $line ( split "\n", $prereq_result ) { | 
| 557 | 51 | 50 |  |  |  | 74 | next unless length $line; | 
| 558 | 51 |  |  |  |  | 113 | my ($mod, $met, $have) = split " ", $line; | 
| 559 | 51 | 50 | 33 |  |  | 246 | unless ( defined($mod) && defined($met) && defined($have) ) { | 
|  |  |  | 33 |  |  |  |  | 
| 560 | 0 |  |  |  |  | 0 | warn "Error parsing output from CPAN::Testers::Common::Client::PrereqCheck:\n$line"; | 
| 561 | 0 |  |  |  |  | 0 | next; | 
| 562 |  |  |  |  |  |  | } | 
| 563 | 51 |  |  |  |  | 162 | $result{$mod}{have} = $have; | 
| 564 | 51 |  |  |  |  | 77 | $result{$mod}{met} = $met; | 
| 565 |  |  |  |  |  |  | } | 
| 566 | 6 |  |  |  |  | 89 | return \%result; | 
| 567 |  |  |  |  |  |  | } | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | sub _create_email { | 
| 571 | 2 |  |  | 2 |  | 5 | my $self = shift; | 
| 572 |  |  |  |  |  |  |  | 
| 573 | 2 |  |  |  |  | 19 | my %intro_para = ( | 
| 574 |  |  |  |  |  |  | 'pass' => <<'HERE', | 
| 575 |  |  |  |  |  |  | Thank you for uploading your work to CPAN.  Congratulations! | 
| 576 |  |  |  |  |  |  | All tests were successful. | 
| 577 |  |  |  |  |  |  | HERE | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | 'fail' => <<'HERE', | 
| 580 |  |  |  |  |  |  | Thank you for uploading your work to CPAN.  However, there was a problem | 
| 581 |  |  |  |  |  |  | testing your distribution. | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | If you think this report is invalid, please consult the CPAN Testers Wiki | 
| 584 |  |  |  |  |  |  | for suggestions on how to avoid getting FAIL reports for missing library | 
| 585 |  |  |  |  |  |  | or binary dependencies, unsupported operating systems, and so on: | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | http://wiki.cpantesters.org/wiki/CPANAuthorNotes | 
| 588 |  |  |  |  |  |  | HERE | 
| 589 |  |  |  |  |  |  |  | 
| 590 |  |  |  |  |  |  | 'unknown' => <<'HERE', | 
| 591 |  |  |  |  |  |  | Thank you for uploading your work to CPAN.  However, attempting to | 
| 592 |  |  |  |  |  |  | test your distribution gave an inconclusive result. | 
| 593 |  |  |  |  |  |  |  | 
| 594 |  |  |  |  |  |  | This could be because your distribution had an error during the make/build | 
| 595 |  |  |  |  |  |  | stage, did not define tests, tests could not be found, because your tests were | 
| 596 |  |  |  |  |  |  | interrupted before they finished, or because the results of the tests could not | 
| 597 |  |  |  |  |  |  | be parsed.  You may wish to consult the CPAN Testers Wiki: | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | http://wiki.cpantesters.org/wiki/CPANAuthorNotes | 
| 600 |  |  |  |  |  |  | HERE | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | 'na' => <<'HERE', | 
| 603 |  |  |  |  |  |  | Thank you for uploading your work to CPAN.  While attempting to build or test | 
| 604 |  |  |  |  |  |  | this distribution, the distribution signaled that support is not available | 
| 605 |  |  |  |  |  |  | either for this operating system or this version of Perl.  Nevertheless, any | 
| 606 |  |  |  |  |  |  | diagnostic output produced is provided below for reference.  If this is not | 
| 607 |  |  |  |  |  |  | what you expect, you may wish to consult the CPAN Testers Wiki: | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | http://wiki.cpantesters.org/wiki/CPANAuthorNotes | 
| 610 |  |  |  |  |  |  | HERE | 
| 611 |  |  |  |  |  |  |  | 
| 612 |  |  |  |  |  |  | ); | 
| 613 |  |  |  |  |  |  |  | 
| 614 | 2 |  |  |  |  | 7 | my $metabase_data = $self->metabase_data; | 
| 615 |  |  |  |  |  |  | my %data = ( | 
| 616 |  |  |  |  |  |  | author             => $self->author, | 
| 617 |  |  |  |  |  |  | dist_name          => $self->distname, | 
| 618 |  |  |  |  |  |  | perl_version       => $metabase_data->{TestSummary}{perl_version}, | 
| 619 |  |  |  |  |  |  | via                => $self->via, | 
| 620 |  |  |  |  |  |  | grade              => $self->grade, | 
| 621 |  |  |  |  |  |  | comment            => $self->comments, | 
| 622 |  |  |  |  |  |  | command            => $self->command, | 
| 623 |  |  |  |  |  |  | test_log           => $metabase_data->{TestOutput}{test} || '', | 
| 624 |  |  |  |  |  |  | prereq_pm          => _format_prereq_report( $metabase_data->{Prereqs} ), | 
| 625 |  |  |  |  |  |  | env_vars           => _format_vars_report( $metabase_data->{TestEnvironment}{environment_vars} ), | 
| 626 |  |  |  |  |  |  | special_vars       => _format_vars_report( $metabase_data->{TestEnvironment}{special_vars} ), | 
| 627 | 2 |  | 100 |  |  | 8 | toolchain_versions => _format_toolchain_report( $metabase_data->{InstalledModules}{toolchain} ), | 
| 628 |  |  |  |  |  |  | ); | 
| 629 |  |  |  |  |  |  |  | 
| 630 | 2 | 50 |  |  |  | 9 | if ( length $data{test_log} > MAX_OUTPUT_LENGTH ) { | 
| 631 | 0 |  |  |  |  | 0 | my $max_k = int(MAX_OUTPUT_LENGTH/1000) . "K"; | 
| 632 | 0 |  |  |  |  | 0 | $data{test_log} = substr( $data{test_log}, 0, MAX_OUTPUT_LENGTH) | 
| 633 |  |  |  |  |  |  | . "\n\n[Output truncated after $max_k]\n\n"; | 
| 634 |  |  |  |  |  |  | } | 
| 635 |  |  |  |  |  |  |  | 
| 636 | 2 |  |  |  |  | 55 | return <<"EOEMAIL"; | 
| 637 |  |  |  |  |  |  | Dear $data{author}, | 
| 638 |  |  |  |  |  |  |  | 
| 639 |  |  |  |  |  |  | This is a computer-generated report for $data{dist_name} | 
| 640 |  |  |  |  |  |  | on perl $data{perl_version}, created by $data{via}. | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | $intro_para{ $data{grade} } | 
| 643 |  |  |  |  |  |  | Sections of this report: | 
| 644 |  |  |  |  |  |  |  | 
| 645 |  |  |  |  |  |  | * Tester comments | 
| 646 |  |  |  |  |  |  | * Program output | 
| 647 |  |  |  |  |  |  | * Prerequisites | 
| 648 |  |  |  |  |  |  | * Environment and other context | 
| 649 |  |  |  |  |  |  |  | 
| 650 |  |  |  |  |  |  | ------------------------------ | 
| 651 |  |  |  |  |  |  | TESTER COMMENTS | 
| 652 |  |  |  |  |  |  | ------------------------------ | 
| 653 |  |  |  |  |  |  |  | 
| 654 |  |  |  |  |  |  | Additional comments from tester: | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | $data{comment} | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | ------------------------------ | 
| 659 |  |  |  |  |  |  | PROGRAM OUTPUT | 
| 660 |  |  |  |  |  |  | ------------------------------ | 
| 661 |  |  |  |  |  |  |  | 
| 662 |  |  |  |  |  |  | Output from '$data{command}': | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | $data{test_log} | 
| 665 |  |  |  |  |  |  | ------------------------------ | 
| 666 |  |  |  |  |  |  | PREREQUISITES | 
| 667 |  |  |  |  |  |  | ------------------------------ | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | Prerequisite modules loaded: | 
| 670 |  |  |  |  |  |  |  | 
| 671 |  |  |  |  |  |  | $data{prereq_pm} | 
| 672 |  |  |  |  |  |  | ------------------------------ | 
| 673 |  |  |  |  |  |  | ENVIRONMENT AND OTHER CONTEXT | 
| 674 |  |  |  |  |  |  | ------------------------------ | 
| 675 |  |  |  |  |  |  |  | 
| 676 |  |  |  |  |  |  | Environment variables: | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | $data{env_vars} | 
| 679 |  |  |  |  |  |  | Perl special variables (and OS-specific diagnostics, for MSWin32): | 
| 680 |  |  |  |  |  |  |  | 
| 681 |  |  |  |  |  |  | $data{special_vars} | 
| 682 |  |  |  |  |  |  | Perl module toolchain versions installed: | 
| 683 |  |  |  |  |  |  |  | 
| 684 |  |  |  |  |  |  | $data{toolchain_versions} | 
| 685 |  |  |  |  |  |  | EOEMAIL | 
| 686 |  |  |  |  |  |  |  | 
| 687 |  |  |  |  |  |  | } | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  | 42; | 
| 690 |  |  |  |  |  |  | __END__ |