File Coverage

blib/lib/Module/CPANTS/Analyse.pm
Criterion Covered Total %
statement 124 146 84.9
branch 30 46 65.2
condition 8 15 53.3
subroutine 22 22 100.0
pod 9 9 100.0
total 193 238 81.0


line stmt bran cond sub pod time code
1             package Module::CPANTS::Analyse;
2 7     7   320717 use 5.008001;
  7         76  
3 7     7   40 use strict;
  7         12  
  7         149  
4 7     7   32 use warnings;
  7         23  
  7         263  
5 7     7   46 use base qw(Class::Accessor::Fast);
  7         27  
  7         3300  
6 7     7   21276 use File::Temp qw(tempdir);
  7         64177  
  7         402  
7 7     7   1399 use File::Spec::Functions qw(catfile catdir splitpath);
  7         2591  
  7         362  
8 7     7   3373 use File::Copy;
  7         16696  
  7         407  
9 7     7   3239 use File::stat;
  7         46432  
  7         32  
10 7     7   3544 use Archive::Any::Lite;
  7         1022644  
  7         291  
11 7     7   65 use Carp;
  7         18  
  7         416  
12 7     7   3070 use CPAN::DistnameInfo;
  7         7087  
  7         10436  
13              
14             our $VERSION = '1.00';
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   63 my $class = shift;
22 7         3411 require Module::CPANTS::Kwalitee;
23 7         69 Module::CPANTS::Kwalitee->import(@_);
24             }
25              
26             sub new {
27 14     14 1 82143 my $class = shift;
28 14   50     120 my $opts = shift || {};
29 14         139 $opts->{d} = {};
30 14   50     306 $opts->{opts} ||= {};
31 14         97 my $me = bless $opts, $class;
32 14 50       168 Carp::croak("need a dist") if not defined $opts->{dist};
33              
34 14         344 $me->mck(Module::CPANTS::Kwalitee->new);
35              
36             # For Test::Kwalitee and friends
37 14 100       800 $me->d->{is_local_distribution} = 1 if -d $opts->{dist};
38              
39 14         435 return $me;
40             }
41              
42             sub run {
43 11     11 1 30935 my $me = shift;
44 11 100       333 $me->unpack unless $me->d->{is_local_distribution};
45 11         231 $me->analyse;
46 11         50 $me->calc_kwalitee;
47 11         236 $me->d;
48             }
49              
50             sub unpack {
51 1     1 1 45 my $me = shift;
52 1 50       49 return 'cant find dist' unless $me->dist;
53              
54 1         45 my $di = CPAN::DistnameInfo->new($me->dist);
55 1   50     217 my $ext = $di->extension || 'unknown';
56              
57 1         41 $me->d->{package} = $di->filename;
58 1         50 $me->d->{vname} = $di->distvname;
59 1         62 $me->d->{extension} = $ext;
60 1         23 $me->d->{version} = $di->version;
61 1         37 $me->d->{dist} = $di->dist;
62 1         41 $me->d->{author} = $di->cpanid;
63 1         60 $me->d->{released} = stat($me->dist)->mtime;
64 1         350 $me->d->{size_packed} = -s $me->dist;
65              
66 1 50       71 unless($me->d->{package}) {
67 0         0 $me->d->{package} = $me->tarball;
68             }
69              
70 1         43 copy($me->dist, $me->testfile);
71              
72 1         481 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   5728 my $entry = shift;
77 3 50 33     17 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         119 return 1;
82 1         121 }});
83             };
84 1 50       1691 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         33 $me->d->{no_pax_headers} = 1;
89             }
90              
91 1 50       18 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         25 $me->d->{extractable} = 1;
104 1         14 unlink($me->testfile);
105              
106 1 50       95 opendir(my $fh_testdir, $me->testdir) or die "Cannot open ".$me->testdir.": $!";
107 1         100 my @stuff = grep {/\w/} readdir($fh_testdir);
  3         16  
108              
109 1 50       6 if (@stuff == 1) {
110 1         4 $me->distdir(catdir($me->testdir, $stuff[0]));
111 1 50       67 if (-d $me->distdir) {
112              
113 1         26 my $vname = $di->distvname;
114 1         7 $vname =~ s/\-TRIAL[0-9]*//;
115              
116 1         24 $me->d->{extracts_nicely} = 1;
117 1 50       10 if ($vname eq $stuff[0]) {
118 1         22 $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         50 return;
131             }
132              
133             sub analyse {
134 11     11 1 47 my $me = shift;
135              
136 11         35 foreach my $mod (@{$me->mck->generators}) {
  11         250  
137 176         3397 $mod->analyse($me);
138             }
139             }
140              
141             sub calc_kwalitee {
142 11     11 1 28 my $me = shift;
143              
144 11         21 my $kwalitee = 0;
145 11         239 $me->d->{kwalitee} = {};
146 11 100       163 my %x_ignore = %{$me->x_opts->{ignore} || {}};
  11         74  
147 11         491 foreach my $i ($me->mck->get_indicators) {
148 363 50       871 next if $i->{needs_db};
149 363         6362 my $rv = $i->{code}($me->d, $i);
150 363         6781 $me->d->{kwalitee}{$i->{name}} = $rv;
151 363 100 100     2938 if ($x_ignore{$i->{name}} && $i->{ignorable}) {
152 2         40 $me->d->{kwalitee}{$i->{name}} = 1;
153 2 50       49 if ($me->d->{error}{$i->{name}}) {
154 2         56 $me->d->{error}{$i->{name}} .= ' [ignored]';
155             }
156             }
157 363         695 $kwalitee += $rv;
158             }
159              
160 11         221 $me->d->{'kwalitee'}{'kwalitee'} = $kwalitee;
161             }
162              
163             #----------------------------------------------------------------
164             # helper methods
165             #----------------------------------------------------------------
166              
167             sub testdir {
168 11     11 1 1339 my $me = shift;
169 11 100       388 return $me->_testdir if $me->_testdir;
170 3 50       94 if ($me->_dont_cleanup) {
171 0         0 return $me->_testdir(tempdir());
172             } else {
173 3         52 return $me->_testdir(tempdir(CLEANUP => 1));
174             }
175             }
176              
177             sub testfile {
178 5     5 1 2113 my $me = shift;
179 5         20 return catfile($me->testdir, $me->tarball);
180             }
181              
182             sub tarball {
183 5     5 1 518 my $me = shift;
184 5 100       328 return $me->_tarball if $me->_tarball;
185 2         58 my (undef, undef, $tb) = splitpath($me->dist);
186 2         86 return $me->_tarball($tb);
187             }
188              
189             sub x_opts {
190 11     11 1 31 my $me = shift;
191 11 50       250 return $me->_x_opts if $me->_x_opts;
192 11         90 my %opts;
193 11 100       191 if (my $x_cpants = $me->d->{meta_yml}{x_cpants}) {
194 2 50       28 if (my $ignore = $x_cpants->{ignore}) {
195 2 50       18 if (ref $ignore eq ref {}) {
196 2         9 $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         297 $me->_x_opts(\%opts);
204             }
205              
206             q{Favourite record of the moment:
207             Jahcoozi: Pure Breed Mongrel};
208              
209             __END__