File Coverage

blib/lib/Dist/Zilla/Plugin/LicenseFromModule.pm
Criterion Covered Total %
statement 49 64 76.5
branch 14 30 46.6
condition 6 16 37.5
subroutine 11 11 100.0
pod 0 4 0.0
total 80 125 64.0


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::LicenseFromModule;
2 5     5   3999681 use strict;
  5         10  
  5         265  
3             our $VERSION = '0.05';
4              
5 5     5   25 use Moose;
  5         7  
  5         33  
6             with 'Dist::Zilla::Role::LicenseProvider';
7              
8             has 'override_author', is => 'rw', isa => 'Bool', default => 0;
9              
10             has source_file => (
11             is => 'ro',
12             lazy => 1,
13             isa => 'Str',
14             builder => '_default_source_file',
15             );
16              
17             sub _default_source_file {
18 4     4   7 my $self = shift;
19 4         113 my $pm = $self->zilla->main_module->name;
20 4         4452 (my $pod = $pm) =~ s/\.pm$/\.pod/;
21 4 100       297 return -e $pod ? $pod : $pm;
22             }
23              
24             sub _file_from_filename {
25 14     14   43 my ($self, $filename) = @_;
26 14         23 for my $file (@{$self->zilla->files}) {
  14         405  
27 51 100       1699 return $file if $file->name eq $filename;
28             }
29 3         64 die 'no file module $filename in dist';
30             }
31              
32 5     5   28895 use Software::LicenseUtils;
  5         127409  
  5         188  
33 5     5   34 use Module::Load ();
  5         7  
  5         3423  
34              
35             sub should_override_author {
36 11     11 0 21 my $self = shift;
37              
38 11 100       443 return unless $self->override_author;
39              
40 4         105 my $stash = $self->zilla->stash_named('%User');
41 4 50       234 return unless $stash; # no %User stash means author is taken out of copyright_holder anyway
42              
43 0         0 return $stash->authors->[0] eq $self->zilla->authors->[0];
44             }
45              
46             sub provide_license {
47 14     14 0 468043 my($self, $args) = @_;
48              
49 14         563 my $content = $self->_file_from_filename($self->source_file)->content;
50              
51 11         8980 my $author = $self->author_from($content);
52 11         52 my $year = $self->copyright_year_from($content);
53              
54 11 50       37 if ($self->should_override_author) {
55 0         0 $self->zilla->{authors} = [ $author ]; # XXX ughhh because it's readonly
56             }
57              
58 11         106 my @guess = Software::LicenseUtils->guess_license_from_pod($content);
59              
60 11 50       4967 if (@guess != 1) {
61 0         0 $self->log(["Failed to parse license from %s", $self->zilla->main_module->name]);
62 0         0 return;
63             }
64              
65 11         19 my $license_class = $guess[0];
66              
67 11   50     430 $self->log(["guessing from %s, License is %s\nCopyright %s %s",
      50        
68             $self->source_file, $license_class,
69             $year || '(unknown)', $author || '(unknown)']);
70              
71 11         3998 Module::Load::load($license_class);
72              
73 11   33     924 return $license_class->new({
      33        
74             holder => $author || $args->{copyright_holder},
75             year => $year || $args->{copyright_year},
76             });
77             }
78              
79             # taken from Module::Install::Metadata::author_from (as well as Minilla)
80             sub author_from {
81 11     11 0 23 my($self, $content) = @_;
82              
83 11 50       246 if ($content =~ m/
84             =head \d \s+ (?:authors?)\b \s*
85             ([^\n]*)
86             |
87             =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s*
88             .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s*
89             ([^\n]*)
90             /ixms) {
91 11   66     56 my $author = $1 || $2;
92              
93             # XXX: ugly but should work anyway...
94 11 50 0     840 if (eval "require Pod::Escapes; 1") { ## no critics.
    0          
95             # Pod::Escapes has a mapping table.
96             # It's in core of perl >= 5.9.3, and should be installed
97             # as one of the Pod::Simple's prereqs, which is a prereq
98             # of Pod::Text 3.x (see also below).
99 11         85 $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> }
100             {
101             defined $2
102             ? chr($2)
103             : defined $Pod::Escapes::Name2character_number{$1}
104             ? chr($Pod::Escapes::Name2character_number{$1})
105 16 50       115 : do {
    50          
106 0         0 warn "Unknown escape: E<$1>";
107 0         0 "E<$1>";
108             };
109             }gex;
110             }
111             ## no critic.
112             elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) {
113             # Pod::Text < 3.0 has yet another mapping table,
114             # though the table name of 2.x and 1.x are different.
115             # (1.x is in core of Perl < 5.6, 2.x is in core of
116             # Perl < 5.9.3)
117 0 0       0 my $mapping = ($Pod::Text::VERSION < 2)
118             ? \%Pod::Text::HTML_Escapes
119             : \%Pod::Text::ESCAPES;
120 0         0 $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> }
121             {
122             defined $2
123             ? chr($2)
124             : defined $mapping->{$1}
125             ? $mapping->{$1}
126 0 0       0 : do {
    0          
127 0         0 warn "Unknown escape: E<$1>";
128 0         0 "E<$1>";
129             };
130             }gex;
131             }
132             else {
133 0         0 $author =~ s{E<lt>}{<}g;
134 0         0 $author =~ s{E<gt>}{>}g;
135             }
136 11         44 return $author;
137             }
138              
139 0         0 return;
140             }
141              
142             sub copyright_year_from {
143 11     11 0 23 my($self, $content) = @_;
144              
145 11 50       138 if ($content =~ m/
146             =head \d \s+ (?:licen[cs]e|licensing|copyright|legal|authors?)\b \s*
147             .*? copyright .*? ([\d\-]+)
148             /ixms) {
149 11         34 return $1;
150             }
151              
152 0           return;
153             }
154              
155 5     5   28 no Moose;
  5         7  
  5         41  
156             __PACKAGE__->meta->make_immutable;
157             1;
158             __END__
159              
160             =encoding utf-8
161              
162             =head1 NAME
163              
164             Dist::Zilla::Plugin::LicenseFromModule - Extract License and Copyright from its main_module file
165              
166             =head1 SYNOPSIS
167              
168             ; dist.ini
169             [LicenseFromModule]
170              
171             =head1 DESCRIPTION
172              
173             Dist::Zilla::Plugin::LicenseFromModule is a Dist::Zilla plugin to
174             extract license, author and copyright year from your main module's POD
175             document.
176              
177             Dist::Zilla by default already extracts license from POD when it's not
178             specified, but it will bail out if you don't specify the right
179             copyright holder. This plugin will scan license B<and> copyright
180             holder from the POD document, like L<Module::Install>'s
181             C<license_from> and C<author_from>.
182              
183             =head1 AUTHOR
184              
185             Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
186              
187             =head1 COPYRIGHT
188              
189             Copyright 2013- Tatsuhiko Miyagawa
190              
191             =head1 LICENSE
192              
193             This library is free software; you can redistribute it and/or modify
194             it under the same terms as Perl itself.
195              
196             =head1 SEE ALSO
197              
198             L<Dist::Zilla> L<Dist::Zilla::Plugin::VersionFromModule>
199              
200             =cut