File Coverage

blib/lib/App/SmokeBrew/Tools.pm
Criterion Covered Total %
statement 131 138 94.9
branch 66 90 73.3
condition 25 36 69.4
subroutine 23 23 100.0
pod 7 7 100.0
total 252 294 85.7


line stmt bran cond sub pod time code
1             package App::SmokeBrew::Tools;
2             $App::SmokeBrew::Tools::VERSION = '1.00';
3             #ABSTRACT: Various utility functions for smokebrew
4              
5 4     4   97194 use strict;
  4         18  
  4         116  
6 4     4   19 use warnings;
  4         17  
  4         95  
7 4     4   2436 use Archive::Extract;
  4         677192  
  4         180  
8 4     4   2529 use File::Fetch;
  4         65157  
  4         131  
9 4     4   30 use File::Spec;
  4         7  
  4         86  
10 4     4   21 use List::Util qw[uniq];
  4         8  
  4         420  
11 4     4   11669 use Module::CoreList;
  4         418745  
  4         64  
12 4     4   5084 use Perl::Version;
  4         8098  
  4         157  
13 4     4   2686 use URI;
  4         18389  
  4         5885  
14              
15             my @mirrors = (
16             'http://www.cpan.org/',
17             'http://cpan.cpantesters.org/',
18             'ftp://ftp.funet.fi/pub/CPAN/',
19             );
20              
21             sub fetch {
22 1     1 1 41216 my $fetch = shift;
23 1 50       21 $fetch = shift if $fetch->isa(__PACKAGE__);
24 1 50       6 return unless $fetch;
25 1   50     7 my $loc = shift || return;
26 1         4 my $mirrors = shift;
27             $mirrors = \@mirrors unless
28 1 0 33     8 $mirrors and ref $mirrors eq 'ARRAY' and scalar @{ $mirrors };
  0   50     0  
29 1         136 $loc = File::Spec->rel2abs($loc);
30 1         19 my $stat;
31 1         3 foreach my $mirror ( @{ $mirrors } ) {
  1         6  
32 1 50       24 my $uri = URI->new( ( $mirror->isa('URI') ? $mirror->as_string : $mirror ) );
33 1         11560 $uri->path_segments( ( grep { $_ } $uri->path_segments ), split(m!/!, $fetch) );
  2         106  
34 1         89 my $ff = File::Fetch->new( uri => $uri->as_string );
35 1         6268 $stat = $ff->fetch( to => $loc );
36 1 50       174965 last if $stat;
37             }
38 1         54 return $stat;
39             }
40              
41             sub extract {
42 1     1 1 1682 my $file = shift;
43 1 50       38 $file = shift if $file->isa(__PACKAGE__);
44 1 50       6 return unless $file;
45 1   50     5 my $loc = shift || return;
46 1         38 $loc = File::Spec->rel2abs($loc);
47 1         9 local $Archive::Extract::PREFER_BIN=1;
48 1         24 my $ae = Archive::Extract->new( archive => $file );
49 1 50       471 return unless $ae;
50 1 50       13 return unless $ae->extract( to => $loc );
51 1         55537 return $ae->extract_path();
52             }
53              
54             sub smokebrew_dir {
55             return $ENV{PERL5_SMOKEBREW_DIR}
56             if exists $ENV{PERL5_SMOKEBREW_DIR}
57 1 50 33 1 1 626 && defined $ENV{PERL5_SMOKEBREW_DIR};
58              
59 0         0 my @os_home_envs = qw( APPDATA HOME USERPROFILE WINDIR SYS$LOGIN );
60              
61 0         0 for my $env ( @os_home_envs ) {
62 0 0       0 next unless exists $ENV{ $env };
63 0 0 0     0 next unless defined $ENV{ $env } && length $ENV{ $env };
64 0 0       0 return $ENV{ $env } if -d $ENV{ $env };
65             }
66              
67 0         0 return cwd();
68             }
69              
70             sub perls {
71 8     8 1 46384 my $type = shift;
72 8 100       84 $type = shift if $type->isa(__PACKAGE__);
73 8 100 100     75 if ( $type and $type eq 'latest' ) {
74 1         2 my %perls;
75 1         19 foreach my $pv ( map { Perl::Version->new($_) } perls('recent') ) {
  37         2934  
76 37         752 my $vers = $pv->version;
77 37 100       1070 unless ( exists $perls{$vers} ) {
78 10         37 $perls{$vers} = $pv;
79 10         18 next;
80             }
81 27 50       66 $perls{$vers} = $pv if $pv > $perls{$vers};
82             }
83 10         18 return map { _format_version($_) } map { $perls{$_} }
  10         39  
84 1         305 sort { $perls{$a} <=> $perls{$b} } keys %perls;
  21         467  
85             ;
86             }
87 7 100 100     84 unless ( $type and $type =~ /^(rel|dev|recent|modern)$/i ) {
88 2 100       25 $type =~ s/[^\d\.]+//g if $type;
89             }
90             return
91             uniq
92 486         941 map { _format_version($_) }
93             grep {
94 1288 100 100     31439 if ( $type and $type eq 'rel' ) {
    100 100        
    100 100        
    100 100        
    100          
95 184 100       305 _is_rel($_) and !_is_ancient($_);
96             }
97             elsif ( $type and $type eq 'dev' ) {
98 184 100       295 _is_dev($_) and !_is_ancient($_);
99             }
100             elsif ( $type and $type eq 'recent' ) {
101 368         611 _is_recent($_);
102             }
103             elsif ( $type and $type eq 'modern' ) {
104 184         333 _is_modern($_);
105             }
106             elsif ( $type ) {
107 184         368 $_->normal =~ /\Q$type\E$/;
108             }
109             else {
110 184 100 66     301 _is_dev($_) or _is_rel($_) and !_is_ancient($_);
111             }
112             }
113 1288         105818 map { Perl::Version->new($_) }
114 7 100       672 map { $_ >= 5.006 ? sprintf('%.6f', $_) : $_ }
  1288         4443  
115             sort keys %Module::CoreList::released;
116             }
117              
118             sub _has_quadmath {
119 2     2   185 my $pv = shift;
120 2 100       8 return 1 if $pv->numify >= 5.021004;
121 1         32 return 0;
122             }
123              
124             sub _is_dev {
125 892     892   1392 my $pv = shift;
126 892 100       1266 return 0 if _is_ancient($pv);
127 872         1719 return $pv->version % 2;
128             }
129              
130             sub _is_rel {
131 254     254   1988 my $pv = shift;
132 254 100       408 return 0 if _is_ancient($pv);
133 234         479 return !( $pv->version % 2 );
134             }
135              
136             sub _is_recent {
137 368     368   492 my $pv = shift;
138 368 100       559 return 0 if _is_ancient($pv);
139 348 100       573 return 0 if _is_dev($pv);
140 120 100       3454 return 1 if $pv->numify >= 5.008009;
141 28         701 return 0;
142             }
143              
144             sub _is_modern {
145 184     184   221 my $pv = shift;
146 184 100       268 return 0 if _is_ancient($pv);
147 174 100       276 return 0 if _is_dev($pv);
148 60 100       1711 return 1 if $pv->numify >= 5.010000;
149 15         385 return 0;
150             }
151              
152             sub _is_ancient {
153 1932     1932   8786 my $pv = shift;
154 1932         3494 ( my $numify = $pv->numify ) =~ s/_//g;
155 1932 100       48380 return 1 if $numify < 5.006;
156 1862         3848 return 0;
157             }
158              
159             sub _format_version {
160 496     496   640 my $pv = shift;
161 496         917 my $numify = $pv->numify;
162 496         11524 $numify =~ s/_//g;
163 496 50       1257 return $pv if $numify < 5.006;
164 496         972 my $normal = $pv->normal();
165 496         11948 $normal =~ s/^v//g;
166 496         1676 return $normal;
167             }
168              
169             sub perl_version {
170 2     2 1 310 my $vers = shift;
171 2 50       3 $vers = shift if eval { $vers->isa(__PACKAGE__) };
  2         13  
172 2         8 my $version = Perl::Version->new( $vers );
173 2         191 ( my $numify = $version->numify ) =~ s/_//g;
174 2 100       70 my $pv = 'perl'.( $numify < 5.006 ? $version->numify : $version->normal );
175 2         56 $pv =~ s/perlv/perl-/g;
176 2         16 return $pv;
177             }
178              
179             sub devel_perl {
180 2     2 1 2167 my $perl = shift;
181 2 50       5 $perl = shift if eval { $perl->isa(__PACKAGE__) };
  2         14  
182 2 50       8 return unless $perl;
183 2         7 return _is_dev( Perl::Version->new( $perl ) );
184             }
185              
186             sub can_quadmath {
187 2     2 1 332 my $perl = shift;
188 2 50       4 $perl = shift if eval { $perl->isa(__PACKAGE__) };
  2         12  
189 2 50       8 return unless $perl;
190 2         7 return _has_quadmath( Perl::Version->new( $perl ) );
191             }
192              
193             qq[Smoke tools look what's inside of you];
194              
195             __END__
196              
197             =pod
198              
199             =encoding UTF-8
200              
201             =head1 NAME
202              
203             App::SmokeBrew::Tools - Various utility functions for smokebrew
204              
205             =head1 VERSION
206              
207             version 1.00
208              
209             =head1 SYNOPSIS
210              
211             use strict;
212             use warnings;
213             use App::SmokeBrew::Tools;
214              
215             # Fetch a perl source tarball
216             my $filename = App::SmokeBrew::Tools->fetch( $path_to_fetch, $where_to_fetch_to );
217              
218             # Extract a tarball
219             my $extracted_loc = App::SmokeBrew::Tools->extract( $tarball, $where_to_extract_to );
220              
221             # Find the smokebrew directory
222             my $dir = App::SmokeBrew::Tools->smokebrew_dir();
223              
224             # Obtain a list of perl versions
225             my @perls = App::SmokeBrew::Tools->perls(); # All perls >= 5.006
226              
227             my @stables = App::SmokeBrew::Tools->perls( 'rel' );
228              
229             my @devs = App::SmokeBrew::Tools->perls( 'dev' );
230              
231             my @recents = App::SmokeBrew::Tools->perls( 'recent' );
232              
233             my $perl = '5.13.0';
234              
235             if ( App::SmokeBrew::Tools->devel_perl( $perl ) ) {
236             print "perl ($perl) is a development perl\n";
237             }
238              
239             =head1 DESCRIPTION
240              
241             App::SmokeBrew::Tools provides a number of utility functions for L<smokebrew>.
242              
243             =head1 FUNCTIONS
244              
245             =over
246              
247             =item C<fetch>
248              
249             Requires two mandatory parameters and one optional. The first two parameters are the path to
250             fetch from a CPAN mirror and the file system path where you want the file fetched to.
251             The third, optional parameter, is an arrayref of CPAN mirrors that you wish the file to fetched from.
252              
253             Returns the path to the fetched file on success, false otherwise.
254              
255             This function is a wrapper around L<File::Fetch>.
256              
257             =item C<extract>
258              
259             Requires two mandatory parameters, the path to a file that you wish to be extracted and the file system
260             path of where you wish the file to be extracted to. Returns the path to the extracted file on success,
261             false otherwise.
262              
263             This function is a wrapper around L<Archive::Extract>.
264              
265             =item C<smokebrew_dir>
266              
267             Returns the path to where the C<.smokebrew> directory may be found.
268              
269             =item C<perls>
270              
271             Returns a list of perl versions. Without a parameter returns all perl releases >= 5.006
272              
273             Specifying C<rel> as the parameter will return all C<stable> perl releases >= 5.006
274              
275             Specifying C<dev> as the parameter will return only the C<development> perl releases >= 5.006
276              
277             Specifying C<recent> as the parameter will return only the C<stable> perl releases >= 5.008009
278              
279             =item C<devel_perl>
280              
281             Takes one parameter a perl version to check.
282              
283             Returns true if given perl is a development perl.
284              
285             =item C<can_quadmath>
286              
287             Takes one parameter a perl version to check.
288              
289             Returns true if given perl is able to be built with C<quadmath>.
290              
291             =item C<perl_version>
292              
293             Takes one parameter a perl version.
294              
295             Returns the version with the C<perl-> prefix.
296              
297             =back
298              
299             =head1 SEE ALSO
300              
301             L<smokebrew>
302              
303             L<Perl::Version>
304              
305             L<File::Fetch>
306              
307             L<Archive::Extract>
308              
309             =head1 AUTHOR
310              
311             Chris Williams <chris@bingosnet.co.uk>
312              
313             =head1 COPYRIGHT AND LICENSE
314              
315             This software is copyright (c) 2020 by Chris Williams.
316              
317             This is free software; you can redistribute it and/or modify it under
318             the same terms as the Perl 5 programming language system itself.
319              
320             =cut