File Coverage

blib/lib/Module/Starter/Simple.pm
Criterion Covered Total %
statement 374 408 91.6
branch 55 102 53.9
condition 12 25 48.0
subroutine 51 59 86.4
pod 35 35 100.0
total 527 629 83.7


line stmt bran cond sub pod time code
1             package Module::Starter::Simple;
2              
3 2     2   74600 use 5.006;
  2         17  
4 2     2   11 use strict;
  2         3  
  2         55  
5 2     2   10 use warnings;
  2         6  
  2         76  
6              
7 2     2   13 use Cwd 'cwd';
  2         3  
  2         168  
8 2     2   13 use File::Path qw( make_path remove_tree );
  2         3  
  2         175  
9 2     2   14 use File::Spec ();
  2         4  
  2         36  
10 2     2   10 use Carp qw( carp confess croak );
  2         3  
  2         126  
11 2     2   629 use Module::Runtime qw( require_module );
  2         1875  
  2         11  
12              
13 2     2   1023 use Module::Starter::BuilderSet;
  2         6  
  2         11620  
14              
15             =head1 NAME
16              
17             Module::Starter::Simple - a simple, comprehensive Module::Starter plugin
18              
19             =head1 VERSION
20              
21             version 1.77
22              
23             =cut
24              
25             our $VERSION = '1.77';
26              
27             =head1 SYNOPSIS
28              
29             use Module::Starter qw(Module::Starter::Simple);
30              
31             Module::Starter->create_distro(%args);
32              
33             =head1 DESCRIPTION
34              
35             Module::Starter::Simple is a plugin for Module::Starter that will perform all
36             the work needed to create a distribution. Given the parameters detailed in
37             L, it will create content, create directories, and populate
38             the directories with the required files.
39              
40             =head1 CLASS METHODS
41              
42             =head2 C<< new(%args) >>
43              
44             This method is called to construct and initialize a new Module::Starter object.
45             It is never called by the end user, only internally by C, which
46             creates ephemeral Module::Starter objects. It's documented only to call it to
47             the attention of subclass authors.
48              
49             =cut
50              
51             sub new {
52 44     44 1 130 my $class = shift;
53 44         402 return bless { @_ } => $class;
54             }
55              
56             =head1 OBJECT METHODS
57              
58             All the methods documented below are object methods, meant to be called
59             internally by the ephemeral objects created during the execution of the class
60             method C above.
61              
62             =head2 postprocess_config
63              
64             A hook to do any work after the configuration is initially processed.
65              
66             =cut
67              
68 0     0 1 0 sub postprocess_config { 1 };
69              
70             =head2 pre_create_distro
71              
72             A hook to do any work right before the distro is created.
73              
74             =cut
75              
76 0     0 1 0 sub pre_create_distro { 1 };
77              
78             =head2 C<< create_distro(%args) >>
79              
80             This method works as advertised in L.
81              
82             =cut
83              
84             sub create_distro {
85 44     44 1 25678855 my $either = shift;
86              
87 44 50       361 ( ref $either ) or $either = $either->new( @_ );
88              
89 44         133 my $self = $either;
90 44   50     215 my $modules = $self->{modules} || [];
91 44         117 my @modules = map { split /,/ } @{$modules};
  520         1118  
  44         118  
92 44 50       209 croak "No modules specified.\n" unless @modules;
93 44         150 for (@modules) {
94 520 50       1950 croak "Invalid module name: $_" unless /\A[a-z_]\w*(?:::[\w]+)*\Z/i;
95             }
96              
97 44 50 33     270 if ( ( not $self->{author} ) && ( $^O ne 'MSWin32' ) ) {
98 0         0 ( $self->{author} ) = split /,/, ( getpwuid $> )[6];
99             }
100              
101 44 0 33     185 if ( not $self->{email} and exists $ENV{EMAIL} ) {
102 0         0 $self->{email} = $ENV{EMAIL};
103             }
104              
105 44 50       158 croak "Must specify an author\n" unless $self->{author};
106 44 50       136 croak "Must specify an email address\n" unless $self->{email};
107 44         291 ($self->{email_obfuscated} = $self->{email}) =~ s/@/ at /;
108              
109 44   50     158 $self->{license} ||= 'artistic2';
110 44   100     214 $self->{minperl} ||= '5.006';
111 44   100     163 $self->{ignores_type} ||= ['generic'];
112 44         98 $self->{manifest_skip} = !! grep { /manifest/ } @{ $self->{ignores_type} };
  170         463  
  44         155  
113            
114 44         273 $self->{license_record} = $self->_license_record();
115              
116 44         523 $self->{main_module} = $modules[0];
117 44 50 33     428 if ( not defined $self->{distro} or not length $self->{distro} ) {
118 0         0 $self->{distro} = $self->{main_module};
119 0         0 $self->{distro} =~ s/::/-/g;
120             }
121              
122 44   33     246 $self->{basedir} = $self->{dir} || $self->{distro};
123 44         223 $self->create_basedir;
124              
125 44         97 my @files;
126 44         276 push @files, $self->create_modules( @modules );
127              
128 44         284 push @files, $self->create_t( @modules );
129 44         247 push @files, $self->create_ignores;
130 44         200 my %build_results = $self->create_build();
131 44         106 push(@files, @{ $build_results{files} } );
  44         126  
132              
133 44         205 push @files, $self->create_Changes;
134 44         242 push @files, $self->create_README( $build_results{instructions} );
135 44 50       367 push @files, $self->create_LICENSE if $self->{genlicense};
136              
137 44 100       214 $self->create_MANIFEST( $build_results{'manifest_method'} ) unless ( $self->{manifest_skip} );
138             # TODO: put files to ignore in a more standard form?
139             # XXX: no need to return the files created
140              
141 44         1116 return;
142             }
143              
144             =head2 post_create_distro
145              
146             A hook to do any work after creating the distribution.
147              
148             =cut
149              
150 0     0 1 0 sub post_create_distro { 1 };
151              
152             =head2 pre_exit
153              
154             A hook to do any work right before exit time.
155              
156             =cut
157              
158             sub pre_exit {
159 0     0 1 0 print "Created starter directories and files\n";
160             }
161              
162             =head2 create_basedir
163              
164             Creates the base directory for the distribution. If the directory already
165             exists, and I<$force> is true, then the existing directory will get erased.
166              
167             If the directory can't be created, or re-created, it dies.
168              
169             =cut
170              
171             sub create_basedir {
172 44     44 1 101 my $self = shift;
173              
174             # Make sure there's no directory
175 44 100       1476 if ( -e $self->{basedir} ) {
176             die( "$self->{basedir} already exists. ".
177             "Use --force if you want to stomp on it.\n"
178 21 50       200 ) unless $self->{force};
179              
180 21         139952 remove_tree $self->{basedir};
181              
182             die "Couldn't delete existing $self->{basedir}: $!\n"
183 21 50       606 if -e $self->{basedir};
184             }
185              
186             CREATE_IT: {
187 44         149 $self->progress( "Created $self->{basedir}" );
  44         428  
188              
189 44         10085 make_path $self->{basedir};
190              
191 44 50       960 die "Couldn't create $self->{basedir}: $!\n" unless -d $self->{basedir};
192             }
193              
194 44         222 return;
195             }
196              
197             =head2 create_modules( @modules )
198              
199             This method will create a starter module file for each module named in
200             I<@modules>.
201              
202             =cut
203              
204             sub create_modules {
205 44     44 1 136 my $self = shift;
206 44         245 my @modules = @_;
207              
208 44         81 my @files;
209              
210 44         136 for my $module ( @modules ) {
211 520         1349 my $rtname = lc $module;
212 520         2538 $rtname =~ s/::/-/g;
213 520         1546 push @files, $self->_create_module( $module, $rtname );
214             }
215              
216 44         337 return @files;
217             }
218              
219             =head2 module_guts( $module, $rtname )
220              
221             This method returns the text which should serve as the contents for the named
222             module. I<$rtname> is the email suffix which rt.cpan.org will use for bug
223             reports. (This should, and will, be moved out of the parameters for this
224             method eventually.)
225              
226             =cut
227              
228             our $LICENSES = {
229             perl => 'Perl_5',
230             artistic => 'Artistic_1_0',
231             artistic2 => 'Artistic_2_0',
232             mozilla => 'Mozilla_1_1',
233             mozilla2 => 'Mozilla_2_0',
234             bsd => 'BSD',
235             freebsd => 'FreeBSD',
236             cc0 => 'CC0_1_0',
237             gpl => 'GPL_2',
238             lgpl => 'LGPL_2_1',
239             gpl3 => 'GPL_3',
240             lgpl3 => 'LGPL_3_0',
241             agpl3 => 'AGPL_3',
242             apache => 'Apache_2_0',
243             qpl => 'QPL_1_0',
244             };
245              
246             sub _license_record {
247 44     44   92 my $self = shift;
248 44         213 my $key = $LICENSES->{ $self->{license} };
249 44 50       133 $key = $self->{license} unless defined $key;
250 44 50       248 my $class = $key =~ m/::/ ? $key : "Software::License::$key";
251             {
252 44         99 local $@;
  44         107  
253 44 50 33     104 undef $class unless eval { require_module $class; 1 } and $class->can('new');
  44         265  
  44         47542  
254             }
255 44 50       208 unless (defined $class) {
256 0         0 require Software::LicenseUtils;
257 0         0 ($class) = Software::LicenseUtils->guess_license_from_meta_key($key);
258 0 0       0 return undef unless defined $class;
259             }
260 44         365 return $class->new( { holder => $self->{author} } );
261             }
262              
263             sub _license_blurb {
264 564     564   852 my $self = shift;
265              
266 564         971 my $record = $self->{license_record};
267 564 50       2493 my $license_blurb = defined($record) ?
268             $record->notice :
269             <<"EOT";
270 0         0 This software is Copyright (c) @{[ $self->_thisyear ]} by $self->{author}.
271              
272             This program is released under the following license:
273              
274             $self->{license}
275             EOT
276              
277 564         694171 chomp $license_blurb;
278 564         1636 return $license_blurb;
279             }
280              
281             # _create_module: used by create_modules to build each file and put data in it
282              
283             sub _create_module {
284 520     520   765 my $self = shift;
285 520         833 my $module = shift;
286 520         809 my $rtname = shift;
287              
288 520         2026 my @parts = split( /::/, $module );
289 520         1133 my $filepart = (pop @parts) . '.pm';
290 520         1658 my @dirparts = ( $self->{basedir}, 'lib', @parts );
291 520         827 my $SLASH = q{/};
292 520         1710 my $manifest_file = join( $SLASH, 'lib', @parts, $filepart );
293 520 50       1235 if ( @dirparts ) {
294 520         5076 my $dir = File::Spec->catdir( @dirparts );
295 520 100       11983 if ( not -d $dir ) {
296 417         121112 make_path $dir;
297 417         3032 $self->progress( "Created $dir" );
298             }
299             }
300              
301 520         6204 my $module_file = File::Spec->catfile( @dirparts, $filepart );
302              
303 520         4424 $self->{module_file}{$module} = File::Spec->catfile('lib', @parts, $filepart);
304 520         1839 $self->create_file( $module_file, $self->module_guts( $module, $rtname ) );
305 520         3233 $self->progress( "Created $module_file" );
306              
307 520         2608 return $manifest_file;
308             }
309              
310             sub _thisyear {
311 0     0   0 return (localtime())[5] + 1900;
312             }
313              
314             sub _module_to_pm_file {
315 564     564   861 my $self = shift;
316 564         737 my $module = shift;
317              
318 564         1444 my @parts = split( /::/, $module );
319 564         981 my $pm = pop @parts;
320 564         3534 my $pm_file = File::Spec->catfile( 'lib', @parts, "${pm}.pm" );
321 564         1383 $pm_file =~ s{\\}{/}g; # even on Win32, use forward slash
322              
323 564         1928 return $pm_file;
324             }
325              
326             sub _reference_links {
327             return (
328 564     564   3427 { nickname => 'RT',
329             title => 'CPAN\'s request tracker (report bugs here)',
330             link => 'https://rt.cpan.org/NoAuth/Bugs.html?Dist=%s',
331             },
332             { title => 'CPAN Ratings',
333             link => 'https://cpanratings.perl.org/d/%s',
334             },
335             { title => 'Search CPAN',
336             link => 'https://metacpan.org/release/%s',
337             },
338             );
339             }
340              
341             =head2 create_Makefile_PL( $main_module )
342              
343             This will create the Makefile.PL for the distribution, and will use the module
344             named in I<$main_module> as the main module of the distribution.
345              
346             =cut
347              
348             sub create_Makefile_PL {
349 18     18 1 61 my $self = shift;
350 18         46 my $main_module = shift;
351 18         43 my $builder_name = 'ExtUtils::MakeMaker';
352 18         57 my $output_file =
353             Module::Starter::BuilderSet->new()->file_for_builder($builder_name);
354 18         288 my $fname = File::Spec->catfile( $self->{basedir}, $output_file );
355              
356 18         86 $self->create_file(
357             $fname,
358             $self->Makefile_PL_guts(
359             $main_module,
360             $self->_module_to_pm_file($main_module),
361             ),
362             );
363              
364 18         153 $self->progress( "Created $fname" );
365              
366 18         42 return $output_file;
367             }
368              
369             =head2 create_MI_Makefile_PL( $main_module )
370              
371             This will create a Module::Install Makefile.PL for the distribution, and will
372             use the module named in I<$main_module> as the main module of the distribution.
373              
374             =cut
375              
376             sub create_MI_Makefile_PL {
377 0     0 1 0 my $self = shift;
378 0         0 my $main_module = shift;
379 0         0 my $builder_name = 'Module::Install';
380 0         0 my $output_file =
381             Module::Starter::BuilderSet->new()->file_for_builder($builder_name);
382 0         0 my $fname = File::Spec->catfile( $self->{basedir}, $output_file );
383              
384 0         0 $self->create_file(
385             $fname,
386             $self->MI_Makefile_PL_guts(
387             $main_module,
388             $self->_module_to_pm_file($main_module),
389             ),
390             );
391              
392 0         0 $self->progress( "Created $fname" );
393              
394 0         0 return $output_file;
395             }
396              
397             =head2 Makefile_PL_guts( $main_module, $main_pm_file )
398              
399             This method is called by create_Makefile_PL and returns text used to populate
400             Makefile.PL; I<$main_pm_file> is the filename of the distribution's main
401             module, I<$main_module>.
402              
403             =cut
404              
405             sub Makefile_PL_guts {
406 18     18 1 53 my $self = shift;
407 18         37 my $main_module = shift;
408 18         32 my $main_pm_file = shift;
409              
410 18         96 (my $author = "$self->{author} <$self->{email}>") =~ s/'/\'/g;
411            
412 18 50       107 my $slname = $self->{license_record} ? $self->{license_record}->meta2_name : $self->{license};
413              
414 18 50       150 my $warnings = sprintf 'warnings%s;', ($self->{fatalize} ? " FATAL => 'all'" : '');
415              
416 18         269 return <<"HERE";
417             use $self->{minperl};
418             use strict;
419             use $warnings
420             use ExtUtils::MakeMaker;
421              
422             my %WriteMakefileArgs = (
423             NAME => '$main_module',
424             AUTHOR => q{$author},
425             VERSION_FROM => '$main_pm_file',
426             ABSTRACT_FROM => '$main_pm_file',
427             LICENSE => '$slname',
428             MIN_PERL_VERSION => '$self->{minperl}',
429             CONFIGURE_REQUIRES => {
430             'ExtUtils::MakeMaker' => '0',
431             },
432             TEST_REQUIRES => {
433             'Test::More' => '0',
434             },
435             PREREQ_PM => {
436             #'ABC' => '1.6',
437             #'Foo::Bar::Module' => '5.0401',
438             },
439             dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
440             clean => { FILES => '$self->{distro}-*' },
441             );
442              
443             # Compatibility with old versions of ExtUtils::MakeMaker
444             unless (eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 }) {
445             my \$test_requires = delete \$WriteMakefileArgs{TEST_REQUIRES} || {};
446             \@{\$WriteMakefileArgs{PREREQ_PM}}{keys %\$test_requires} = values %\$test_requires;
447             }
448              
449             unless (eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 }) {
450             my \$build_requires = delete \$WriteMakefileArgs{BUILD_REQUIRES} || {};
451             \@{\$WriteMakefileArgs{PREREQ_PM}}{keys %\$build_requires} = values %\$build_requires;
452             }
453              
454             delete \$WriteMakefileArgs{CONFIGURE_REQUIRES}
455             unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
456             delete \$WriteMakefileArgs{MIN_PERL_VERSION}
457             unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
458             delete \$WriteMakefileArgs{LICENSE}
459             unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };
460              
461             WriteMakefile(%WriteMakefileArgs);
462             HERE
463              
464             }
465              
466             =head2 MI_Makefile_PL_guts( $main_module, $main_pm_file )
467              
468             This method is called by create_MI_Makefile_PL and returns text used to populate
469             Makefile.PL; I<$main_pm_file> is the filename of the distribution's main
470             module, I<$main_module>.
471              
472             =cut
473              
474             sub MI_Makefile_PL_guts {
475 0     0 1 0 my $self = shift;
476 0         0 my $main_module = shift;
477 0         0 my $main_pm_file = shift;
478              
479 0         0 my $author = "$self->{author} <$self->{email}>";
480 0         0 $author =~ s/'/\'/g;
481            
482 0 0       0 my $license_url = $self->{license_record} ? $self->{license_record}->url : '';
483              
484 0 0       0 my $warnings = sprintf 'warnings%s;', ($self->{fatalize} ? " FATAL => 'all'" : '');
485              
486 0         0 return <<"HERE";
487             use $self->{minperl};
488             use strict;
489             use $warnings
490             use inc::Module::Install;
491              
492             name '$self->{distro}';
493             all_from '$main_pm_file';
494             author q{$author};
495             license '$self->{license}';
496              
497             perl_version '$self->{minperl}';
498              
499             tests_recursive('t');
500              
501             resources (
502             #homepage => 'http://yourwebsitehere.com',
503             #IRC => 'irc://irc.perl.org/#$self->{distro}',
504             license => '$license_url',
505             #repository => 'git://github.com/$self->{author}/$self->{distro}.git',
506             #repository => 'https://bitbucket.org/$self->{author}/$self->{distro}',
507             bugtracker => 'https://rt.cpan.org/NoAuth/Bugs.html?Dist=$self->{distro}',
508             );
509              
510             configure_requires (
511             'Module::Install' => '0',
512             );
513              
514             test_requires (
515             'Test::More' => '0',
516             );
517              
518             requires (
519             #'ABC' => '1.6',
520             #'Foo::Bar::Module' => '5.0401',
521             );
522              
523             install_as_cpan;
524             auto_install;
525             WriteAll;
526             HERE
527              
528             }
529              
530             =head2 create_Build_PL( $main_module )
531              
532             This will create the Build.PL for the distribution, and will use the module
533             named in I<$main_module> as the main module of the distribution.
534              
535             =cut
536              
537             sub create_Build_PL {
538 26     26 1 59 my $self = shift;
539 26         43 my $main_module = shift;
540 26         59 my $builder_name = 'Module::Build';
541 26         103 my $output_file =
542             Module::Starter::BuilderSet->new()->file_for_builder($builder_name);
543 26         426 my $fname = File::Spec->catfile( $self->{basedir}, $output_file );
544              
545 26         185 $self->create_file(
546             $fname,
547             $self->Build_PL_guts(
548             $main_module,
549             $self->_module_to_pm_file($main_module),
550             ),
551             );
552              
553 26         227 $self->progress( "Created $fname" );
554              
555 26         56 return $output_file;
556             }
557              
558             =head2 Build_PL_guts( $main_module, $main_pm_file )
559              
560             This method is called by create_Build_PL and returns text used to populate
561             Build.PL; I<$main_pm_file> is the filename of the distribution's main module,
562             I<$main_module>.
563              
564             =cut
565              
566             sub Build_PL_guts {
567 26     26 1 72 my $self = shift;
568 26         53 my $main_module = shift;
569 26         44 my $main_pm_file = shift;
570              
571 26         141 (my $author = "$self->{author} <$self->{email}>") =~ s/'/\'/g;
572              
573 26 50       176 my $slname = $self->{license_record} ? $self->{license_record}->meta2_name : $self->{license};
574            
575 26 50       226 my $warnings = sprintf 'warnings%s;', ($self->{fatalize} ? " FATAL => 'all'" : '');
576              
577 26         335 return <<"HERE";
578             use $self->{minperl};
579             use strict;
580             use $warnings
581             use Module::Build;
582             Module::Build->VERSION('0.4004');
583              
584             my \$builder = Module::Build->new(
585             module_name => '$main_module',
586             license => '$slname',
587             dist_author => q{$author},
588             dist_version_from => '$main_pm_file',
589             release_status => 'stable',
590             configure_requires => {
591             'Module::Build' => '0.4004',
592             },
593             test_requires => {
594             'Test::More' => '0',
595             },
596             requires => {
597             #'ABC' => '1.6',
598             #'Foo::Bar::Module' => '5.0401',
599             },
600             add_to_cleanup => [ '$self->{distro}-*' ],
601             );
602              
603             \$builder->create_build_script();
604             HERE
605              
606             }
607              
608             =head2 create_Changes( )
609              
610             This method creates a skeletal Changes file.
611              
612             =cut
613              
614             sub create_Changes {
615 44     44 1 79 my $self = shift;
616              
617 44         542 my $fname = File::Spec->catfile( $self->{basedir}, 'Changes' );
618 44         241 $self->create_file( $fname, $self->Changes_guts() );
619 44         353 $self->progress( "Created $fname" );
620              
621 44         154 return 'Changes';
622             }
623              
624             =head2 Changes_guts
625              
626             Called by create_Changes, this method returns content for the Changes file.
627              
628             =cut
629              
630             sub Changes_guts {
631 44     44 1 84 my $self = shift;
632              
633 44         221 return <<"HERE";
634             Revision history for $self->{distro}
635              
636             0.01 Date/time
637             First version, released on an unsuspecting world.
638              
639             HERE
640             }
641              
642             =head2 create_LICENSE
643              
644             This method creates the distribution's LICENSE file.
645              
646             =cut
647              
648             sub create_LICENSE {
649 44     44 1 83 my $self = shift;
650            
651 44   50     195 my $record = $self->{license_record} || return ();
652 44         640 my $fname = File::Spec->catfile( $self->{basedir}, 'LICENSE' );
653 44         339 $self->create_file( $fname, $record->license );
654 44         501 $self->progress( "Created $fname" );
655            
656 44         147 return 'LICENSE';
657             }
658              
659             =head2 create_README( $build_instructions )
660              
661             This method creates the distribution's README file.
662              
663             =cut
664              
665             sub create_README {
666 44     44 1 86 my $self = shift;
667 44         99 my $build_instructions = shift;
668              
669 44         542 my $fname = File::Spec->catfile( $self->{basedir}, 'README' );
670 44         249 $self->create_file( $fname, $self->README_guts($build_instructions) );
671 44         357 $self->progress( "Created $fname" );
672              
673 44         121 return 'README';
674             }
675              
676             =head2 README_guts
677              
678             Called by create_README, this method returns content for the README file.
679              
680             =cut
681              
682             sub _README_intro {
683 44     44   69 my $self = shift;
684              
685 44         120 return <<"HERE";
686             The README is used to introduce the module and provide instructions on
687             how to install the module, any machine dependencies it may have (for
688             example C compilers and installed libraries) and any other information
689             that should be provided before the module is installed.
690              
691             A README file is required for CPAN modules since CPAN extracts the README
692             file from a module distribution so that people browsing the archive
693             can use it to get an idea of the module's uses. It is usually a good idea
694             to provide version information here so that people can decide whether
695             fixes for the module are worth downloading.
696             HERE
697             }
698              
699             sub _README_information {
700 44     44   83 my $self = shift;
701              
702 44         92 my @reference_links = _reference_links();
703              
704 44         125 my $content = "You can also look for information at:\n";
705              
706 44         170 foreach my $ref (@reference_links){
707 132         185 my $title;
708 132 100       328 $title = "$ref->{nickname}, " if exists $ref->{nickname};
709 132         213 $title .= $ref->{title};
710 132         445 my $link = sprintf($ref->{link}, $self->{distro});
711              
712 132         499 $content .= qq[
713             $title
714             $link
715             ];
716             }
717              
718 44         201 return $content;
719             }
720              
721             sub _README_license {
722 44     44   83 my $self = shift;
723              
724 44         124 my $license_blurb = $self->_license_blurb();
725              
726 44         298 return <<"HERE";
727             LICENSE AND COPYRIGHT
728              
729             $license_blurb
730             HERE
731             }
732              
733             sub README_guts {
734 44     44 1 93 my $self = shift;
735 44         72 my $build_instructions = shift;
736              
737 44         121 my $intro = $self->_README_intro();
738 44         173 my $information = $self->_README_information();
739 44         228 my $license = $self->_README_license();
740              
741 44         628 return <<"HERE";
742             $self->{distro}
743              
744             $intro
745              
746             INSTALLATION
747              
748             $build_instructions
749              
750             SUPPORT AND DOCUMENTATION
751              
752             After installing, you can find documentation for this module with the
753             perldoc command.
754              
755             perldoc $self->{main_module}
756              
757             $information
758              
759             $license
760             HERE
761             }
762              
763             =head2 create_t( @modules )
764              
765             This method creates a bunch of *.t files. I<@modules> is a list of all modules
766             in the distribution.
767              
768             =cut
769              
770             sub create_t {
771 44     44 1 116 my $self = shift;
772 44         202 my @modules = @_;
773              
774 44         188 my %t_files = $self->t_guts(@modules);
775 44         229 my %xt_files = $self->xt_guts(@modules);
776              
777 44         107 my @files;
778 44         142 push @files, map { $self->_create_t('t', $_, $t_files{$_}) } keys %t_files;
  176         496  
779 44         258 push @files, map { $self->_create_t('xt', $_, $xt_files{$_}) } keys %xt_files;
  44         181  
780              
781 44         329 return @files;
782             }
783              
784             =head2 t_guts( @modules )
785              
786             This method is called by create_t, and returns a description of the *.t files
787             to be created.
788              
789             The return value is a hash of test files to create. Each key is a filename and
790             each value is the contents of that file.
791              
792             =cut
793              
794             sub t_guts {
795 44     44 1 99 my $self = shift;
796 44         151 my @modules = @_;
797              
798 44         85 my %t_files;
799 44         111 my $minperl = $self->{minperl};
800 44 50       280 my $warnings = sprintf 'warnings%s;', ($self->{fatalize} ? " FATAL => 'all'" : '');
801              
802 44         241 my $header = <<"EOH";
803             #!perl
804             use $minperl;
805             use strict;
806             use $warnings
807             use Test::More;
808              
809             EOH
810            
811 44         196 $t_files{'pod.t'} = $header.<<'HERE';
812             unless ( $ENV{RELEASE_TESTING} ) {
813             plan( skip_all => "Author tests not required for installation" );
814             }
815              
816             # Ensure a recent version of Test::Pod
817             my $min_tp = 1.22;
818             eval "use Test::Pod $min_tp";
819             plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
820              
821             all_pod_files_ok();
822             HERE
823              
824 44         150 $t_files{'manifest.t'} = $header.<<'HERE';
825             unless ( $ENV{RELEASE_TESTING} ) {
826             plan( skip_all => "Author tests not required for installation" );
827             }
828              
829             my $min_tcm = 0.9;
830             eval "use Test::CheckManifest $min_tcm";
831             plan skip_all => "Test::CheckManifest $min_tcm required" if $@;
832              
833             ok_manifest();
834             HERE
835              
836 44         155 $t_files{'pod-coverage.t'} = $header.<<'HERE';
837             unless ( $ENV{RELEASE_TESTING} ) {
838             plan( skip_all => "Author tests not required for installation" );
839             }
840              
841             # Ensure a recent version of Test::Pod::Coverage
842             my $min_tpc = 1.08;
843             eval "use Test::Pod::Coverage $min_tpc";
844             plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage"
845             if $@;
846              
847             # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
848             # but older versions don't recognize some common documentation styles
849             my $min_pc = 0.18;
850             eval "use Pod::Coverage $min_pc";
851             plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
852             if $@;
853              
854             all_pod_coverage_ok();
855             HERE
856              
857 44         81 my $nmodules = @modules;
858 44         93 my $main_module = $modules[0];
859             my $use_lines = join(
860 44         137 "\n", map { qq{ use_ok( '$_' ) || print "Bail out!\\n";} } @modules
  520         1374  
861             );
862              
863 44         365 $t_files{'00-load.t'} = $header.<<"HERE";
864             plan tests => $nmodules;
865              
866             BEGIN {
867             $use_lines
868             }
869              
870             diag( "Testing $main_module \$${main_module}::VERSION, Perl \$], \$^X" );
871             HERE
872              
873 44         346 return %t_files;
874             }
875              
876             =head2 xt_guts( @modules )
877              
878             This method is called by create_t, and returns a description of the author
879             only *.t files to be created in the xt directory.
880              
881             The return value is a hash of test files to create. Each key is a filename and
882             each value is the contents of that file.
883              
884             =cut
885              
886             sub xt_guts {
887 44     44 1 142 my $self = shift;
888 44         150 my @modules = @_;
889              
890 44         70 my %xt_files;
891 44         124 my $minperl = $self->{minperl};
892 44 50       232 my $warnings = sprintf 'warnings%s;', ($self->{fatalize} ? " FATAL => 'all'" : '');
893              
894 44         193 my $header = <<"EOH";
895             #!perl
896             use $minperl;
897             use strict;
898             use $warnings
899             use Test::More;
900              
901             EOH
902              
903 44         108 my $module_boilerplate_tests;
904             $module_boilerplate_tests .=
905 44         237 " module_boilerplate_ok('".$self->_module_to_pm_file($_)."');\n" for @modules;
906              
907 44         134 my $boilerplate_tests = @modules + 2;
908 44         283 $xt_files{'boilerplate.t'} = $header.<<"HERE";
909             plan tests => $boilerplate_tests;
910              
911             sub not_in_file_ok {
912             my (\$filename, \%regex) = \@_;
913             open( my \$fh, '<', \$filename )
914             or die "couldn't open \$filename for reading: \$!";
915              
916             my \%violated;
917              
918             while (my \$line = <\$fh>) {
919             while (my (\$desc, \$regex) = each \%regex) {
920             if (\$line =~ \$regex) {
921             push \@{\$violated{\$desc}||=[]}, \$.;
922             }
923             }
924             }
925              
926             if (\%violated) {
927             fail("\$filename contains boilerplate text");
928             diag "\$_ appears on lines \@{\$violated{\$_}}" for keys \%violated;
929             } else {
930             pass("\$filename contains no boilerplate text");
931             }
932             }
933              
934             sub module_boilerplate_ok {
935             my (\$module) = \@_;
936             not_in_file_ok(\$module =>
937             'the great new \$MODULENAME' => qr/ - The great new /,
938             'boilerplate description' => qr/Quick summary of what the module/,
939             'stub function definition' => qr/function[12]/,
940             );
941             }
942              
943             TODO: {
944             local \$TODO = "Need to replace the boilerplate text";
945              
946             not_in_file_ok(README =>
947             "The README is used..." => qr/The README is used/,
948             "'version information here'" => qr/to provide version information/,
949             );
950              
951             not_in_file_ok(Changes =>
952             "placeholder date/time" => qr(Date/time)
953             );
954              
955             $module_boilerplate_tests
956              
957             }
958              
959             HERE
960              
961 44         238 return %xt_files;
962             }
963              
964             sub _create_t {
965 220     220   389 my $self = shift;
966 220         314 my $directory = shift; # 't' or 'xt'
967 220         295 my $filename = shift;
968 220         340 my $content = shift;
969              
970 220         559 my @dirparts = ( $self->{basedir}, $directory );
971 220         1720 my $tdir = File::Spec->catdir( @dirparts );
972 220 100       4421 if ( not -d $tdir ) {
973 88         11494 make_path $tdir;
974 88         684 $self->progress( "Created $tdir" );
975             }
976              
977 220         2345 my $fname = File::Spec->catfile( @dirparts, $filename );
978 220         846 $self->create_file( $fname, $content );
979 220         1261 $self->progress( "Created $fname" );
980              
981 220         1179 return join('/', $directory, $filename );
982             }
983              
984             =head2 create_MB_MANIFEST
985              
986             This methods creates a MANIFEST file using Module::Build's methods.
987              
988             =cut
989              
990             sub create_MB_MANIFEST {
991 2     2 1 6 my $self = shift;
992 2         9 $self->create_EUMM_MANIFEST;
993             }
994              
995             =head2 create_MI_MANIFEST
996              
997             This method creates a MANIFEST file using Module::Install's methods.
998              
999             Currently runs ExtUtils::MakeMaker's methods.
1000              
1001             =cut
1002              
1003             sub create_MI_MANIFEST {
1004 0     0 1 0 my $self = shift;
1005 0         0 $self->create_EUMM_MANIFEST;
1006             }
1007              
1008             =head2 create_EUMM_MANIFEST
1009              
1010             This method creates a MANIFEST file using ExtUtils::MakeMaker's methods.
1011              
1012             =cut
1013              
1014             sub create_EUMM_MANIFEST {
1015 2     2 1 4 my $self = shift;
1016 2         6365 my $orig_dir = cwd();
1017              
1018             # create the MANIFEST in the correct path
1019 2 50       84 chdir $self->{'basedir'} || die "Can't reach basedir: $!\n";
1020              
1021 2         1125 require ExtUtils::Manifest;
1022 2         10002 $ExtUtils::Manifest::Quiet = 0;
1023 2         36 ExtUtils::Manifest::mkmanifest();
1024              
1025             # return to our original path, wherever it was
1026 2 50       9193 chdir $orig_dir || die "Can't return to original dir: $!\n";
1027             }
1028              
1029             =head2 create_MANIFEST( $method )
1030              
1031             This method creates the distribution's MANIFEST file. It must be run last,
1032             because all the other create_* functions have been returning the functions they
1033             create.
1034              
1035             It receives a method to run in order to create the MANIFEST file. That way it
1036             can create a MANIFEST file according to the builder used.
1037              
1038             =cut
1039              
1040             sub create_MANIFEST {
1041 2     2 1 7 my ( $self, $manifest_method ) = @_;
1042 2         28 my $fname = File::Spec->catfile( $self->{basedir}, 'MANIFEST' );
1043              
1044 2         14 $self->$manifest_method();
1045 2         66 $self->filter_lines_in_file(
1046             $fname,
1047             qr/^xt\/boilerplate\.t$/,
1048             qr/^ignore\.txt$/,
1049             );
1050              
1051 2         34 $self->progress( "Created $fname" );
1052              
1053 2         13 return 'MANIFEST';
1054             }
1055              
1056             =head2 get_builders( )
1057              
1058             This methods gets the correct builder(s).
1059              
1060             It is called by C, and returns an arrayref with the builders.
1061              
1062             =cut
1063              
1064             sub get_builders {
1065 44     44 1 80 my $self = shift;
1066              
1067             # pass one: pull the builders out of $self->{builder}
1068             my @tmp =
1069 0         0 ref $self->{'builder'} eq 'ARRAY' ? @{ $self->{'builder'} }
1070 44 50       264 : $self->{'builder'};
1071              
1072 44         86 my @builders;
1073 44         86 my $COMMA = q{,};
1074             # pass two: expand comma-delimited builder lists
1075 44         533 foreach my $builder (@tmp) {
1076 44         1068 push( @builders, split( $COMMA, $builder ) );
1077             }
1078              
1079 44         232 return \@builders;
1080             }
1081              
1082             =head2 create_build( )
1083              
1084             This method creates the build file(s) and puts together some build
1085             instructions. The builders currently supported are:
1086              
1087             ExtUtils::MakeMaker
1088             Module::Build
1089             Module::Install
1090              
1091             =cut
1092              
1093             sub create_build {
1094 44     44 1 111 my $self = shift;
1095              
1096             # get the builders
1097 44         111 my @builders = @{ $self->get_builders };
  44         157  
1098 44         469 my $builder_set = Module::Starter::BuilderSet->new();
1099              
1100             # Remove mutually exclusive and unsupported builders
1101 44         285 @builders = $builder_set->check_compatibility( @builders );
1102              
1103             # compile some build instructions, create a list of files generated
1104             # by the builders' create_* methods, and call said methods
1105              
1106 44         257 my @build_instructions;
1107             my @files;
1108 44         0 my $manifest_method;
1109              
1110 44         138 foreach my $builder ( @builders ) {
1111 44 50       145 if ( !@build_instructions ) {
1112 44         119 push( @build_instructions,
1113             'To install this module, run the following commands:'
1114             );
1115             }
1116             else {
1117 0         0 push( @build_instructions,
1118             "Alternatively, to install with $builder, you can ".
1119             "use the following commands:"
1120             );
1121             }
1122 44         136 push( @files, $builder_set->file_for_builder($builder) );
1123 44         177 my @commands = $builder_set->instructions_for_builder($builder);
1124 44         170 push( @build_instructions, join("\n", map { "\t$_" } @commands) );
  176         478  
1125              
1126 44         202 my $build_method = $builder_set->method_for_builder($builder);
1127 44         348 $self->$build_method($self->{main_module});
1128              
1129 44         264 $manifest_method = $builder_set->manifest_method($builder);
1130             }
1131              
1132             return(
1133 44         683 files => [ @files ],
1134             instructions => join( "\n\n", @build_instructions ),
1135             manifest_method => $manifest_method,
1136             );
1137             }
1138              
1139              
1140             =head2 create_ignores()
1141              
1142             This creates a text file for use as MANIFEST.SKIP, .cvsignore,
1143             .gitignore, or whatever you use.
1144              
1145             =cut
1146              
1147             sub create_ignores {
1148 44     44 1 159 my $self = shift;
1149 44         106 my $type = $self->{ignores_type};
1150 44         336 my %names = (
1151             generic => 'ignore.txt',
1152             cvs => '.cvsignore',
1153             git => '.gitignore',
1154             hg => '.hgignore',
1155             manifest => 'MANIFEST.SKIP',
1156             );
1157              
1158             my $create_file = sub {
1159 170     170   301 my $type = shift;
1160 170         328 my $name = $names{$type};
1161 170         1876 my $fname = File::Spec->catfile( $self->{basedir}, $names{$type} );
1162 170         592 $self->create_file( $fname, $self->ignores_guts($type) );
1163 170         996 $self->progress( "Created $fname" );
1164 44         315 };
1165              
1166 44 50       198 if ( ref $type eq 'ARRAY' ) {
    0          
1167 44         76 foreach my $single_type ( @{$type} ) {
  44         126  
1168 170         331 $create_file->($single_type);
1169             }
1170             } elsif ( ! ref $type ) {
1171 0         0 $create_file->($type);
1172             }
1173              
1174 44         339 return; # Not a file that goes in the MANIFEST
1175             }
1176              
1177             =head2 ignores_guts()
1178              
1179             Called by C, this method returns the contents of the
1180             ignore file.
1181              
1182             =cut
1183              
1184             sub ignores_guts {
1185 170     170 1 390 my ($self, $type) = @_;
1186              
1187 170 100       509 my $ms = $self->{manifest_skip} ? "MANIFEST\nMANIFEST.bak\n" : '';
1188 170         842 my $guts = {
1189             generic => $ms.<<"EOF",
1190             Makefile
1191             Makefile.old
1192             Build
1193             Build.bat
1194             META.*
1195             MYMETA.*
1196             .build/
1197             _build/
1198             cover_db/
1199             blib/
1200             inc/
1201             .lwpcookies
1202             .last_cover_stats
1203             nytprof.out
1204             pod2htm*.tmp
1205             pm_to_blib
1206             $self->{distro}-*
1207             $self->{distro}-*.tar.gz
1208             EOF
1209             # make this more restrictive, since MANIFEST tends to be less noticeable
1210             # (also, manifest supports REs.)
1211             manifest => <<'EOF',
1212             # Top-level filter (only include the following...)
1213             ^(?!(?:script|examples|lib|inc|t|xt|maint)/|(?:(?:Makefile|Build)\.PL|README|LICENSE|MANIFEST|Changes|META\.(?:yml|json))$)
1214              
1215             # Avoid version control files.
1216             \bRCS\b
1217             \bCVS\b
1218             ,v$
1219             \B\.svn\b
1220             \b_darcs\b
1221             # (.git or .hg only in top-level, hence it's blocked above)
1222              
1223             # Avoid temp and backup files.
1224             ~$
1225             \.tmp$
1226             \.old$
1227             \.bak$
1228             \..*?\.sw[po]$
1229             \#$
1230             \b\.#
1231              
1232             # avoid OS X finder files
1233             \.DS_Store$
1234              
1235             # ditto for Windows
1236             \bdesktop\.ini$
1237             \b[Tt]humbs\.db$
1238              
1239             # Avoid patch remnants
1240             \.orig$
1241             \.rej$
1242             EOF
1243             };
1244 170         433 $guts->{hg} = $guts->{cvs} = $guts->{git} = $guts->{generic};
1245            
1246 170         670 return $guts->{$type};
1247             }
1248              
1249             =head1 HELPER METHODS
1250              
1251             =head2 verbose
1252              
1253             C tells us whether we're in verbose mode.
1254              
1255             =cut
1256              
1257 1637     1637 1 4974 sub verbose { return shift->{verbose} }
1258              
1259             =head2 create_file( $fname, @content_lines )
1260              
1261             Creates I<$fname>, dumps I<@content_lines> in it, and closes it.
1262             Dies on any error.
1263              
1264             =cut
1265              
1266             sub create_file {
1267 1086     1086 1 277518 my $self = shift;
1268 1086         1637 my $fname = shift;
1269              
1270 1086         2275 my @content = @_;
1271 1086 50       73120 open( my $fh, '>', $fname ) or confess "Can't create $fname: $!\n";
1272 1086         3687 print {$fh} @content;
  1086         12112  
1273 1086 50       33183 close $fh or die "Can't close $fname: $!\n";
1274              
1275 1086         7346 return;
1276             }
1277              
1278             =head2 progress( @list )
1279              
1280             C prints the given progress message if we're in verbose mode.
1281              
1282             =cut
1283              
1284             sub progress {
1285 1637     1637 1 2952 my $self = shift;
1286 1637 50       3233 print @_, "\n" if $self->verbose;
1287              
1288 1637         3544 return;
1289             }
1290              
1291             =head2 filter_lines_in_file( $filename, @compiled_regexes )
1292              
1293             C goes over a file and removes lines with the received
1294             regexes.
1295              
1296             For example, removing t/boilerplate.t in the MANIFEST.
1297              
1298             =cut
1299              
1300             sub filter_lines_in_file {
1301 2     2 1 18 my ( $self, $file, @regexes ) = @_;
1302 2         11 my @read_lines;
1303 2 50       95 open my $fh, '<', $file or die "Can't open file $file: $!\n";
1304 2         190 @read_lines = <$fh>;
1305 2 50       29 close $fh or die "Can't close file $file: $!\n";
1306              
1307 2         9 chomp @read_lines;
1308              
1309 2 50       176 open $fh, '>', $file or die "Can't open file $file: $!\n";
1310 2         22 foreach my $line (@read_lines) {
1311 28         42 my $found;
1312              
1313 28         40 foreach my $regex (@regexes) {
1314 56 100       184 if ( $line =~ $regex ) {
1315 4         12 $found++;
1316             }
1317             }
1318              
1319 28 100       49 $found or print {$fh} "$line\n";
  24         66  
1320             }
1321 2 50       216 close $fh or die "Can't close file $file: $!\n";
1322             }
1323              
1324             =head1 BUGS
1325              
1326             Please report any bugs or feature requests to the bugtracker for this project
1327             on GitHub at: L. I will be
1328             notified, and then you'll automatically be notified of progress on your bug
1329             as I make changes.
1330              
1331             =head1 AUTHOR
1332              
1333             Dan Book, L<< >>
1334              
1335             Sawyer X, C<< >>
1336              
1337             Andy Lester, C<< >>
1338              
1339             C.J. Adams-Collier, C<< >>
1340              
1341             =head1 Copyright & License
1342              
1343             Copyright 2005-2009 Andy Lester and C.J. Adams-Collier, All Rights Reserved.
1344              
1345             Copyright 2010 Sawyer X, All Rights Reserved.
1346              
1347             This program is free software; you can redistribute it and/or modify it
1348             under the same terms as Perl itself.
1349              
1350             Please note that these modules are not products of or supported by the
1351             employers of the various contributors to the code.
1352              
1353             =cut
1354              
1355             sub _module_header {
1356 520     520   842 my $self = shift;
1357 520         770 my $module = shift;
1358 520         723 my $rtname = shift;
1359 520 50       2418 my $warnings = sprintf 'warnings%s;', ($self->{fatalize} ? " FATAL => 'all'" : '');
1360              
1361 520         2657 my $content = <<"HERE";
1362             package $module;
1363              
1364             use $self->{minperl};
1365             use strict;
1366             use $warnings
1367              
1368             \=head1 NAME
1369              
1370             $module - The great new $module!
1371              
1372             \=head1 VERSION
1373              
1374             Version 0.01
1375              
1376             \=cut
1377              
1378             our \$VERSION = '0.01';
1379             HERE
1380 520         1212 return $content;
1381             }
1382              
1383             sub _module_bugs {
1384 520     520   783 my $self = shift;
1385 520         735 my $module = shift;
1386 520         838 my $rtname = shift;
1387              
1388 520         1428 my $bug_email = "bug-\L$self->{distro}\E at rt.cpan.org";
1389 520         955 my $bug_link =
1390             "https://rt.cpan.org/NoAuth/ReportBug.html?Queue=$self->{distro}";
1391              
1392 520         1336 my $content = <<"HERE";
1393             \=head1 BUGS
1394              
1395             Please report any bugs or feature requests to C<$bug_email>, or through
1396             the web interface at L<$bug_link>. I will be notified, and then you'll
1397             automatically be notified of progress on your bug as I make changes.
1398              
1399             HERE
1400              
1401 520         1049 return $content;
1402             }
1403              
1404             sub _module_support {
1405 520     520   824 my $self = shift;
1406 520         753 my $module = shift;
1407 520         765 my $rtname = shift;
1408              
1409 520         1042 my $content = qq[
1410             \=head1 SUPPORT
1411              
1412             You can find documentation for this module with the perldoc command.
1413              
1414             perldoc $module
1415             ];
1416 520         1177 my @reference_links = _reference_links();
1417              
1418 520 50       1328 return undef unless @reference_links;
1419 520         959 $content .= qq[
1420              
1421             You can also look for information at:
1422              
1423             \=over 4
1424             ];
1425              
1426 520         1011 foreach my $ref (@reference_links) {
1427 1560         1930 my $title;
1428 1560         3419 my $link = sprintf($ref->{link}, $self->{distro});
1429              
1430 1560 100       3576 $title = "$ref->{nickname}: " if exists $ref->{nickname};
1431 1560         2216 $title .= $ref->{title};
1432 1560         3482 $content .= qq[
1433             \=item * $title
1434              
1435             L<$link>
1436             ];
1437             }
1438 520         806 $content .= qq[
1439             \=back
1440             ];
1441 520         2095 return $content;
1442             }
1443              
1444             sub _module_license {
1445 520     520   769 my $self = shift;
1446              
1447 520         698 my $module = shift;
1448 520         766 my $rtname = shift;
1449              
1450 520         1200 my $license_blurb = $self->_license_blurb();
1451              
1452 520         1712 my $content = qq[
1453             \=head1 LICENSE AND COPYRIGHT
1454              
1455             $license_blurb
1456             ];
1457              
1458 520         1220 return $content;
1459             }
1460              
1461             sub module_guts {
1462 520     520 1 852 my $self = shift;
1463 520         740 my $module = shift;
1464 520         905 my $rtname = shift;
1465              
1466             # Sub-templates
1467 520         1289 my $header = $self->_module_header($module, $rtname);
1468 520         1273 my $bugs = $self->_module_bugs($module, $rtname);
1469 520         1122 my $support = $self->_module_support($module, $rtname);
1470 520         1326 my $license = $self->_module_license($module, $rtname);
1471              
1472 520         5153 my $content = <<"HERE";
1473             $header
1474              
1475             \=head1 SYNOPSIS
1476              
1477             Quick summary of what the module does.
1478              
1479             Perhaps a little code snippet.
1480              
1481             use $module;
1482              
1483             my \$foo = $module->new();
1484             ...
1485              
1486             \=head1 EXPORT
1487              
1488             A list of functions that can be exported. You can delete this section
1489             if you don't export anything, such as for a purely object-oriented module.
1490              
1491             \=head1 SUBROUTINES/METHODS
1492              
1493             \=head2 function1
1494              
1495             \=cut
1496              
1497             sub function1 {
1498             }
1499              
1500             \=head2 function2
1501              
1502             \=cut
1503              
1504             sub function2 {
1505             }
1506              
1507             \=head1 AUTHOR
1508              
1509             $self->{author}, C<< <$self->{email_obfuscated}> >>
1510              
1511             $bugs
1512              
1513             $support
1514              
1515             \=head1 ACKNOWLEDGEMENTS
1516              
1517             $license
1518              
1519             \=cut
1520              
1521             1; # End of $module
1522             HERE
1523 520         2230 return $content;
1524             }
1525              
1526             1;
1527              
1528             # vi:et:sw=4 ts=4