File Coverage

blib/lib/App/SmokeBrew/Plugin/CPANPLUS/YACSmoke.pm
Criterion Covered Total %
statement 55 134 41.0
branch 2 38 5.2
condition 0 2 0.0
subroutine 15 20 75.0
pod 1 1 100.0
total 73 195 37.4


line stmt bran cond sub pod time code
1             package App::SmokeBrew::Plugin::CPANPLUS::YACSmoke;
2             $App::SmokeBrew::Plugin::CPANPLUS::YACSmoke::VERSION = '1.00';
3             #ABSTRACT: A smokebrew plugin for CPANPLUS::YACSmoke based smokers
4              
5 1     1   779 use strict;
  1         2  
  1         29  
6 1     1   6 use warnings;
  1         2  
  1         25  
7 1     1   455 use App::SmokeBrew::Tools;
  1         27  
  1         38  
8 1     1   10 use File::Fetch;
  1         2  
  1         25  
9 1     1   6 use File::Spec;
  1         3  
  1         52  
10 1     1   6 use Cwd qw[realpath];
  1         3  
  1         74  
11 1     1   6 use File::Path qw[rmtree mkpath];
  1         2  
  1         50  
12 1     1   599 use File::pushd qw[pushd];
  1         1285  
  1         67  
13 1     1   8 use IPC::Cmd qw[run can_run];
  1         2  
  1         53  
14 1     1   476 use Log::Message::Simple qw[msg error];
  1         9195  
  1         83  
15              
16 1     1   719 use Moose;
  1         522863  
  1         9  
17              
18             with 'App::SmokeBrew::PerlVersion', 'App::SmokeBrew::Plugin';
19              
20             has '_cpanplus' => (
21             is => 'ro',
22             isa => 'Str',
23             init_arg => undef,
24             lazy_build => 1,
25             );
26              
27             sub _build__cpanplus {
28 1     1   3 my $self = shift;
29 1         31 $self->builddir->mkpath;
30 1         86 my $default = 'B/BI/BINGOS/CPANPLUS-0.9168.tar.gz';
31 1         2 my $path;
32 1         27 my $ff = File::Fetch->new( uri => 'http://cpanidx.org/cpanidx/yaml/mod/CPANPLUS' );
33 1         5464 my $stat = $ff->fetch( to => $self->builddir->absolute );
34 1         113015 require Parse::CPAN::Meta;
35 1         1657 my ($doc) = eval { Parse::CPAN::Meta::LoadFile( $stat ) };
  1         13  
36 1 50       6112 return $default unless $doc;
37 1         6 $path = $doc->[0]->{dist_file};
38 1         69 unlink( $stat );
39 1 50       92 return $path if $path;
40 0           return $default;
41             }
42              
43             sub configure {
44 0     0 1   my $self = shift;
45 0           $self->builddir->mkpath;
46 0           msg("Fetching '" . $self->_cpanplus . "'", $self->verbose);
47 0           my $loc = 'authors/id/' . $self->_cpanplus;
48 0           my $fetch = App::SmokeBrew::Tools->fetch( $loc, $self->builddir->absolute );
49 0 0         if ( $fetch ) {
50 0           msg("Fetched to '$fetch'", $self->verbose );
51             }
52             else {
53 0           error("Could not fetch '$loc'", $self->verbose );
54 0           return;
55             }
56 0 0         return unless $fetch;
57 0           msg("Extracting '$fetch'", $self->verbose);
58 0           my $extract = App::SmokeBrew::Tools->extract( $fetch, $self->builddir->absolute );
59 0 0         if ( $extract ) {
60 0           msg("Extracted to '$extract'", $self->verbose );
61             }
62             else {
63 0           error("Could not extract '$fetch'");
64 0           return;
65             }
66 0 0         return unless $extract;
67 0 0         unlink( $fetch ) unless $self->noclean();
68 0           my $perl = can_run( $self->perl_exe->absolute );
69 0 0         unless ( $perl ) {
70 0           error("Could not execute '" . $self->perl_exe->absolute . "'", $self->verbose );
71 0           return;
72             }
73             {
74 0           my $CWD = pushd( $extract );
  0            
75 1     1   10150 use IO::Handle;
  1         3  
  1         263  
76 0 0         open my $boxed, '>', 'bin/boxer' or die "$!\n";
77 0           $boxed->autoflush(1);
78 0           print $boxed $self->_boxed;
79 0           close $boxed;
80 0           my $cmd = [ $perl, 'bin/boxer' ];
81 0           local $ENV{PERL_MM_USE_DEFAULT} = 1;
82 0 0         return unless scalar run( command => $cmd, verbose => 1 );
83             }
84 0 0         rmtree( $extract ) unless $self->noclean();
85 0           my $conf = File::Spec->catdir( $self->prefix->absolute, 'conf', $self->perl_version );
86 0           mkpath( $conf );
87             {
88 0           local $ENV{APPDATA} = $conf;
  0            
89 0           my $cpconf = $self->_cpconf();
90 0           my $CWD = pushd( $self->builddir->absolute );
91 1     1   9 use IO::Handle;
  1         2  
  1         998  
92 0 0         open my $boxed, '>', 'cpconf.pl' or die "$!\n";
93 0           $boxed->autoflush(1);
94 0           print $boxed $cpconf;
95 0           close $boxed;
96 0           my $cmd = [ $perl, 'cpconf.pl', '--email', $self->email ];
97 0 0         push @$cmd, ( '--mx', $self->mx ) if $self->mx;
98 0 0         return unless scalar run( command => $cmd, verbose => 1 );
99 0 0         unlink( 'cpconf.pl' ) unless $self->noclean();
100             # Setup symlinks
101 0 0         if ( eval { symlink("",""); 1 } ) {
  0            
  0            
102 0           my $parent = realpath( File::Spec->catdir( $self->prefix->absolute, '..' ) );
103 0           my $authors = File::Spec->catdir( $parent, 'authors' );
104 0           my $smokeini = File::Spec->catfile( $parent, 'cpansmoke.ini' );
105 0 0         unless ( -e $smokeini ) {
106 0 0         open my $ini, '>', $smokeini or die "$!\n";
107 0           $ini->autoflush(1);
108 0           print $ini $self->_cpansmokeini;
109 0           close $ini;
110             }
111 0 0         mkpath( $authors ) unless -d $authors;
112 0           symlink( $authors, File::Spec->catdir( $conf, '.cpanplus', 'authors' ) );
113 0           symlink( $smokeini, File::Spec->catdir( $conf, '.cpanplus', 'cpansmoke.ini' ) );
114             }
115             }
116 0           return 1;
117             }
118              
119             sub _boxed {
120 0     0     my $self = shift;
121 0           return q+
122             BEGIN {
123             use strict;
124             use warnings;
125              
126             use Config;
127             use FindBin;
128             use File::Spec;
129             use File::Spec::Unix;
130              
131             use vars qw[@RUN_TIME_INC $LIB_DIR $BUNDLE_DIR $BASE $PRIV_LIB];
132             $LIB_DIR = File::Spec->catdir( $FindBin::Bin, qw[.. lib] );
133             $BUNDLE_DIR = File::Spec->catdir( $FindBin::Bin, qw[.. inc bundle] );
134              
135             my $who = getlogin || getpwuid($<) || $<;
136             $BASE = File::Spec->catfile(
137             $FindBin::Bin, '..', '.cpanplus', $who);
138             $PRIV_LIB = File::Spec->catfile( $BASE, 'lib' );
139              
140             @RUN_TIME_INC = ($PRIV_LIB, @INC);
141             unshift @INC, $LIB_DIR, $BUNDLE_DIR;
142              
143             $ENV{'PERL5LIB'} = join $Config{'path_sep'}, grep { defined }
144             $PRIV_LIB, # to find the boxed config
145             $LIB_DIR, # the CPANPLUS libs
146             $ENV{'PERL5LIB'}; # original PERL5LIB
147              
148             }
149              
150             use FindBin;
151             use File::Find qw[find];
152             use CPANPLUS::Error;
153             use CPANPLUS::Configure;
154             use CPANPLUS::Internals::Constants;
155             use CPANPLUS::Internals::Utils;
156              
157             { for my $dir ( ($BUNDLE_DIR, $LIB_DIR) ) {
158             my $base_re = quotemeta $dir;
159              
160             find( sub { my $file = $File::Find::name;
161             return unless -e $file && -f _ && -s _;
162              
163             return if $file =~ /\._/; # osx temp files
164              
165             $file =~ s/^$base_re(\W)?//;
166              
167             return if $INC{$file};
168              
169             my $unixfile = File::Spec::Unix->catfile(
170             File::Spec->splitdir( $file )
171             );
172             my $pm = join '::', File::Spec->splitdir( $file );
173             $pm =~ s/\.pm$//i or return; # not a .pm file
174              
175             #return if $pm =~ /(?:IPC::Run::)|(?:File::Spec::)/;
176              
177             eval "require $pm ; 1";
178              
179             if( $@ ) {
180             push @failures, $unixfile;
181             }
182             }, $dir );
183             }
184              
185             delete $INC{$_} for @failures;
186              
187             @INC = @RUN_TIME_INC;
188             }
189              
190              
191             my $ConfObj = CPANPLUS::Configure->new;
192             my $Config = CONFIG_BOXED;
193             my $Util = 'CPANPLUS::Internals::Utils';
194             my $ConfigFile = $ConfObj->_config_pm_to_file( $Config => $PRIV_LIB );
195              
196             { ### no base dir even, set it up
197             unless( IS_DIR->( $BASE ) ) {
198             $Util->_mkdir( dir => $BASE ) or die CPANPLUS::Error->stack_as_string;
199             }
200              
201             unless( -e $ConfigFile ) {
202             $ConfObj->set_conf( base => $BASE ); # new base dir
203             $ConfObj->set_conf( verbose => 1 ); # be verbose
204             $ConfObj->set_conf( prereqs => 1 ); # install prereqs
205             $ConfObj->set_conf( prefer_makefile => 1 ); # prefer Makefile.PL because of v5.10.0
206             $ConfObj->set_conf( enable_custom_sources => 0 ); # install prereqs
207             $ConfObj->set_conf( hosts => + . $self->_mirrors . q+ );
208             $ConfObj->set_program( sudo => undef );
209             $ConfObj->save( $Config => $PRIV_LIB ); # save the pm in that dir
210             }
211             }
212              
213             {
214             $Module::Load::Conditional::CHECK_INC_HASH = 1;
215             use CPANPLUS::Backend;
216             my $cb = CPANPLUS::Backend->new( $ConfObj );
217             my $su = $cb->selfupdate_object;
218              
219             $cb->parse_module( module => 'http://backpan.perl.org/authors/id/J/JP/JPEACOCK/version-0.82.tar.gz' )->install();
220              
221             $cb->module_tree( 'Module::Build' )->install(); # Move this here because perl-5.10.0 is icky
222              
223             $su->selfupdate( update => 'dependencies', latest => 1 );
224             $cb->module_tree( $_ )->install() for
225             qw(
226             CPANPLUS
227             File::Temp
228             Compress::Raw::Bzip2
229             Compress::Raw::Zlib
230             Compress::Zlib
231             ExtUtils::CBuilder
232             ExtUtils::ParseXS
233             ExtUtils::Manifest
234             ExtUtils::MakeMaker
235             Log::Message::Simple
236             CPANPLUS::YACSmoke
237             );
238             $_->install() for map { $su->modules_for_feature( $_ ) } qw(prefer_makefile md5 storable cpantest);
239             }
240             +;
241             }
242              
243             sub _cpconf {
244 0     0     my $self = shift;
245 0           my $cpconf = q+
246             use strict;
247             use warnings;
248             use Getopt::Long;
249             use CPANPLUS::Configure;
250              
251             my $mx;
252             my $email;
253              
254             GetOptions( 'mx=s', \$mx, 'email=s', \$email );
255              
256             my $conf = CPANPLUS::Configure->new();
257             $conf->set_conf( verbose => 1 );
258             $conf->set_conf( cpantest => 'dont_cc' );
259             $conf->set_conf( cpantest_mx => $mx ) if $mx;
260             $conf->set_conf( email => $email );
261             $conf->set_conf( makeflags => 'UNINST=1' );
262             $conf->set_conf( buildflags => 'uninst=1' );
263             $conf->set_conf( enable_custom_sources => 0 );
264             $conf->set_conf( show_startup_tip => 0 );
265             $conf->set_conf( write_install_logs => 0 );
266             $conf->set_conf( hosts => +;
267 0           $cpconf .= $self->_mirrors() . ');';
268 0           $cpconf .= q+
269             $conf->set_program( sudo => undef );
270             $conf->save();
271             exit 0;
272             +;
273 0           return $cpconf;
274             }
275              
276             sub _cpansmokeini {
277 0     0     return q+
278             [CONFIG]
279             exclude_dists=<<HERE
280             mod_perl
281             ^OpenResty
282             ^Prima-
283             ^Router-Generic-
284             ^Net-TDMA-
285             ^PLUTO-
286             HERE
287             +;
288             }
289              
290             sub _mirrors {
291 0     0     my $self = shift;
292 0           my $mirrors = q{[ };
293 0           foreach my $uri ( $self->mirrors ) {
294 0           my $scheme = $uri->scheme;
295 0           my $host = $uri->host;
296 0   0       my $path = $uri->path || '/';
297 0           $mirrors .= qq!{ scheme => '$scheme', host => '$host', path => '$path' }, !;
298             }
299 0           $mirrors .= q{ ] };
300 0           return $mirrors;
301             }
302              
303 1     1   10 no Moose;
  1         2  
  1         7  
304              
305             __PACKAGE__->meta->make_immutable;
306              
307             qq[Smokin'];
308              
309             __END__
310              
311             =pod
312              
313             =encoding UTF-8
314              
315             =head1 NAME
316              
317             App::SmokeBrew::Plugin::CPANPLUS::YACSmoke - A smokebrew plugin for CPANPLUS::YACSmoke based smokers
318              
319             =head1 VERSION
320              
321             version 1.00
322              
323             =head1 SYNOPSIS
324              
325             smokebrew --plugin App::SmokeBrew::Plugin::CPANPLUS::YACSmoke
326              
327             =head1 DESCRIPTION
328              
329             App::SmokeBrew::Plugin::CPANPLUS::YACSmoke is a L<App::SmokeBrew::Plugin> for L<smokebrew> which
330             configures the built perl installations for CPAN Testing with L<CPANPLUS::YACSmoke>.
331              
332             It will set up the L<CPANPLUS> / L<CPANPLUS::YACSmoke> base locations to be in the C<conf> directory
333             under the given C<prefix> directory with a directory for each perl version.
334              
335             =head1 METHODS
336              
337             =over
338              
339             =item C<configure>
340              
341             Called by L<smokebrew> to perform the CPAN Testing configuration.
342              
343             =back
344              
345             =head1 SEE ALSO
346              
347             L<App::SmokeBrew::Plugin>
348              
349             L<smokebrew>
350              
351             L<CPANPLUS>
352              
353             L<CPANPLUS::YACSmoke>
354              
355             =head1 AUTHOR
356              
357             Chris Williams <chris@bingosnet.co.uk>
358              
359             =head1 COPYRIGHT AND LICENSE
360              
361             This software is copyright (c) 2020 by Chris Williams.
362              
363             This is free software; you can redistribute it and/or modify it under
364             the same terms as the Perl 5 programming language system itself.
365              
366             =cut