File Coverage

blib/lib/App/MechaCPAN/Perl.pm
Criterion Covered Total %
statement 91 121 75.2
branch 18 40 45.0
condition 2 12 16.6
subroutine 9 9 100.0
pod 1 1 100.0
total 121 183 66.1


line stmt bran cond sub pod time code
1             package App::MechaCPAN::Perl;
2              
3 22     22   158 use strict;
  22         53  
  22         695  
4 22     22   124 use autodie;
  22         48  
  22         161  
5 22     22   118946 use Config;
  22         59  
  22         997  
6 22     22   14676 use File::Fetch qw//;
  22         985240  
  22         815  
7 22     22   217 use App::MechaCPAN qw/:go/;
  22         61  
  22         23050  
8              
9             our @args = (
10             'threads!',
11             'skip-tests!',
12             'skip-local!',
13             'skip-lib!',
14             'devel!',
15             );
16              
17             sub go
18             {
19 1     1 1 6 my $class = shift;
20 1         4 my $opts = shift;
21 1         6 my $src = shift;
22 1         6 my @argv = shift;
23              
24 1 50       12 if ( $^O eq 'MSWin32' )
25             {
26 0         0 info 'Cannot build perl on Win32';
27 0         0 return 0;
28             }
29              
30 1         23 my $orig_dir = &dest_dir;
31 1         11 my @orig_dir = File::Spec->splitdir("$orig_dir");
32 1         8 my $orig_len = $#orig_dir;
33 1         6 my $dest_dir = "$orig_dir/perl";
34              
35 1         11 my ( $src_tz, $version ) = _get_targz($src);
36              
37 1 50       44 if ( -e -x "$dest_dir/bin/perl" )
38             {
39 0 0       0 unless ( $opts->{is_restarted_process} )
40             {
41             # If it exists, we're probably running it by now.
42 0 0 0     0 if ( $version && $^V ne "v$version" )
43             {
44 0         0 info(
45             $version,
46             "perl has already been installed ($^V, not $version)"
47             );
48             }
49             else
50             {
51 0         0 success( $version, "perl has already been installed" );
52             }
53             }
54 0         0 return 0;
55             }
56              
57 1         6 $version = "perl $version";
58 1         12 info $version, "Fetching $version";
59              
60 1         7 my $src_dir = inflate_archive($src_tz);
61              
62 1         13 chdir $src_dir;
63              
64 1 50       173 if ( !-e 'Configure' )
65             {
66 1         115 my @files = glob('*');
67 1 50       12 if ( @files > 1 )
68             {
69 0         0 die 'Could not find perl to configure';
70             }
71 1         6 chdir $files[0];
72             }
73              
74 1         265 my $local_dir = [ @orig_dir, qw/lib perl5/ ];
75 1         16 my $lib_dir = [ @orig_dir[ 0 .. $orig_len - 1 ], qw/lib perl5/ ];
76              
77             my @otherlib = (
78             !$opts->{skip_local} ? () : $local_dir,
79 1 50 33     35 !$opts->{skip_lib} && -d $lib_dir ? $lib_dir : (),
    50          
80             );
81              
82 1         6 @otherlib = map { File::Spec->catdir(@$_) } @otherlib;
  0         0  
83              
84 1         18 my @config = (
85             q[-des],
86             qq[-Dprefix=$dest_dir],
87             q[-Accflags=-DAPPLLIB_EXP=\"] . join( ":", @otherlib ) . q[\"],
88             qq[-A'eval:scriptdir=$dest_dir/bin'],
89             );
90 1         26 my @make = ( $Config{make} );
91              
92 1 50       10 if ( $opts->{threads} )
93             {
94 0         0 push @config, '-Dusethreads';
95             }
96              
97 1 50       7 if ( $opts->{devel} )
98             {
99 0         0 push @config, '-Dusedevel';
100             }
101              
102 1         19 delete @ENV{qw(PERL5LIB PERL5OPT)};
103              
104             # Make sure no tomfoolery is happening with perl, like plenv shims
105 1         20 $ENV{PATH} = $Config{binexp} . ":$ENV{PATH}";
106              
107 1         6 eval {
108 1         370 require Devel::PatchPerl;
109 0         0 info $version, "Patching $version";
110 0         0 Devel::PatchPerl->patch_source();
111             };
112              
113 1         19 info $version, "Configuring $version";
114 1         10 run qw[sh Configure], @config;
115              
116 1         21 info $version, "Building $version";
117 1         9 run @make;
118              
119 1 50       18 if ( !$opts->{'skip-tests'} )
120             {
121 1         27 info $version, "Testing $version";
122 1         10 run @make, 'test_harness';
123             }
124              
125 1         39 info $version, "Installing $version";
126 1         10 run @make, 'install';
127              
128 1         30 success "Installed $version";
129              
130 1         14 chdir $orig_dir;
131              
132 1         18 &restart_script();
133              
134 1         165 return 0;
135             }
136              
137             my $perl5_re = qr/^ v? 5 [.] (\d{1,2}) (?: [.] (\d{1,2}) )? $/xms;
138              
139             sub _dnld_url
140             {
141 5     5   31 my $version = shift;
142 5         22 my $minor = shift;
143 5         29 my $mirror = 'http://www.cpan.org/src/5.0';
144              
145 5         81 return "$mirror/perl-5.$version.$minor.tar.bz2";
146             }
147              
148             sub _get_targz
149             {
150 2     2   443 my $src = shift;
151              
152 2         17 local $File::Fetch::WARN;
153              
154             # Attempt to find the perl version if none was given
155 2 50 33     22 if ( !defined $src && -f '.perl-version' )
156             {
157 0         0 open my $pvFH, '<', '.perl-version';
158 0         0 my $pv = do { local $/; <$pvFH> };
  0         0  
  0         0  
159              
160             #($src) = $pv =~ m[($perl5_re)]xms;
161             }
162              
163             # If there's no src, find the newest version.
164 2 50       19 if ( !defined $src )
165             {
166             # Do a terrible job of guessing what the current version is
167 22     22   12343 use Time::localtime;
  22         91869  
  22         9493  
168 0         0 my $year = localtime->year() + 1900;
169              
170             # 5.12 was released in 2010, and approximatly every May, a new even
171             # version was released
172 0 0       0 my $major = ( $year - 2010 ) * 2 + ( localtime->mon < 4 ? 10 : 12 );
173              
174             # Verify our guess
175             {
176 0         0 my $dnld = _dnld_url( $major, 0 ) . ".md5.txt";
  0         0  
177 0         0 my $ff = File::Fetch->new( uri => $dnld );
178 0         0 my $contents = '';
179 0         0 my $where = $ff->fetch( to => \$contents );
180              
181 0 0 0     0 if ( !defined $where && $major > 12 )
182             {
183 0         0 $major -= 2;
184 0         0 redo;
185             }
186             }
187 0         0 $src = "5.$major";
188             }
189              
190             # file
191              
192 2 100       69 if ( -e $src )
193             {
194 1         16 return ( $src, '' );
195             }
196              
197 1         4 my $url;
198              
199             # URL
200 1 50       7 if ( $src =~ url_re )
201             {
202 0         0 return ( $src, '' );
203             }
204              
205             # CPAN
206 1 50       15 if ( $src =~ $perl5_re )
207             {
208 1         21 my $version = $1;
209 1         5 my $minor = $2;
210              
211             # They probably want the latest if minor wasn't given
212 1 50       6 if ( !defined $minor )
213             {
214             # 11 is the highest minor version seen as of this writing
215 1         7 my @possible = ( 0 .. 15 );
216              
217 1         7 while ( @possible > 1 )
218             {
219 4         89 my $i = int( @possible / 2 );
220 4         32 $minor = $possible[$i];
221 4         32 my $dnld = _dnld_url( $version, $minor ) . ".md5.txt";
222 4         67 my $ff = File::Fetch->new( uri => $dnld );
223 4         37504 my $contents = '';
224 4         53 my $where = $ff->fetch( to => \$contents );
225              
226 4 100       374900 if ( defined $where )
227             {
228             # The version exists, which means it's higher still
229 2         70 @possible = @possible[ $i .. $#possible ];
230             }
231             else
232             {
233             # The version doesn't exit. That means higher versions don't either
234 2         462 @possible = @possible[ 0 .. $i - 1 ];
235             }
236             }
237 1         14 $minor = $possible[0];
238             }
239              
240 1         11 return ( _dnld_url( $version, $minor ), "5.$version.$minor" );
241             }
242              
243 0           die "Cannot find $src\n";
244             }
245              
246             1;
247             __END__