File Coverage

blib/lib/CatalystX/Starter.pm
Criterion Covered Total %
statement 68 74 91.8
branch 6 12 50.0
condition n/a
subroutine 12 13 92.3
pod n/a
total 86 99 86.8


line stmt bran cond sub pod time code
1             # Copyright (c) 2007 Jonathan Rockway <jrockway@cpan.org>
2              
3             package CatalystX::Starter;
4 6     6   102027 use strict;
  6         14  
  6         402  
5 6     6   35 use warnings;
  6         11  
  6         289  
6              
7             our $VERSION = '0.07';
8              
9 6     6   7206 use File::ShareDir qw/module_dir/;
  6         99069  
  6         642  
10 6     6   27819 use File::Copy::Recursive qw/dircopy/;
  6         82345  
  6         622  
11 6     6   19080 use File::Slurp qw/read_file write_file/;
  6         144571  
  6         579  
12 6     6   136808 use File::pushd;
  6         410915  
  6         5482  
13              
14             # don't use any of these subroutines.
15              
16             sub _boilerplate {
17 6     6   62 return module_dir('CatalystX::Starter');
18             }
19              
20             sub _module2dist {
21 3     3   2272 my $module = shift;
22 3 50       14 die("You seem to have passed a dist name, not a module name: $module\n")
23             unless $module =~ /::/;
24 3         11 $module =~ s/::/-/g;
25 3         62 return $module;
26             }
27              
28             sub _copy_files {
29 3     3   17759 my $dest = shift;
30 3         15 my $src = _boilerplate();
31 3 50       2107 dircopy($src, $dest) or die "Failed to install boilerplate: $!";
32             }
33              
34             sub _fix_files {
35 7     7   75684 my ($module, $dir) = @_;
36            
37 7 50       164 opendir my $dh, $dir or die "Failed to opendir $dir: $!";
38 7 50       149 my @paths = grep {!/^[.][.]?$/} readdir $dh
  35         126  
39             or die "Failed to read $dir: $!";
40              
41 7         36 my $p = pushd $dir;
42 7         4360 my @dirs = grep { -d } @paths;
  21         241  
43 7         2210 my @files = grep { !-d } @paths;
  21         229  
44              
45             # fix files
46             {
47 7         13 my $dist_name = $module;
  7         604  
48 7         22 my $main_module_path = "lib/$module.pm";
49 7         26 $dist_name =~ s/::/-/g;
50 7         21 $main_module_path =~ s|::|/|g;
51              
52 7         16 foreach my $file (@files) {
53 15         1239 my $data = read_file($file);
54 15         1977 chmod 0644, $file;
55 15         44 $data =~ s/\[% DIST_NAME %\]/$dist_name/g;
56 15         30 $data =~ s/\[% MODULE %\]/$module/g;
57 15         22 $data =~ s/\[% MAIN_MODULE_PATH %\]/$main_module_path/g;
58 15         45 write_file($file, $data);
59             }
60             }
61             # fix subdirs
62 7         1923 _fix_files($module, $_) for @dirs;
63 7         262 closedir $dh;
64            
65 7         40 return;
66             }
67              
68             sub _split_module {
69 3     3   2158 my $module = shift;
70 3         23 return split /::/, $module;
71             }
72              
73             sub _mk_module {
74 1     1   63830 my $module = shift;
75 1         3 my $dist = shift;
76            
77 1         9 my $d = pushd $dist;
78 1         481 mkdir 'lib';
79 1 50       19 die "Failed to create lib in $dist: $!" unless -d 'lib';
80              
81 1         9 chdir 'lib';
82 1         6 my @path = _split_module($module);
83 1         3 my $file = pop @path;
84 1         8 foreach my $part (@path) {
85 1         71 mkdir $part;
86 1 50       17 die "Failed to mkdir $part: $!" if !-d $part;
87 1         9 chdir $part;
88             }
89            
90 1         7 my $data = <<"MOD"; # indented to prevent pod parser from parsing it
91             package $module;
92             use Moose;
93             use namespace::autoclean;
94            
95             1;
96            
97             =head1 NAME
98            
99             $module -
100            
101             =head1 DESCRIPTION
102            
103             =head1 METHODS
104            
105             =head1 BUGS
106            
107             =head1 AUTHOR
108            
109             =head1 COPYRIGHT & LICENSE
110              
111             Copyright 2009 the above author(s).
112            
113             This sofware is free software, and is licensed under the same terms as perl itself.
114            
115             =cut
116            
117             MOD
118            
119 1         25 $data =~ s/^ //mg; # cleanup the leading space
120 1         9 write_file("$file.pm",$data);
121 1         6456 return;
122             }
123              
124             sub _go {
125 0     0     my $module = shift;
126 0           my $dist = _module2dist($module);
127 0           _copy_files($dist);
128 0           _fix_files($module, $dist);
129 0           _mk_module($module, $dist);
130 0           return $dist;
131             }
132              
133             1;
134              
135             __END__
136              
137             =head1 NAME
138              
139             CatalystX::Starter - bootstrap a CPAN-able Catalyst component
140              
141             =head1 SYNOPSIS
142              
143             Like C<module-starter>, but sane:
144              
145             $ catalystx-starter 'Module::Name'
146             $ cd Module-Name
147             $ git init
148             $ mv gitignore .gitignore
149             $ git add .gitignore *
150             $ git ci -m 'Start my component'
151              
152             Then edit Changes and README to taste
153            
154             $ mg README
155             $ mg Changes
156             $ git ci -a -m 'update Changes and README'
157              
158             Then you're ready to work:
159              
160             $ make test
161             00load.............ok
162             live...............ok
163             All tests successful.
164              
165             $ prove --lib t/author # don't want users running these
166             pod................ok
167             pod-coverage.......ok
168             All tests successful.
169              
170             =head1 DESCRIPTION
171              
172             Recently, I've stopped using C<Module::Starter>, because it generates
173             way too much boilerplate and not enough of stuff I actually need. I
174             find it easier to just start with nothing and manually write what I
175             need.
176              
177             C<CatalystX::Starter> automates this minimalism for me. It will
178             create everything you need to start developing a Catalyst component or
179             plugin, but won't create useless crap that you just have to delete.
180              
181             Here's what you get:
182              
183             =over 4
184              
185             =item C<t/lib/TestApp>
186              
187             A live app that can be run from tests (including C<t/live-test.t>).
188             It also comes with the C<testapp_server.pl> and C<testapp_test.pl>, so
189             you can try our your TestApp from the command line. Yay for never
190             having to write this again.
191              
192             So far, I've wasted more than an hour of my life typing this exact
193             TestApp code in again and again. Now it's automatic. FINALLY.
194              
195             =item Makefile.PL
196              
197             C<Module::Install>-based Makefile.PL with C<build_requires> set up to
198             run the default tests.
199              
200             =item gitignore
201              
202             Save yourself the effort of setting up a C<.gitignore>. You can of
203             course import this as C<svn:ignore> or C<.cvsignore>. I use git, so
204             that's what you get by default.
205              
206             Note that you have to rename this yourself, because I want git to
207             track it, not treat it as an ignore file.
208              
209             =item MANIFEST.SKIP
210              
211             A useful MANIFEST.SKIP that ignores stuff that C<make> leaves lying
212             around, and my C<.git> directory.
213              
214             =item Changes / README
215              
216             No text in here. Change it to what you want it to look like.
217              
218             =item C<lib/Your/Module.pm>
219              
220             Almost nothing:
221              
222             package Your::Module;
223             use strict;
224             use warnings;
225              
226             1;
227              
228             Write the POD yourself. You're smart enough to remember that the
229             sequence is NAME, SYNOPSIS, DESCRIPTION, METHODS, BUGS, AUTHOR,
230             COPYRIGHT. If not... now you are :)
231              
232             =back
233              
234             That's about it. Enjoy.
235              
236             =head1 SEE ALSO
237              
238             C<catalyst.pl>, for creating Catalyst applications.
239              
240             L<Module::Starter|Module::Starter>, if you like deleting code more
241             than writing it.
242              
243             =head1 AUTHOR
244              
245             Jonathan Rockway C<< <jrockway@cpan.org> >>.
246              
247             =head1 COPYRIGHT
248              
249             I don't assert any copyright over the generated files. This module
250             itself is copyright (c) 2007 Jonathan Rockway and is licensed under
251             the same terms as Perl itself.