File Coverage

blib/lib/App/Module/Setup.pm
Criterion Covered Total %
statement 15 93 16.1
branch 0 48 0.0
condition 0 16 0.0
subroutine 5 9 55.5
pod 1 2 50.0
total 21 168 12.5


line stmt bran cond sub pod time code
1             #! perl
2              
3             package App::Module::Setup;
4              
5             ### Please use this module via the command line module-setup tool.
6              
7             our $VERSION = '0.07';
8              
9 1     1   68006 use warnings;
  1         3  
  1         36  
10 1     1   7 use strict;
  1         1  
  1         20  
11 1     1   5 use File::Find;
  1         2  
  1         55  
12 1     1   6 use File::Basename qw( dirname );
  1         2  
  1         68  
13 1     1   7 use File::Path qw( mkpath );
  1         2  
  1         1075  
14              
15             sub main {
16 0     0 1   my $options = shift;
17             # Just in case we're called as a method.
18 0 0         eval { $options->{module} || 1 } or $options = shift;
  0 0          
19              
20 0           my $tpldir = "templates/". $options->{template};
21 0           my $mod = $options->{module};
22              
23             # Replacement variables
24             my $vars =
25             { "module.name" => $mod, # Foo::Bar
26             "module.version" => "0.01",
27             "module.license" => $options->{license} || "perl_5",
28             "current.year" => $options->{year} || 1900 + (localtime)[5],
29             "author.name" => $options->{author} || (getpwuid($<))[6],
30             "author.email" => $options->{email},
31             "author.cpanid" => $options->{cpanid},
32 0   0       "perl.minversion" => $options->{minperl} || '5.008000',
      0        
      0        
      0        
33             };
34              
35 0           my $dir;
36 0 0         if ( $options->{'install-templates'} ) {
37 0           $dir = $tpldir;
38             }
39             else {
40 0           ( $dir = $mod ) =~ s/::/-/g;
41 0           $vars->{"module.distname"} = $dir; # Foo-Bar
42 0           $vars->{"module.distnamelc"} = lc($dir);
43 0           ( my $t = $mod ) =~ s/::/\//g;
44 0           $vars->{"module.filename"} = $t . ".pm"; # Foo/Bar.pm
45             $vars->{"author.cpanid"} ||= $1
46             if $options->{email}
47 0 0 0       && $options->{email} =~ /^(.*)\@cpan.org$/i;
      0        
48             $vars->{"author.cpanid"} = uc( $vars->{"author.cpanid"} )
49 0 0         if $vars->{"author.cpanid"};
50             }
51              
52 0 0         if ( -d $dir ) {
53 0           die( "Directory $dir exists. Aborted!\n" );
54             }
55              
56             # Get template names and data.
57 0           my ( $files, $dirs, $data );
58 0           for my $cfg ( "./", @{ $options->{_configs} } ) {
  0            
59 0 0         if ( -d "$cfg$tpldir" ) {
60 0           ( $files, $dirs, $data ) =
61             load_templates_from_directory( "$cfg$tpldir" );
62 0 0         last if $files;
63             }
64             }
65              
66             # Nope. Use built-in defaults.
67 0 0         unless ( $files ) {
68 0 0         unless ( $options->{template} eq "default" ) {
69             warn( "No templates found for ", $options->{template},
70 0           ", using default templates\n" );
71             }
72 0           require App::Module::Setup::Templates::Default;
73 0           ( $files, $dirs, $data ) =
74             App::Module::Setup::Templates::Default->load;
75             }
76              
77 0 0         if ( $options->{'install-templates'} ) {
78 0           warn( "Writing built-in templates to $dir\n" );
79             }
80             else {
81             # Change the magic _Module.pm name to
82             # the module file name.
83 0           for my $file ( @$files ) {
84 0 0         if ( $file =~ /^(.*)_Module.pm$/ ) {
85 0           my $t = $1 . $vars->{"module.filename"};
86 0           push( @$dirs, dirname($t) );
87 0           $data->{$t} = delete $data->{$file};
88 0           $file = $t;
89             }
90             }
91             }
92              
93 0           my $massage;
94 0 0         if ( $options->{'install-templates'} ) {
95 0     0     $massage = sub { $_[0] };
  0            
96             }
97             else {
98 0           require App::Module::Setup::Templates;
99 0           $massage = App::Module::Setup::Templates->can("templater");
100             }
101              
102             # Create the neccessary directories.
103 0           mkpath($dir, $options->{trace}, 0777 );
104 0 0         chdir($dir) or die( "Error creating directory $dir\n" );
105 0           mkpath( $dirs, $options->{trace}, 0777 );
106              
107 0           for my $target ( @$files ) {
108 0           $vars->{" file"} = $target;
109 0 0         open( my $fd, '>', $target )
110             or die( "Error opening ", "$dir/$target: $!\n" );
111 0           print { $fd } $massage->( $data->{$target}, $vars );
  0            
112 0 0         close($fd)
113             or die( "Error writing $target: $!\n" );
114             warn( "Wrote: $dir/$target\n" )
115 0 0         if $options->{verbose};
116             }
117              
118             # Postprocessing, e.g., set up git repo.
119 0           foreach my $cmd ( @{ $options->{postcmd} } ) {
  0            
120 0           system( $cmd );
121             }
122              
123             # If we have a git repo, add all boilerplate files.
124 0 0         if ( -d ".git" ) {
125 0           system( "git", "add", @$files );
126             }
127              
128 0           chdir(".."); # see t/90-ivp.t
129              
130 0           return 1; # assume everything went ok
131             }
132              
133             sub load_templates_from_directory {
134 0     0 0   my ( $dir ) = shift;
135 0           my $dl = length($dir);
136 0 0         $dl++ unless $dir =~ m;/$;;
137 0           my ( $files, $dirs, $data );
138              
139             find( { wanted => sub {
140 0 0   0     return if length($_) < $dl; # skip top
141 0           my $f = substr( $_, $dl ); # file relative to top
142 0 0         if ( -d $_ ) {
143 0           push( @$dirs, $f );
144 0           return;
145             }
146 0 0         return unless -f $_;
147 0 0         return if /~$/;
148              
149 0           push( @$files, $f );
150 0 0         open( my $fd, '<', $_ )
151             or die( "Error reading template $_: $!\n" );
152 0           local $/;
153 0           $data->{$f} = <$fd>;
154 0           close($fd);
155             },
156 0           no_chdir => 1,
157             }, $dir );
158              
159 0           return ( $files, $dirs, $data );
160             }
161              
162              
163             =head1 NAME
164              
165             App::Module::Setup - a simple setup for a new module
166              
167              
168             =head1 SYNOPSIS
169              
170             Nothing in here is meant for public consumption. Use F
171             from the command line.
172              
173             module-setup --author="A.U. Thor" --email=a.u.thor@example.com Foo::Bar
174              
175              
176             =head1 DESCRIPTION
177              
178             This is the core module for App::Module::Setup. If you're not looking
179             to extend or alter the behavior of this module, you probably want to
180             look at L instead.
181              
182             App::Module::Setup is used to create a skeletal CPAN distribution,
183             including basic builder scripts, tests, documentation, and module
184             code. This is done through just one method, C
.
185              
186              
187             =head1 METHODS
188              
189             =head2 App::Module::Setup->main( $options )
190              
191             C
is the only method you should need to use from outside this
192             module; all the other methods are called internally by this one.
193              
194             This method creates the distribution and populates it with the all the
195             requires files.
196              
197             It takes a reference to a hash of params, as follows:
198              
199             module # module to create in distro
200             version # initial version
201             author # author's full name (taken from C if not provided)
202             email # author's email address
203             verbose # bool: print progress messages; defaults to 0
204             template # template set to use
205             postcmd # array ref of commands to execute after creating
206             install-templates # bool: just install the selected templates
207             minperl # minimal perl version, e.g. 5.010000
208             license # e.g. perl_5
209              
210             =cut
211              
212              
213             =head1 AUTHOR
214              
215             Johan Vromans, C<< >>
216              
217              
218             =head1 BUGS
219              
220             Please report any bugs or feature requests to C, or through
221             the web interface at L. I will be notified, and then you'll
222             automatically be notified of progress on your bug as I make changes.
223              
224              
225             =head1 SUPPORT
226              
227             You can find documentation for this module with the perldoc command.
228              
229             perldoc App::Module::Setup
230              
231             You can also look for information at:
232              
233             =over 4
234              
235             =item * RT: CPAN's request tracker
236              
237             L
238              
239             =item * Search CPAN
240              
241             L
242              
243             =back
244              
245              
246             =head1 ACKNOWLEDGEMENTS
247              
248             David Golden, for giving me the final incentive to write this module.
249              
250             Sawyer X, for writing Module::Starter where I borrowed many ideas from.
251              
252              
253             =head1 COPYRIGHT & LICENSE
254              
255             Copyright 2013 Johan Vromans, all rights reserved.
256              
257             This program is free software; you can redistribute it and/or modify it
258             under the same terms as Perl itself.
259              
260              
261             =cut
262              
263             1; # End of App::Module::Setup