File Coverage

blib/lib/Module/Package/Plugin.pm
Criterion Covered Total %
statement 39 217 17.9
branch 0 100 0.0
condition 0 39 0.0
subroutine 13 44 29.5
pod 8 27 29.6
total 60 427 14.0


line stmt bran cond sub pod time code
1             ##
2             # name: Module::Package::Plugin
3             # abstract: Base class for Module::Package author-side plugins
4             # author: Ingy döt Net
5             # license: perl
6             # copyright: 2011
7             # see:
8             # - Module::Package
9             # - Module::Package::Tutorial
10              
11 1     1   1702 use 5.008003;
  1         3  
  1         38  
12 1     1   1818 use utf8;
  1         11  
  1         6  
13              
14             package Module::Package::Plugin;
15 1     1   1065 use Moo 0.009008;
  1         45590  
  1         7  
16              
17             our $VERSION = '0.30';
18              
19 1     1   8033 use Cwd 0 ();
  1         23  
  1         24  
20 1     1   7 use File::Find 0 ();
  1         20  
  1         25  
21 1     1   747 use Module::Install 1.01 ();
  1         25  
  1         30  
22 1     1   986 use Module::Install::AuthorRequires 0.02 ();
  1         225  
  1         29  
23 1     1   1594 use Module::Install::ManifestSkip 0.19 ();
  1         416  
  1         28  
24 1     1   1006 use IO::All 0.41;
  1         18729  
  1         12  
25              
26             has mi => (is => 'rw');
27             has options => (
28             is => 'rw',
29             lazy => 1,
30             default => sub {
31             my ($self) = @_;
32             $self->mi->package_options;
33             },
34             );
35              
36             #-----------------------------------------------------------------------------#
37             # These 3 functions (initial, main and final) make up the Module::Package
38             # plugin API. Subclasses MUST override 'main', and should rarely override
39             # 'initial' and 'final'.
40             #-----------------------------------------------------------------------------#
41             sub initial {
42 0     0 1   my ($self) = @_;
43             # Load pkg/conf.yaml if it exists
44 0           $self->eval_deps_list;
45             }
46              
47             sub main {
48 0     0 1   my ($self) = @_;
49 0           my $class = ref($self);
50 0 0         die "$class cannot be used as a Module::Package plugin. Use a subclass"
51             if $class eq __PACKAGE__;
52 0           die "$class needs to provide a method called 'main()'";
53             }
54              
55             sub final {
56 0     0 1   my ($self) = @_;
57              
58 0           $self->manifest_skip;
59              
60             # NOTE These must match Module::Install::Package::_final.
61 0           $self->all_from;
62 0           $self->requires_from;
63 0           $self->install_bin;
64 0           $self->install_share;
65 0           $self->WriteAll;
66              
67 0           $self->write_deps_list;
68             }
69              
70             #-----------------------------------------------------------------------------#
71             # This is where the useful methods (that author plugins can invoke) live.
72             #-----------------------------------------------------------------------------#
73 0     0 0   sub pm_file { return "$main::PM" }
74 0     0 0   sub pod_file { return "$main::POD" }
75 0   0 0 0   sub pod_or_pm_file { return "$main::POD" || "$main::PM" }
76              
77             my $deps_list_file = 'pkg/deps_list.pl';
78             sub eval_deps_list {
79 0     0 0   my ($self) = @_;
80 0 0         return if not $self->options->{deps_list};
81 0           my $data = '';
82 0 0         if (-e 'Makefile.PL') {
83 0           my $text = io('Makefile.PL')->all;
84 0 0         if ($text =~ /.*\n__(?:DATA|END)__\r?\n(.*)/s) {
85 0           $data = $1;
86             }
87             }
88 0 0 0       if (-e $deps_list_file and -s $deps_list_file) {
    0          
89             package main;
90 0           require $deps_list_file;
91             }
92             elsif ($data) {
93             package main;
94 0           eval $data;
95 0 0         die $@ if $@;
96             }
97             }
98              
99             sub write_deps_list {
100 0     0 0   my ($self) = @_;
101 0 0         return if not $self->options->{deps_list};
102 0           my $text = $self->generate_deps_list;
103 0 0         if (-e $deps_list_file) {
104 0           my $old_text = io($deps_list_file)->all;
105 0 0         $text .= "\n1;\n" if $text;
106 0 0         if ($text ne $old_text) {
107 0           warn "Updating $deps_list_file\n";
108 0           io($deps_list_file)->print($text);
109             }
110 0           $text = '';
111             }
112 0 0 0       if (
    0          
113             -e 'Makefile.PL' and
114             io('Makefile.PL')->all =~ /^__(?:DATA|END)__$/m
115             ) {
116 0           my $perl = io('Makefile.PL')->all;
117 0           my $old_perl = $perl;
118 0 0         $perl =~ s/(.*\n__(?:DATA|END)__\r?\n).*/$1/s or die $perl;
119 0 0         if (-e $deps_list_file) {
120 0           io('Makefile.PL')->print($perl);
121 0           return;
122             }
123 0 0         $perl .= "\n" . $text if $text;
124 0 0         if ($perl ne $old_perl) {
125 0           warn "Updating deps_list in Makefile.PL\n";
126 0           io('Makefile.PL')->print($perl);
127 0 0         if (-e 'Makefile') {
128 0           sleep 1;
129 0           io('Makefile')->touch;
130             }
131             }
132             }
133             elsif ($text) {
134 0           warn <<"...";
135             Note: Can't find a place to write deps list, and deps_list option is true.
136 0           touch $deps_list_file or add __END__ to Makefile.PL.
137             See 'deps_list' in Module::Package::Plugin documentation.
138             Deps List:
139 0           ${$_ = $text; chomp; s/^/ /mg; \$_}
  0            
  0            
140             ...
141             }
142             }
143              
144             sub generate_deps_list {
145 0     0 0   my ($self) = @_;
146 0           my $base = Cwd::cwd();
147 0           my %skip = map {($_, 1)}
  0            
148             qw(Module::Package Module::Install),
149             $self->skip_deps(ref($self)),
150             (map "Module::Install::$_", qw(
151             Admin AuthorRequires AutoInstall Base Bundle Can Compiler
152             Deprecated DSL External Fetch Include Inline Makefile MakeMaker
153             ManifestSkip Metadata Package PAR Run Scripts Share Win32 With
154             WriteAll
155             ));
156 0           my @skip;
157 0           for my $module (keys %skip) {
158 0 0         if ($skip{"Module::Install::$module"}) {
159 0           push @skip, "${module}::";
160             }
161             }
162 0           my @inc = ();
163             File::Find::find(sub {
164 0 0 0 0     return unless -f $_ and $_ =~ /\.pm$/;
165 0           my $module = $File::Find::name;
166 0           $module =~ s!inc[\/\\](.*)\.pm$!$1!;
167 0 0         return if -e "$base/lib/$module.pm";
168 0           $module =~ s!/+!::!g;
169 0 0         return if $skip{$module};
170 0           for my $prefix (@skip) {
171 0 0         return if $module =~ /^\Q$prefix\E/;
172             }
173 0           push @inc, $module;
174 0           }, 'inc');
175 0 0         if (grep /^Module::Install::TestBase$/, @inc) {
176 0           @inc = grep not(/^(Test::|Spiffy)/), @inc;
177             }
178 0 0         if (not $Module::Package::plugin_version) {
179 0           my $module = ref($self);
180 0           $module =~ s/::[a-z].*//;
181 0           unshift @inc, $module;
182             };
183 0           my $text = '';
184 1     1   1663 no strict 'refs';
  1         2  
  1         765  
185             $text .= join '', map {
186 0   0       my $version = ${"${_}::VERSION"} || '';
  0            
187 0 0         if ($version) {
188 0           "author_requires '$_' => '$version';\n";
189             }
190             else {
191 0           "author_requires '$_';\n";
192             }
193             } @inc;
194 0 0         $text = <<"..." . $text if $text;
195             # Deps list generated by:
196             author_requires 'Module::Package' => '$Module::Package::VERSION';
197              
198             ...
199 0           return $text;
200             }
201              
202             sub skip_deps {
203 0     0 0   my ($self, $file) = @_;
204 0 0         $file =~ s/^(.*)::[^A-Z].*$/$1/
205             or die "Can't grok paackage '$file'";
206 0           $file =~ s!::!/!g;
207 0           $file .= '.pm';
208 0 0         $file = $INC{$file} or return ();
209 0           my $content = Module::Install::_readperl($file);
210 0           return ($content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(?:[\d\.]+)/mg);
211             }
212              
213             # We generate a MANIFEST.SKIP and add things to it.
214             # We add pkg/, because that should only contain author stuff.
215             # We add author only M::I plugins, so they don't get distributed.
216             sub manifest_skip {
217 0     0 1   my ($self) = @_;
218 0 0         return unless $self->options->{manifest_skip};
219 0           $self->mi->manifest_skip;
220              
221 0           $self->set_author_only_defaults;
222 0           my @skips = (
223             "^pkg/\n",
224             "^inc/.*\\.pod\n",
225             );
226 0           for (sort keys %INC) {
227 0           my $path = $_;
228 0           s!/!::!g;
229 0           s!\.pm$!!;
230 0 0         next unless /^Module::Install::/;
231 1     1   7 no strict 'refs';
  1         3  
  1         1365  
232 0           push @skips, "^inc/$path\$\n"
233 0 0         if ${"${_}::AUTHOR_ONLY"}
234             }
235              
236 0           io('MANIFEST.SKIP')->append(join '', @skips);
237 0 0         if (-e 'pkg/manifest.skip') {
238 0           io('MANIFEST.SKIP')->append(io('pkg/manifest.skip')->all);
239             }
240              
241 0           $self->mi->clean_files('MANIFEST MANIFEST.SKIP');
242             }
243              
244             sub check_use_test_base {
245 0     0 0   my ($self) = @_;
246 0           my @files;
247             File::Find::find(sub {
248 0 0 0 0     return unless -f $_ and $_ =~ /\.(pm|t)$/;
249 0           push @files, $File::Find::name;
250 0           }, 't');
251 0           for my $file (@files) {
252 0 0         if (io($file)->all =~ /\bTest::Base\b/) {
253 0           $self->mi->use_test_base;
254 0           return;
255             }
256             }
257             }
258              
259             sub check_use_testml {
260 0     0 0   my ($self) = @_;
261 0           my $found = 0;
262             File::Find::find(sub {
263 0 0 0 0     return unless -f $_ and $_ =~ /\.t$/;
264 0 0         return unless io($_)->all =~ /\buse TestML\b/;
265 0           $found = 1;
266 0           }, 't');
267 0 0 0       if ($found or -e 't/testml') {
268 0           $self->mi->use_testml;
269             }
270             }
271              
272             sub check_test_common {
273 0     0 0   my ($self) = @_;
274 0 0         if (-e 't/common.yaml') {
275 0           $self->mi->test_common_update;
276             }
277             }
278              
279             sub check_use_gloom {
280 0     0 0   my ($self) = @_;
281 0           my @files;
282             File::Find::find(sub {
283 0 0 0 0     return unless -f $_ and $_ =~ /\.pm$/;
284 0 0         return if $File::Find::name eq 'lib/Gloom.pm';
285 0 0         return if $File::Find::name eq 'lib/Module/Install/Gloom.pm';
286 0 0         return unless io($_)->getline =~ /\bGloom\b/;
287 0           push @files, $File::Find::name;
288 0           }, 'lib');
289 0           for my $file (@files) {
290 0 0         $file =~ s/^lib\/(.*)\.pm$/$1/ or die;
291 0           $file =~ s/\//::/g;
292 0           $self->mi->use_gloom($file);
293             }
294             }
295              
296 0     0 0   sub strip_extra_comments {
297             # TODO later
298             }
299              
300             #-----------------------------------------------------------------------------#
301             # These functions are wrappers around Module::Install functions of the same
302             # names. They are generally safer (and simpler) to call than the real ones.
303             # They should almost always be chosen by Module::Package::Plugin subclasses.
304             #-----------------------------------------------------------------------------#
305             sub post_all_from {
306 0     0 0   my $self = shift;
307 0   0       push @{$self->{post_all_from} ||= []}, @_;
  0            
308             }
309             sub all_from {
310 0     0 0   my $self = shift;
311 0           $self->mi->_all_from(@_);
312 0 0         $_->() for @{$self->{post_all_from} || []};
  0            
313             }
314             sub post_WriteAll {
315 0     0 0   my $self = shift;
316 0   0       push @{$self->{post_WriteAll} ||= []}, @_;
  0            
317             }
318             sub WriteAll {
319 0     0 0   my $self = shift;
320 0           $self->mi->_WriteAll(@_);
321 0 0         $_->() for @{$self->{post_WriteAll} || []};
  0            
322             }
323 0     0 1   sub requires_from { my $self = shift; $self->mi->_requires_from(@_) }
  0            
324 0     0 1   sub install_bin { my $self = shift; $self->mi->_install_bin(@_) }
  0            
325 0     0 1   sub install_share { my $self = shift; $self->mi->_install_share(@_) }
  0            
326              
327             #-----------------------------------------------------------------------------#
328             # Other housekeeping stuffs
329             #-----------------------------------------------------------------------------#
330             # This gets called very last on the author side.
331             sub replicate_module_package {
332 0     0 0   my $target_file = 'inc/Module/Package.pm';
333 0 0 0       if (-e 'inc/.author' and not -e $target_file) {
334 0 0         my $source_file = $INC{'Module/Package.pm'}
335             or die "Can't bootstrap inc::Module::Package";
336 0           Module::Install::Admin->copy($source_file, $target_file);
337             }
338             }
339              
340             # TODO Check all versions possible here.
341             sub version_check {
342 0     0 0   my ($self, $version) = @_;
343 0 0 0       die <<"..."
      0        
344              
345             Error! Something has gone awry:
346             inc::Module::Package version=$inc::Module::Package::VERSION
347             Module::Package version=$::Module::Package::VERSION
348             Module::Install::Package version=$version
349             Module::Package::Plugin version=$VERSION
350             Try upgrading Module::Package.
351              
352             ...
353             unless $version == $VERSION and
354             $version == $Module::Package::VERSION and
355             $version == $inc::Module::Package::VERSION;
356             }
357              
358             # This is a set of known AUTHOR_ONLY plugins. Until authors set this variable
359             # themselves, do it here to make sure these get added to the MANIFEST.SKIP and
360             # thus do not end up in the distributions, causing bloat.
361             sub set_author_only_defaults {
362 0     0 0   my @known_author_only = qw(
363             AckXXX
364             AuthorRequires
365             AutoLicense
366             GitHubMeta
367             ManifestSkip
368             ReadmeFromPod
369             ReadmeMarkdownFromPod
370             Repository
371             Stardoc
372             TestBase
373             TestML
374             VersionCheck
375             );
376 0           for (@known_author_only) {
377 1     1   8 no strict 'refs';
  1         3  
  1         110  
378 0           ${"Module::Install::${_}::AUTHOR_ONLY"} = 1
  0            
379 0 0         unless defined ${"Module::Install::${_}::AUTHOR_ONLY"};
380             }
381             }
382              
383             #-----------------------------------------------------------------------------#
384             # These are the usable subclasses that this module provides. Currently there
385             # is only one, ':basic'. It does the minimum amount possible. Even though it
386             # seems to do nothing, there is plenty of functionality that happens in the
387             # final() method.
388             #-----------------------------------------------------------------------------#
389             package Module::Package::Plugin::basic;
390 1     1   6 use Moo;
  1         2  
  1         9  
391             extends 'Module::Package::Plugin';
392              
393             sub main {
394 0     0 1   my ($self) = @_;
395             }
396              
397             1;
398              
399             =head1 SYNOPSIS
400              
401             package Module::Package::Name;
402              
403             package Module::Package::Name::flavor;
404             use Moo;
405             extends 'Module::Package::Plugin';
406              
407             sub main {
408             my ($self) = @_;
409             $self->mi->some_module_install_author_plugin;
410             $self->mi->other_author_plugin;
411             }
412              
413             1;
414              
415             =head1 DESCRIPTION
416              
417             This module is the base class for Module::Package plugins.
418              
419             =head1 EXAMPLE
420              
421             Take a look at the L module, for a decent starting
422             point example. That plugin module is actually used to package Module::Package
423             itself.
424              
425             =head1 API
426              
427             To create a Module::Package plugin you need to subclass
428             Module::Package::Plugin and override the C
method, and possibly other
429             things. This section describes how that works.
430              
431             Makefile.PL processing happens in the following order:
432              
433             - 'use inc::Module::Package...' is invoked
434             - $plugin->initial is called
435             - BEGIN blocks in Makefile.PL are run
436             - $plugin->main is called
437             - The body of Makefile.PL is run
438             - $plugin->final is called
439              
440             =head2 initial
441              
442             This method is call during the processing of 'use inc::Module::Package'. You
443             probably don't need to subclass it. If you do you probably want to call the
444             SUPER method.
445              
446             It runs the deps_list, if any and guesses the primary modules file path.
447              
448             =head2 main
449              
450             This is the method you must override. Do all the things you want. You can call
451             C, if you need to get sequencing right, otherwise it gets called by
452             final(). Don't call C, it get's called automatically in final().
453              
454             =head2 final
455              
456             This does all the things after the entire Makefile.PL body has run. You
457             probably don't need to override it.
458              
459             =head1 OPTIONS
460              
461             The following options are available for use from the Makefile.PL:
462              
463             use Module::Package 'Foo:bar',
464             deps_list => 0|1,
465             install_bin => 0|1,
466             install_share => 0|1,
467             manifest_skip => 0|1,
468             requires_from => 0|1;
469              
470             These options can be used by any subclass of this module.
471              
472             =head2 deps_list
473              
474             Default is 1.
475              
476             This option tells Module::Package to generate a C deps list,
477             when you run the Makefile.PL. This list will go in the file
478             C if that exists, or after a '__END__' statement in your
479             Makefile.PL. If neither is available, a reminder will be warned (only when the
480             author runs it).
481              
482             This list is important if you want people to be able to collaborate on your
483             modules easily.
484              
485             =head2 install_bin
486              
487             Default is 1.
488              
489             All files in a C directory will be installed. It will call the
490             C plugin for you. Set this option to 0 to disable it.
491              
492             =head2 install_share
493              
494             Default is 1.
495              
496             All files in a C directory will be installed. It will call the
497             C plugin for you. Set this option to 0 to disable it.
498              
499             =head2 manifest_skip
500              
501             Default is 1.
502              
503             This option will generate a sane MANIFEST.SKIP for you and delete it again
504             when you run C. You can add your own skips in the file called
505             C. You almost certainly want this option on. Set to 0 if
506             you are weird.
507              
508             =head2 requires_from
509              
510             Default is 1.
511              
512             This option will attempt to find all the requirements from the primary module.
513             If you make any of your own requires or requires_from calls, this option will
514             do nothing.