File Coverage

blib/lib/Module/CPANTS/Kwalitee/License.pm
Criterion Covered Total %
statement 58 109 53.2
branch 21 52 40.3
condition 10 22 45.4
subroutine 12 17 70.5
pod 3 3 100.0
total 104 203 51.2


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