File Coverage

blib/lib/Module/CPANTS/Analyse.pm
Criterion Covered Total %
statement 123 146 84.2
branch 30 46 65.2
condition 8 15 53.3
subroutine 22 22 100.0
pod 9 9 100.0
total 192 238 80.6


line stmt bran cond sub pod time code
1             package Module::CPANTS::Analyse;
2 7     7   285056 use 5.008001;
  7         69  
3 7     7   33 use strict;
  7         11  
  7         124  
4 7     7   30 use warnings;
  7         20  
  7         232  
5 7     7   39 use base qw(Class::Accessor::Fast);
  7         23  
  7         3022  
6 7     7   19195 use File::Temp qw(tempdir);
  7         55079  
  7         368  
7 7     7   1128 use File::Spec::Functions qw(catfile catdir splitpath);
  7         2155  
  7         312  
8 7     7   3024 use File::Copy;
  7         15140  
  7         385  
9 7     7   3029 use File::stat;
  7         42519  
  7         47  
10 7     7   3375 use Archive::Any::Lite;
  7         904927  
  7         245  
11 7     7   58 use Carp;
  7         15  
  7         369  
12 7     7   2720 use CPAN::DistnameInfo;
  7         6136  
  7         9181  
13              
14             our $VERSION = '1.01';
15             $VERSION =~ s/_//; ## no critic
16              
17             __PACKAGE__->mk_accessors(qw(dist opts tarball distdir d mck));
18             __PACKAGE__->mk_accessors(qw(_testdir _dont_cleanup _tarball _x_opts));
19              
20             sub import {
21 7     7   58 my $class = shift;
22 7         3040 require Module::CPANTS::Kwalitee;
23 7         63 Module::CPANTS::Kwalitee->import(@_);
24             }
25              
26             sub new {
27 14     14 1 74043 my $class = shift;
28 14   50     91 my $opts = shift || {};
29 14         137 $opts->{d} = {};
30 14   50     241 $opts->{opts} ||= {};
31 14         80 my $me = bless $opts, $class;
32 14 50       140 Carp::croak("need a dist") if not defined $opts->{dist};
33              
34 14         271 $me->mck(Module::CPANTS::Kwalitee->new);
35              
36             # For Test::Kwalitee and friends
37 14 100       646 $me->d->{is_local_distribution} = 1 if -d $opts->{dist};
38              
39 14         382 return $me;
40             }
41              
42             sub run {
43 11     11 1 28834 my $me = shift;
44 11 100       319 $me->unpack unless $me->d->{is_local_distribution};
45 11         186 $me->analyse;
46 11         47 $me->calc_kwalitee;
47 11         222 $me->d;
48             }
49              
50             sub unpack {
51 1     1 1 31 my $me = shift;
52 1 50       32 return 'cant find dist' unless $me->dist;
53              
54 1         28 my $di = CPAN::DistnameInfo->new($me->dist);
55 1   50     159 my $ext = $di->extension || 'unknown';
56              
57 1         24 $me->d->{package} = $di->filename;
58 1         43 $me->d->{vname} = $di->distvname;
59 1         44 $me->d->{extension} = $ext;
60 1         12 $me->d->{version} = $di->version;
61 1         24 $me->d->{dist} = $di->dist;
62 1         21 $me->d->{author} = $di->cpanid;
63 1         39 $me->d->{released} = stat($me->dist)->mtime;
64 1         236 $me->d->{size_packed} = -s $me->dist;
65              
66 1 50       53 unless($me->d->{package}) {
67 0         0 $me->d->{package} = $me->tarball;
68             }
69              
70 1         30 copy($me->dist, $me->testfile);
71              
72 1         339 my @pax_headers;
73 1         2 eval {
74 1         3 my $archive = Archive::Any::Lite->new($me->testfile);
75             $archive->extract($me->testdir, {tar_filter_cb => sub {
76 3     3   4436 my $entry = shift;
77 3 50 33     12 if ($entry->name eq Archive::Tar::Constant::PAX_HEADER() or $entry->type eq 'x' or $entry->type eq 'g') {
      33        
78 0         0 push @pax_headers, $entry->name;
79 0         0 return;
80             }
81 3         85 return 1;
82 1         96 }});
83             };
84 1 50       1274 if (@pax_headers) {
85 0         0 $me->d->{no_pax_headers} = 0;
86 0         0 $me->d->{error}{no_pax_headers} = join ',', @pax_headers;
87             } else {
88 1         25 $me->d->{no_pax_headers} = 1;
89             }
90              
91 1 50       8 if (my $error = $@) {
92 0         0 $me->d->{extractable} = 0;
93 0         0 $me->d->{error}{extractable} = $error;
94 0         0 $me->d->{kwalitee}{extractable} = 0;
95 0         0 my ($vol, $dir, $name) = splitpath($me->dist);
96 0         0 $name =~ s/\..*$//;
97 0         0 $name =~ s/\-[\d\.]+$//;
98 0         0 $name =~ s/\-TRIAL[0-9]*//;
99 0         0 $me->d->{dist} = $name;
100 0         0 return $error;
101             }
102              
103 1         15 $me->d->{extractable} = 1;
104 1         6 unlink($me->testfile);
105              
106 1 50       69 opendir(my $fh_testdir, $me->testdir) or die "Cannot open ".$me->testdir.": $!";
107 1         58 my @stuff = grep {/\w/} readdir($fh_testdir);
  3         12  
108              
109 1 50       4 if (@stuff == 1) {
110 1         4 $me->distdir(catdir($me->testdir, $stuff[0]));
111 1 50       52 if (-d $me->distdir) {
112              
113 1         20 my $vname = $di->distvname;
114 1         6 $vname =~ s/\-TRIAL[0-9]*//;
115              
116 1         19 $me->d->{extracts_nicely} = 1;
117 1 50       7 if ($vname ne $stuff[0]) {
118 0         0 $me->d->{error}{extracts_nicely} = "expected $vname but got $stuff[0]";
119             }
120             } else {
121 0         0 $me->distdir($me->testdir);
122 0         0 $me->d->{extracts_nicely} = 0;
123 0         0 $me->d->{error}{extracts_nicely} = join ",", @stuff;
124             }
125             } else {
126 0         0 $me->distdir($me->testdir);
127 0         0 $me->d->{extracts_nicely} = 0;
128 0         0 $me->d->{error}{extracts_nicely} = join ",", @stuff;
129             }
130 1         28 return;
131             }
132              
133             sub analyse {
134 11     11 1 61 my $me = shift;
135              
136 11         31 foreach my $mod (@{$me->mck->generators}) {
  11         254  
137 176         2939 $mod->analyse($me);
138             }
139             }
140              
141             sub calc_kwalitee {
142 11     11 1 24 my $me = shift;
143              
144 11         23 my $kwalitee = 0;
145 11         206 $me->d->{kwalitee} = {};
146 11 100       82 my %x_ignore = %{$me->x_opts->{ignore} || {}};
  11         48  
147 11         430 foreach my $i ($me->mck->get_indicators) {
148 363 50       682 next if $i->{needs_db};
149 363         5781 my $rv = $i->{code}($me->d, $i);
150 363         6174 $me->d->{kwalitee}{$i->{name}} = $rv;
151 363 100 100     2532 if ($x_ignore{$i->{name}} && $i->{ignorable}) {
152 2         39 $me->d->{kwalitee}{$i->{name}} = 1;
153 2 50       49 if ($me->d->{error}{$i->{name}}) {
154 2         44 $me->d->{error}{$i->{name}} .= ' [ignored]';
155             }
156             }
157 363         595 $kwalitee += $rv;
158             }
159              
160 11         242 $me->d->{'kwalitee'}{'kwalitee'} = $kwalitee;
161             }
162              
163             #----------------------------------------------------------------
164             # helper methods
165             #----------------------------------------------------------------
166              
167             sub testdir {
168 11     11 1 1347 my $me = shift;
169 11 100       302 return $me->_testdir if $me->_testdir;
170 3 50       75 if ($me->_dont_cleanup) {
171 0         0 return $me->_testdir(tempdir());
172             } else {
173 3         40 return $me->_testdir(tempdir(CLEANUP => 1));
174             }
175             }
176              
177             sub testfile {
178 5     5 1 1692 my $me = shift;
179 5         16 return catfile($me->testdir, $me->tarball);
180             }
181              
182             sub tarball {
183 5     5 1 561 my $me = shift;
184 5 100       86 return $me->_tarball if $me->_tarball;
185 2         42 my (undef, undef, $tb) = splitpath($me->dist);
186 2         67 return $me->_tarball($tb);
187             }
188              
189             sub x_opts {
190 11     11 1 25 my $me = shift;
191 11 50       235 return $me->_x_opts if $me->_x_opts;
192 11         72 my %opts;
193 11 100       170 if (my $x_cpants = $me->d->{meta_yml}{x_cpants}) {
194 2 50       32 if (my $ignore = $x_cpants->{ignore}) {
195 2 50       17 if (ref $ignore eq ref {}) {
196 2         18 $opts{ignore} = $ignore;
197             }
198             else {
199 0         0 $me->d->{error}{x_cpants} = "x_cpants ignore should be a hash reference (key: metric, value: reason to ignore)";
200             }
201             }
202             }
203 11         261 $me->_x_opts(\%opts);
204             }
205              
206             q{Favourite record of the moment:
207             Jahcoozi: Pure Breed Mongrel};
208              
209             __END__