File Coverage

blib/lib/App/SmokeBrew/Tools.pm
Criterion Covered Total %
statement 135 142 95.0
branch 72 96 75.0
condition 36 48 75.0
subroutine 24 24 100.0
pod 7 7 100.0
total 274 317 86.4


line stmt bran cond sub pod time code
1             package App::SmokeBrew::Tools;
2             $App::SmokeBrew::Tools::VERSION = '1.06';
3             #ABSTRACT: Various utility functions for smokebrew
4              
5 8     8   307525 use strict;
  8         20  
  8         293  
6 8     8   42 use warnings;
  8         17  
  8         439  
7 8     8   7518 use Archive::Extract;
  8         1644778  
  8         507  
8 8     8   5582 use File::Fetch;
  8         197417  
  8         388  
9 8     8   105 use File::Spec;
  8         29  
  8         235  
10 8     8   47 use List::Util qw[uniq];
  8         19  
  8         899  
11 8     8   35905 use Module::CoreList;
  8         1787427  
  8         133  
12 8     8   22156 use Perl::Version;
  8         34272  
  8         433  
13 8     8   5695 use URI;
  8         57390  
  8         16536  
14              
15             my @mirrors = (
16             'http://www.cpan.org/',
17             'http://cpan.cpantesters.org/',
18             );
19              
20             sub fetch {
21 1     1 1 381697 my $fetch = shift;
22 1 50       15 $fetch = shift if $fetch->isa(__PACKAGE__);
23 1 50       5 return unless $fetch;
24 1   50     4 my $loc = shift || return;
25 1         3 my $mirrors = shift;
26             $mirrors = \@mirrors unless
27 1 0 33     6 $mirrors and ref $mirrors eq 'ARRAY' and scalar @{ $mirrors };
  0   50     0  
28 1         55 $loc = File::Spec->rel2abs($loc);
29 1         3 my $stat;
30 1         2 foreach my $mirror ( @{ $mirrors } ) {
  1         4  
31 1 50       16 my $uri = URI->new( ( $mirror->isa('URI') ? $mirror->as_string : $mirror ) );
32 1         16591 $uri->path_segments( ( grep { $_ } $uri->path_segments ), split(m!/!, $fetch) );
  2         137  
33 1         148 my $ff = File::Fetch->new( uri => $uri->as_string );
34 1         13809 $stat = $ff->fetch( to => $loc );
35 1 50       330542 last if $stat;
36             }
37 1         9 return $stat;
38             }
39              
40             sub extract {
41 1     1 1 1631 my $file = shift;
42 1 50       11 $file = shift if $file->isa(__PACKAGE__);
43 1 50       3 return unless $file;
44 1   50     3 my $loc = shift || return;
45 1         30 $loc = File::Spec->rel2abs($loc);
46 1         5 local $Archive::Extract::PREFER_BIN=1;
47 1         11 my $ae = Archive::Extract->new( archive => $file );
48 1 50       1879 return unless $ae;
49 1 50       13 return unless $ae->extract( to => $loc );
50 1         114398 return $ae->extract_path();
51             }
52              
53             sub smokebrew_dir {
54             return $ENV{PERL5_SMOKEBREW_DIR}
55             if exists $ENV{PERL5_SMOKEBREW_DIR}
56 1 50 33 1 1 701 && defined $ENV{PERL5_SMOKEBREW_DIR};
57              
58 0         0 my @os_home_envs = qw( APPDATA HOME USERPROFILE WINDIR SYS$LOGIN );
59              
60 0         0 for my $env ( @os_home_envs ) {
61 0 0       0 next unless exists $ENV{ $env };
62 0 0 0     0 next unless defined $ENV{ $env } && length $ENV{ $env };
63 0 0       0 return $ENV{ $env } if -d $ENV{ $env };
64             }
65              
66 0         0 return cwd();
67             }
68              
69             sub perls {
70 8     8 1 108230 my $type = shift;
71 8 100       67 $type = shift if $type->isa(__PACKAGE__);
72 8 100 100     71 if ( $type and $type eq 'latest' ) {
73 1         2 my %perls;
74 1         9 foreach my $pv ( map { Perl::Version->new($_) } perls('recent') ) {
  65         3971  
75 65         808 my $vers = $pv->version;
76 65 100       1174 unless ( exists $perls{$vers} ) {
77 18         43 $perls{$vers} = $pv;
78 18         24 next;
79             }
80 47 50       67 $perls{$vers} = $pv if $pv > $perls{$vers};
81             }
82 18         22 return map { _format_version($_) } map { $perls{$_} }
  18         33  
83 1         1252 sort { $perls{$a} <=> $perls{$b} } keys %perls;
  55         758  
84             ;
85             }
86 7 100 100     122 unless ( $type and $type =~ /^(rel|dev|recent|modern)$/i ) {
87 2 100       23 $type =~ s/[^\d\.]+//g if $type;
88             }
89             return
90             uniq
91 868         1213 map { _format_version($_) }
92             grep {
93 2268 100 100     41394 if ( $type and $type eq 'rel' ) {
    100 100        
    100 100        
    100 100        
    100          
94 324 100 66     621 _is_rel($_) and !_is_ancient($_) and !_skip($_);
95             }
96             elsif ( $type and $type eq 'dev' ) {
97 324 100       1038 _is_dev($_) and !_is_ancient($_);
98             }
99             elsif ( $type and $type eq 'recent' ) {
100 648 100       875 _is_recent($_) and !_skip($_);
101             }
102             elsif ( $type and $type eq 'modern' ) {
103 324 100       389 _is_modern($_) and !_skip($_);
104             }
105             elsif ( $type ) {
106 324         416 $_->normal =~ /\Q$type\E$/;
107             }
108             else {
109 324 100 66     351 _is_dev($_) or _is_rel($_) and !_is_ancient($_) and !_skip($_);
      100        
110             }
111             }
112 2268         187365 map { Perl::Version->new($_) }
113 7 100       2116 map { $_ >= 5.006 ? sprintf('%.6f', $_) : $_ }
  2268         7827  
114             sort keys %Module::CoreList::released;
115             }
116              
117             sub _has_quadmath {
118 2     2   168 my $pv = shift;
119 2 100       6 return 1 if $pv->numify >= 5.021004;
120 1         25 return 0;
121             }
122              
123             sub _is_dev {
124 1592     1592   1923 my $pv = shift;
125 1592 100       2038 return 0 if _is_ancient($pv);
126 1572         2457 return $pv->version % 2;
127             }
128              
129             sub _is_rel {
130 433     433   2505 my $pv = shift;
131 433 100       753 return 0 if _is_ancient($pv);
132 413         961 return !( $pv->version % 2 );
133             }
134              
135             sub _is_recent {
136 648     648   625 my $pv = shift;
137 648 100       764 return 0 if _is_ancient($pv);
138 628 100       768 return 0 if _is_dev($pv);
139 198 100       4130 return 1 if $pv->numify >= 5.008009;
140 28         507 return 0;
141             }
142              
143             sub _is_modern {
144 324     324   362 my $pv = shift;
145 324 100       401 return 0 if _is_ancient($pv);
146 314 100       392 return 0 if _is_dev($pv);
147 99 100       2179 return 1 if $pv->numify >= 5.010000;
148 15         257 return 0;
149             }
150              
151             sub _is_ancient {
152 3410     3410   16165 my $pv = shift;
153 3410         5477 ( my $numify = $pv->numify ) =~ s/_//g;
154 3410 100       72572 return 1 if $numify < 5.006;
155 3340         6057 return 0;
156             }
157              
158             sub _skip {
159 452     452   4829 my $pv = shift;
160 452         647 my $nv = $pv->numify;
161 452 100 100     9860 return 1 if $nv == 5.034002 || $nv == 5.036002 || $nv == 5.038001;
      100        
162 437         1111 return 0;
163             }
164              
165             sub _format_version {
166 886     886   1133 my $pv = shift;
167 886         1482 my $numify = $pv->numify;
168 886         18248 $numify =~ s/_//g;
169 886 50       2308 return $pv if $numify < 5.006;
170 886         1438 my $normal = $pv->normal();
171 886         18666 $normal =~ s/^v//g;
172 886         2591 return $normal;
173             }
174              
175             sub perl_version {
176 2     2 1 217 my $vers = shift;
177 2 50       3 $vers = shift if eval { $vers->isa(__PACKAGE__) };
  2         10  
178 2         68 my $version = Perl::Version->new( $vers );
179 2         253 ( my $numify = $version->numify ) =~ s/_//g;
180 2 100       79 my $pv = 'perl'.( $numify < 5.006 ? $version->numify : $version->normal );
181 2         43 $pv =~ s/perlv/perl-/g;
182 2         16 return $pv;
183             }
184              
185             sub devel_perl {
186 2     2 1 14000 my $perl = shift;
187 2 50       3 $perl = shift if eval { $perl->isa(__PACKAGE__) };
  2         12  
188 2 50       4 return unless $perl;
189 2         7 return _is_dev( Perl::Version->new( $perl ) );
190             }
191              
192             sub can_quadmath {
193 2     2 1 393 my $perl = shift;
194 2 50       3 $perl = shift if eval { $perl->isa(__PACKAGE__) };
  2         11  
195 2 50       4 return unless $perl;
196 2         6 return _has_quadmath( Perl::Version->new( $perl ) );
197             }
198              
199             qq[Smoke tools look what's inside of you];
200              
201             __END__
202              
203             =pod
204              
205             =encoding UTF-8
206              
207             =head1 NAME
208              
209             App::SmokeBrew::Tools - Various utility functions for smokebrew
210              
211             =head1 VERSION
212              
213             version 1.06
214              
215             =head1 SYNOPSIS
216              
217             use strict;
218             use warnings;
219             use App::SmokeBrew::Tools;
220              
221             # Fetch a perl source tarball
222             my $filename = App::SmokeBrew::Tools->fetch( $path_to_fetch, $where_to_fetch_to );
223              
224             # Extract a tarball
225             my $extracted_loc = App::SmokeBrew::Tools->extract( $tarball, $where_to_extract_to );
226              
227             # Find the smokebrew directory
228             my $dir = App::SmokeBrew::Tools->smokebrew_dir();
229              
230             # Obtain a list of perl versions
231             my @perls = App::SmokeBrew::Tools->perls(); # All perls >= 5.006
232              
233             my @stables = App::SmokeBrew::Tools->perls( 'rel' );
234              
235             my @devs = App::SmokeBrew::Tools->perls( 'dev' );
236              
237             my @recents = App::SmokeBrew::Tools->perls( 'recent' );
238              
239             my $perl = '5.13.0';
240              
241             if ( App::SmokeBrew::Tools->devel_perl( $perl ) ) {
242             print "perl ($perl) is a development perl\n";
243             }
244              
245             =head1 DESCRIPTION
246              
247             App::SmokeBrew::Tools provides a number of utility functions for L<smokebrew>.
248              
249             =head1 FUNCTIONS
250              
251             =over
252              
253             =item C<fetch>
254              
255             Requires two mandatory parameters and one optional. The first two parameters are the path to
256             fetch from a CPAN mirror and the file system path where you want the file fetched to.
257             The third, optional parameter, is an arrayref of CPAN mirrors that you wish the file to fetched from.
258              
259             Returns the path to the fetched file on success, false otherwise.
260              
261             This function is a wrapper around L<File::Fetch>.
262              
263             =item C<extract>
264              
265             Requires two mandatory parameters, the path to a file that you wish to be extracted and the file system
266             path of where you wish the file to be extracted to. Returns the path to the extracted file on success,
267             false otherwise.
268              
269             This function is a wrapper around L<Archive::Extract>.
270              
271             =item C<smokebrew_dir>
272              
273             Returns the path to where the C<.smokebrew> directory may be found.
274              
275             =item C<perls>
276              
277             Returns a list of perl versions. Without a parameter returns all perl releases >= 5.006
278              
279             Specifying C<rel> as the parameter will return all C<stable> perl releases >= 5.006
280              
281             Specifying C<dev> as the parameter will return only the C<development> perl releases >= 5.006
282              
283             Specifying C<recent> as the parameter will return only the C<stable> perl releases >= 5.008009
284              
285             =item C<devel_perl>
286              
287             Takes one parameter a perl version to check.
288              
289             Returns true if given perl is a development perl.
290              
291             =item C<can_quadmath>
292              
293             Takes one parameter a perl version to check.
294              
295             Returns true if given perl is able to be built with C<quadmath>.
296              
297             =item C<perl_version>
298              
299             Takes one parameter a perl version.
300              
301             Returns the version with the C<perl-> prefix.
302              
303             =back
304              
305             =head1 SEE ALSO
306              
307             L<smokebrew>
308              
309             L<Perl::Version>
310              
311             L<File::Fetch>
312              
313             L<Archive::Extract>
314              
315             =head1 AUTHOR
316              
317             Chris Williams <chris@bingosnet.co.uk>
318              
319             =head1 COPYRIGHT AND LICENSE
320              
321             This software is copyright (c) 2023 by Chris Williams.
322              
323             This is free software; you can redistribute it and/or modify it under
324             the same terms as the Perl 5 programming language system itself.
325              
326             =cut