File Coverage

blib/lib/Module/CPANTS/Kwalitee/License.pm
Criterion Covered Total %
statement 61 112 54.4
branch 23 56 41.0
condition 10 22 45.4
subroutine 12 17 70.5
pod 3 3 100.0
total 109 210 51.9


line stmt bran cond sub pod time code
1             package Module::CPANTS::Kwalitee::License;
2 7     7   3886 use warnings;
  7         12  
  7         291  
3 7     7   35 use strict;
  7         14  
  7         173  
4 7     7   36 use File::Spec::Functions qw(catfile);
  7         15  
  7         326  
5 7     7   2726 use Software::LicenseUtils;
  7         372708  
  7         8538  
6              
7             our $VERSION = '1.01';
8             $VERSION =~ s/_//; ## no critic
9              
10 35     35 1 108 sub order { 100 }
11              
12             ##################################################################
13             # Analyse
14             ##################################################################
15              
16             sub analyse {
17 11     11 1 54 my $class = shift;
18 11         24 my $me = shift;
19 11         239 my $distdir = $me->distdir;
20              
21             # check META.yml
22 11         206 my $yaml = $me->d->{meta_yml};
23 11         210 $me->d->{license} = '';
24 11 100       123 if ($yaml) {
25 3 50 33     37 if ($yaml->{license} and $yaml->{license} ne 'unknown') {
26 3         20 my $license = $yaml->{license};
27 3 50       10 $license = join ',', @$license if ref $license eq 'ARRAY';
28 3         61 $me->d->{license_from_yaml} = $license;
29 3         102 $me->d->{license} = $license.' defined in META.yml';
30             }
31             }
32             # use "files_array" to exclude files listed in "no_index".
33 11   50     203 my $files = $me->d->{files_array} || [];
34              
35             # check if there's a LICEN[CS]E file
36             # (also accept LICENSE.txt etc; RT #114247)
37 11 50       91 if (my ($file) = grep {$_ =~ /^(?:LICEN[CS]E|COPYING)\b/} @$files) {
  19         123  
38 0         0 $me->d->{license} .= " defined in $file";
39 0         0 $me->d->{external_license_file} = $file;
40             }
41              
42             # check pod
43 11         46 my %licenses;
44 11         46 foreach my $file (grep { /\.(?:pm|pod|pl|PL)$/ } sort @$files ) {
  19         166  
45 9 50       46 next if $file =~ /(?:Makefile|Build)\.PL$/;
46 9         57 my $path = catfile($distdir, $file);
47 9 50       168 next unless -r $path; # skip if not readable
48 9 50       339 open my $fh, '<', $path or next;
49 9         32 my $in_pod = 0;
50 9         47 my $pod = '';
51 9         37 my $pod_head = '';
52 9         37 my @possible_licenses;
53             my @unknown_license_texts;
54 9         0 my $uc_head;
55 9         172 while(<$fh>) {
56 33         83 my $first_four = substr($_, 0, 4);
57 33 50 66     326 if ($first_four eq '=hea' && (($uc_head = uc $_) =~ /(?:LICEN[CS]E|LICEN[CS]ING|COPYRIGHT|LEGAL)/)) {
    100 100        
    50          
58 0         0 $me->d->{license_in_pod} = 1;
59 0   0     0 $me->d->{license} ||= "defined in POD ($file)";
60 0 0       0 if ($in_pod) {
61 0         0 my @guessed = Software::LicenseUtils->guess_license_from_pod("=head1 LICENSE\n$pod\n\n=cut\n");
62 0 0       0 if (@guessed) {
63 0         0 push @possible_licenses, @guessed;
64             } else {
65 0         0 push @unknown_license_texts, "$pod_head$pod";
66             }
67             }
68              
69 0         0 $in_pod = 1;
70 0         0 $pod_head = $_;
71 0         0 $pod = '';
72             }
73             elsif ($first_four eq '=hea' or $first_four eq '=cut') {
74 2 50       6 if ($in_pod) {
75 0         0 my @guessed = Software::LicenseUtils->guess_license_from_pod("=head1 LICENSE\n$pod\n\n=cut\n");
76 0 0       0 if (@guessed) {
77 0         0 push @possible_licenses, @guessed;
78             } else {
79 0         0 push @unknown_license_texts, "$pod_head$pod";
80             }
81             }
82 2         3 $in_pod = 0;
83 2         5 $pod = '';
84             }
85             elsif ($in_pod) {
86 0         0 $pod .= $_;
87             }
88             }
89 9 50       37 if ($pod) {
90 0         0 my @guessed = Software::LicenseUtils->guess_license_from_pod("=head1 LICENSE\n$pod\n\n=cut\n");
91 0 0       0 if (@guessed) {
92 0         0 push @possible_licenses, @guessed;
93             } else {
94 0         0 push @unknown_license_texts, "$pod_head$pod";
95             }
96             }
97 9 50       38 if (@possible_licenses) {
98 0         0 @possible_licenses = map { s/^Software::License:://; $_ } @possible_licenses;
  0         0  
  0         0  
99 0   0     0 push @{$licenses{$_} ||= []}, $file for @possible_licenses;
  0         0  
100 0         0 $me->d->{files_hash}{$file}{license} = join ',', @possible_licenses;
101             } else {
102 9 50       119 $me->d->{unknown_license_texts}{$file} = join "\n", @unknown_license_texts if @unknown_license_texts;
103             }
104             }
105 11 50       48 if (%licenses) {
106 0         0 $me->d->{licenses} = \%licenses;
107 0         0 my @possible_licenses = keys %licenses;
108 0 0       0 if (@possible_licenses == 1) {
109 0         0 my ($type) = @possible_licenses;
110 0         0 $me->d->{license_type} = $type;
111 0         0 $me->d->{license_file} = join ',', @{$licenses{$type}};
  0         0  
112             }
113             }
114              
115 11         48 return;
116             }
117              
118             ##################################################################
119             # Kwalitee Indicators
120             ##################################################################
121              
122             sub kwalitee_indicators{
123             return [
124             {
125             name => 'meta_yml_has_license',
126             error => q{This distribution does not have a license defined in META.yml.},
127             remedy => q{Define the license if you are using in Build.PL. If you are using MakeMaker (Makefile.PL) you should upgrade to ExtUtils::MakeMaker version 6.31.},
128             is_extra => 1,
129             code => sub {
130 11     11   81 my $d = shift;
131 11         29 my $yaml = $d->{meta_yml};
132 11 100 66     68 ($yaml->{license} and $yaml->{license} ne 'unknown') ? 1 : 0 },
133             details => sub {
134 0     0   0 my $d = shift;
135 0         0 my $yaml = $d->{meta_yml};
136 0 0       0 return "No META.yml." unless $yaml;
137 0 0       0 return "No license was found in META.yml." unless $yaml->{license};
138 0         0 return "Unknown license was found in META.yml.";
139             },
140             },
141             {
142             name => 'has_human_readable_license',
143             error => q{This distribution does not have a license defined in the documentation or in a file called LICENSE},
144             remedy => q{Add a section called "LICENSE" to the documentation, or add a file named LICENSE to the distribution.},
145             code => sub {
146 11     11   65 my $d = shift;
147 11 50 33     105 return $d->{external_license_file} || $d->{license_in_pod} ? 1 : 0;
148             },
149             details => sub {
150 0     0   0 my $d = shift;
151 0         0 return "Neither LICENSE file nor LICENSE section in pod was found.";
152             },
153             },
154             {
155             name => 'has_separate_license_file',
156             error => q{This distribution does not have a LICENSE or LICENCE file in its root directory.},
157             remedy => q{This is not a critical issue. Currently mainly informative for the CPANTS authors. It might be removed later.},
158             is_experimental => 1,
159 11 50   11   75 code => sub { shift->{external_license_file} ? 1 : 0 },
160             details => sub {
161 0     0   0 my $d = shift;
162 0         0 return "LICENSE file was found.";
163             },
164             },
165             {
166             name => 'has_license_in_source_file',
167             error => q{Does not have license information in any of its source files},
168             remedy => q{Add =head1 LICENSE and the text of the license to the main module in your code.},
169             code => sub {
170 11     11   72 my $d = shift;
171 11 50       36 return $d->{license_in_pod} ? 1 : 0;
172             },
173             details => sub {
174 0     0   0 my $d = shift;
175 0         0 return "LICENSE section was not found in the pod.";
176             },
177             },
178             {
179             name => 'has_known_license_in_source_file',
180             error => q{Does not have license information in any of its source files, or the information is not recognized by Software::License},
181             remedy => q{Add =head1 LICENSE and/or the proper text of the well-known license to the main module in your code.},
182             is_extra => 1,
183             code => sub {
184 11     11   68 my $d = shift;
185 11 50       41 return 0 unless $d->{license_in_pod};
186 0         0 my @files_with_licenses = grep {$d->{files_hash}{$_}{license}} keys %{$d->{files_hash}};
  0         0  
  0         0  
187 0 0       0 return @files_with_licenses ? 1 : 0;
188             },
189             details => sub {
190 0     0   0 my $d = shift;
191 0         0 return "LICENSE section was not found in the pod, or the license information was not recognized by Software::License.";
192             },
193             },
194 8     8 1 376 ];
195             }
196              
197              
198             q{Favourite record of the moment:
199             Lili Allen - Allright, still};
200              
201             __END__