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   349543 use 5.008001;
  7         76  
3 7     7   41 use strict;
  7         13  
  7         153  
4 7     7   34 use warnings;
  7         15  
  7         198  
5 7     7   36 use base qw(Class::Accessor::Fast);
  7         23  
  7         3688  
6 7     7   24455 use File::Temp qw(tempdir);
  7         69303  
  7         372  
7 7     7   1413 use File::Spec::Functions qw(catfile catdir splitpath);
  7         2622  
  7         389  
8 7     7   3542 use File::Copy;
  7         17212  
  7         399  
9 7     7   4699 use File::stat;
  7         48599  
  7         30  
10 7     7   3856 use Archive::Any::Lite;
  7         1066538  
  7         305  
11 7     7   69 use Carp;
  7         19  
  7         464  
12 7     7   3609 use Parse::Distname;
  7         14322  
  7         11135  
13              
14             our $VERSION = '1.02';
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   75 my $class = shift;
22 7         3676 require Module::CPANTS::Kwalitee;
23 7         72 Module::CPANTS::Kwalitee->import(@_);
24             }
25              
26             sub new {
27 15     15 1 125551 my $class = shift;
28 15   50     120 my $opts = shift || {};
29 15         177 $opts->{d} = {};
30 15   50     355 $opts->{opts} ||= {};
31 15         102 my $me = bless $opts, $class;
32 15 50       182 Carp::croak("need a dist") if not defined $opts->{dist};
33              
34 15         372 $me->mck(Module::CPANTS::Kwalitee->new);
35              
36             # For Test::Kwalitee and friends
37 15 100       980 $me->d->{is_local_distribution} = 1 if -d $opts->{dist};
38              
39 15         519 return $me;
40             }
41              
42             sub run {
43 12     12 1 36079 my $me = shift;
44 12 100       382 $me->unpack unless $me->d->{is_local_distribution};
45 12         258 $me->analyse;
46 12         62 $me->calc_kwalitee;
47 12         265 $me->d;
48             }
49              
50             sub unpack {
51 1     1 1 48 my $me = shift;
52 1 50       48 return 'cant find dist' unless $me->dist;
53              
54 1         65 my $di = Parse::Distname->new($me->dist);
55 1   50     318 my $ext = $di->extension || 'unknown';
56              
57 1         32 $me->d->{package} = $di->filename;
58 1         63 $me->d->{vname} = $di->distvname;
59 1         61 $me->d->{extension} = $ext;
60 1         20 $me->d->{version} = $di->version;
61 1         50 $me->d->{dist} = $di->dist;
62 1         35 $me->d->{author} = $di->cpanid;
63 1         47 $me->d->{released} = stat($me->dist)->mtime;
64 1         345 $me->d->{size_packed} = -s $me->dist;
65              
66 1 50       384 unless($me->d->{package}) {
67 0         0 $me->d->{package} = $me->tarball;
68             }
69              
70 1         45 copy($me->dist, $me->testfile);
71              
72 1         513 my @pax_headers;
73 1         3 eval {
74 1         5 my $archive = Archive::Any::Lite->new($me->testfile);
75             $archive->extract($me->testdir, {tar_filter_cb => sub {
76 3     3   6076 my $entry = shift;
77 3 50 33     11 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         97 return 1;
82 1         131 }});
83             };
84 1 50       1704 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         32 $me->d->{no_pax_headers} = 1;
89             }
90              
91 1 50       24 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         24 $me->d->{extractable} = 1;
104 1         20 unlink($me->testfile);
105              
106 1 50       101 opendir(my $fh_testdir, $me->testdir) or die "Cannot open ".$me->testdir.": $!";
107 1         96 my @stuff = grep {/\w/} readdir($fh_testdir);
  3         19  
108              
109 1 50       7 if (@stuff == 1) {
110 1         6 $me->distdir(catdir($me->testdir, $stuff[0]));
111 1 50       72 if (-d $me->distdir) {
112              
113 1         33 my $vname = $di->distvname;
114 1         9 $vname =~ s/\-TRIAL[0-9]*//;
115              
116 1         24 $me->d->{extracts_nicely} = 1;
117 1 50       26 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         42 return;
131             }
132              
133             sub analyse {
134 12     12 1 46 my $me = shift;
135              
136 12         26 foreach my $mod (@{$me->mck->generators}) {
  12         295  
137 192         3823 $mod->analyse($me);
138             }
139             }
140              
141             sub calc_kwalitee {
142 12     12 1 37 my $me = shift;
143              
144 12         24 my $kwalitee = 0;
145 12         266 $me->d->{kwalitee} = {};
146 12 100       116 my %x_ignore = %{$me->x_opts->{ignore} || {}};
  12         66  
147 12         598 foreach my $i ($me->mck->get_indicators) {
148 396 50       849 next if $i->{needs_db};
149 396         7149 my $rv = $i->{code}($me->d, $i);
150 396         7471 $me->d->{kwalitee}{$i->{name}} = $rv;
151 396 100 100     3262 if ($x_ignore{$i->{name}} && $i->{ignorable}) {
152 2         62 $me->d->{kwalitee}{$i->{name}} = 1;
153 2 50       44 if ($me->d->{error}{$i->{name}}) {
154 2         57 $me->d->{error}{$i->{name}} .= ' [ignored]';
155             }
156             }
157 396         711 $kwalitee += $rv;
158             }
159              
160 12         244 $me->d->{'kwalitee'}{'kwalitee'} = $kwalitee;
161             }
162              
163             #----------------------------------------------------------------
164             # helper methods
165             #----------------------------------------------------------------
166              
167             sub testdir {
168 11     11 1 1548 my $me = shift;
169 11 100       284 return $me->_testdir if $me->_testdir;
170 3 50       108 if ($me->_dont_cleanup) {
171 0         0 return $me->_testdir(tempdir());
172             } else {
173 3         80 return $me->_testdir(tempdir(CLEANUP => 1));
174             }
175             }
176              
177             sub testfile {
178 5     5 1 2193 my $me = shift;
179 5         18 return catfile($me->testdir, $me->tarball);
180             }
181              
182             sub tarball {
183 5     5 1 557 my $me = shift;
184 5 100       102 return $me->_tarball if $me->_tarball;
185 2         60 my (undef, undef, $tb) = splitpath($me->dist);
186 2         104 return $me->_tarball($tb);
187             }
188              
189             sub x_opts {
190 12     12 1 25 my $me = shift;
191 12 50       295 return $me->_x_opts if $me->_x_opts;
192 12         119 my %opts;
193 12 100       211 if (my $x_cpants = $me->d->{meta_yml}{x_cpants}) {
194 2 50       27 if (my $ignore = $x_cpants->{ignore}) {
195 2 50       15 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 12         332 $me->_x_opts(\%opts);
204             }
205              
206             q{Favourite record of the moment:
207             Jahcoozi: Pure Breed Mongrel};
208              
209             __END__