Lets compile. That would be novel. merge fail
[catagits/Catalyst-Devel.git] / lib / Catalyst / Helper.pm
CommitLineData
68ccb5e5 1package Catalyst::Helper;
2
3use strict;
c93c671b 4use warnings;
68ccb5e5 5use base 'Class::Accessor::Fast';
6use Config;
7use File::Spec;
8use File::Path;
68ccb5e5 9use FindBin;
2415f774 10use IO::File;
11use POSIX 'strftime';
68ccb5e5 12use Template;
9ffb6b83 13use Catalyst::Devel;
68ccb5e5 14use Catalyst::Utils;
15use Catalyst::Exception;
312ab89f 16use Path::Class qw/dir file/;
17use File::ShareDir qw/dist_dir/;
18use Moose;
19use aliased 'Path::Class::Dir';
20
68ccb5e5 21
22my %cache;
23
24=head1 NAME
25
26Catalyst::Helper - Bootstrap a Catalyst application
27
28=head1 SYNOPSIS
29
fab70e0a 30 catalyst.pl <myappname>
68ccb5e5 31
32=cut
33
312ab89f 34
35
36sub get_sharedir_file {
37 my ($self, @filename) = @_;
38 my $dist_dir;
39 if (-d "inc/.author") { # Can't use sharedir if we're in a checkout
40 # this feels horrible, better ideas?
41 $dist_dir = 'share';
42 }
43 else {
44 $dist_dir = dist_dir('Catalyst-Devel');
45 }
46 my $file = file( $dist_dir, @filename);
47 my $contents = $file->slurp;
48 return $contents;
49}
50
51# Do not touch this method, *EVER*, it is needed for back compat.
68ccb5e5 52sub get_file {
53 my ( $self, $class, $file ) = @_;
54 unless ( $cache{$class} ) {
55 local $/;
56 $cache{$class} = eval "package $class; <DATA>";
57 }
58 my $data = $cache{$class};
312ab89f 59 Carp::confess("Could not get data from __DATA__ segment for $class")
60 unless $data;
68ccb5e5 61 my @files = split /^__(.+)__\r?\n/m, $data;
62 shift @files;
63 while (@files) {
64 my ( $name, $content ) = splice @files, 0, 2;
65 return $content if $name eq $file;
66 }
67 return 0;
68}
69
312ab89f 70
68ccb5e5 71sub mk_app {
72 my ( $self, $name ) = @_;
73
74 # Needs to be here for PAR
75 require Catalyst;
76
555cab18 77 if ( $name =~ /[^\w:]/ || $name =~ /^\d/ || $name =~ /\b:\b|:{3,}/) {
68ccb5e5 78 warn "Error: Invalid application name.\n";
79 return 0;
80 }
902763f2 81 $self->{name } = $name;
82 $self->{dir } = $name;
83 $self->{dir } =~ s/\:\:/-/g;
84 $self->{script } = File::Spec->catdir( $self->{dir}, 'script' );
85 $self->{appprefix } = Catalyst::Utils::appprefix($name);
e9345225 86 $self->{appenv } = Catalyst::Utils::class2env($name);
675fef06 87 $self->{startperl } = -r '/usr/bin/env'
88 ? '#!/usr/bin/env perl'
9bc8b354 89 : "#!$Config{perlpath} -w";
9ffb6b83 90 $self->{scriptgen } = $Catalyst::Devel::CATALYST_SCRIPT_GEN || 4;
902763f2 91 $self->{catalyst_version} = $Catalyst::VERSION;
92 $self->{author } = $self->{author} = $ENV{'AUTHOR'}
68ccb5e5 93 || eval { @{ [ getpwuid($<) ] }[6] }
94 || 'Catalyst developer';
95
96 my $gen_scripts = ( $self->{makefile} ) ? 0 : 1;
97 my $gen_makefile = ( $self->{scripts} ) ? 0 : 1;
98 my $gen_app = ( $self->{scripts} || $self->{makefile} ) ? 0 : 1;
99
100 if ($gen_app) {
101 $self->_mk_dirs;
102 $self->_mk_config;
103 $self->_mk_appclass;
104 $self->_mk_rootclass;
105 $self->_mk_readme;
106 $self->_mk_changes;
107 $self->_mk_apptest;
108 $self->_mk_images;
109 $self->_mk_favicon;
110 }
111 if ($gen_makefile) {
112 $self->_mk_makefile;
113 }
114 if ($gen_scripts) {
115 $self->_mk_cgi;
116 $self->_mk_fastcgi;
117 $self->_mk_server;
118 $self->_mk_test;
119 $self->_mk_create;
45d74601 120 $self->_mk_information;
68ccb5e5 121 }
122 return $self->{dir};
123}
124
68ccb5e5 125sub mk_component {
126 my $self = shift;
127 my $app = shift;
128 $self->{app} = $app;
129 $self->{author} = $self->{author} = $ENV{'AUTHOR'}
130 || eval { @{ [ getpwuid($<) ] }[6] }
131 || 'A clever guy';
132 $self->{base} ||= File::Spec->catdir( $FindBin::Bin, '..' );
133 unless ( $_[0] =~ /^(?:model|view|controller)$/i ) {
134 my $helper = shift;
135 my @args = @_;
136 my $class = "Catalyst::Helper::$helper";
137 eval "require $class";
138
139 if ($@) {
140 Catalyst::Exception->throw(
141 message => qq/Couldn't load helper "$class", "$@"/ );
142 }
143
144 if ( $class->can('mk_stuff') ) {
145 return 1 unless $class->mk_stuff( $self, @args );
146 }
147 }
148 else {
149 my $type = shift;
150 my $name = shift || "Missing name for model/view/controller";
151 my $helper = shift;
152 my @args = @_;
fab70e0a 153 return 0 if $name =~ /[^\w\:]/;
68ccb5e5 154 $type = lc $type;
155 $self->{long_type} = ucfirst $type;
156 $type = 'M' if $type =~ /model/i;
157 $type = 'V' if $type =~ /view/i;
158 $type = 'C' if $type =~ /controller/i;
159 my $appdir = File::Spec->catdir( split /\:\:/, $app );
160 my $test_path =
161 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, 'C' );
162 $type = $self->{long_type} unless -d $test_path;
163 $self->{type} = $type;
164 $self->{name} = $name;
165 $self->{class} = "$app\::$type\::$name";
166
167 # Class
168 my $path =
169 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, $type );
170 my $file = $name;
171 if ( $name =~ /\:/ ) {
172 my @path = split /\:\:/, $name;
173 $file = pop @path;
174 $path = File::Spec->catdir( $path, @path );
175 }
176 $self->mk_dir($path);
177 $file = File::Spec->catfile( $path, "$file.pm" );
178 $self->{file} = $file;
179
180 # Test
181 $self->{test_dir} = File::Spec->catdir( $FindBin::Bin, '..', 't' );
182 $self->{test} = $self->next_test;
183
184 # Helper
185 if ($helper) {
186 my $comp = $self->{long_type};
187 my $class = "Catalyst::Helper::$comp\::$helper";
188 eval "require $class";
189
190 if ($@) {
191 Catalyst::Exception->throw(
192 message => qq/Couldn't load helper "$class", "$@"/ );
193 }
194
195 if ( $class->can('mk_compclass') ) {
196 return 1 unless $class->mk_compclass( $self, @args );
197 }
198 else { return 1 unless $self->_mk_compclass }
199
200 if ( $class->can('mk_comptest') ) {
201 $class->mk_comptest( $self, @args );
202 }
203 else { $self->_mk_comptest }
204 }
205
206 # Fallback
207 else {
208 return 1 unless $self->_mk_compclass;
209 $self->_mk_comptest;
210 }
211 }
212 return 1;
213}
214
68ccb5e5 215sub mk_dir {
216 my ( $self, $dir ) = @_;
217 if ( -d $dir ) {
218 print qq/ exists "$dir"\n/;
219 return 0;
220 }
221 if ( mkpath [$dir] ) {
222 print qq/created "$dir"\n/;
223 return 1;
224 }
225
226 Catalyst::Exception->throw( message => qq/Couldn't create "$dir", "$!"/ );
227}
228
68ccb5e5 229sub mk_file {
230 my ( $self, $file, $content ) = @_;
312ab89f 231 if ( -e $file && -s _ ) {
68ccb5e5 232 print qq/ exists "$file"\n/;
233 return 0
234 unless ( $self->{'.newfiles'}
235 || $self->{scripts}
236 || $self->{makefile} );
237 if ( $self->{'.newfiles'} ) {
238 if ( my $f = IO::File->new("< $file") ) {
239 my $oldcontent = join( '', (<$f>) );
240 return 0 if $content eq $oldcontent;
241 }
242 $file .= '.new';
243 }
244 }
245 if ( my $f = IO::File->new("> $file") ) {
246 binmode $f;
247 print $f $content;
248 print qq/created "$file"\n/;
249 return 1;
250 }
251
252 Catalyst::Exception->throw( message => qq/Couldn't create "$file", "$!"/ );
253}
254
68ccb5e5 255sub next_test {
256 my ( $self, $tname ) = @_;
257 if ($tname) { $tname = "$tname.t" }
258 else {
259 my $name = $self->{name};
260 my $prefix = $name;
261 $prefix =~ s/::/-/g;
262 $prefix = $prefix;
263 $tname = $prefix . '.t';
264 $self->{prefix} = $prefix;
265 $prefix = lc $prefix;
266 $prefix =~ s/-/\//g;
267 $self->{uri} = "/$prefix";
268 }
269 my $dir = $self->{test_dir};
270 my $type = lc $self->{type};
271 $self->mk_dir($dir);
272 return File::Spec->catfile( $dir, "$type\_$tname" );
273}
274
312ab89f 275# Do not touch this method, *EVER*, it is needed for back compat.
276## addendum: we had to split this method so we could have backwards
277## compatability. otherwise, we'd have no way to pass stuff from __DATA__
278
68ccb5e5 279sub render_file {
280 my ( $self, $file, $path, $vars ) = @_;
312ab89f 281 my $template = $self->get_file( ( caller(0) )[0], $file );
282 $self->render_file_contents($template, $path, $vars);
283}
284
285sub render_sharedir_file {
286 my ( $self, $file, $path, $vars ) = @_;
287 my $template = $self->get_sharedir_file( $file );
288 $self->render_file_contents($template, $path, $vars);
289}
290
291sub render_file_contents {
292 my ( $self, $template, $path, $vars ) = @_;
68ccb5e5 293 $vars ||= {};
294 my $t = Template->new;
68ccb5e5 295 return 0 unless $template;
296 my $output;
297 $t->process( \$template, { %{$self}, %$vars }, \$output )
298 || Catalyst::Exception->throw(
312ab89f 299 message => qq/Couldn't process "$template", / . $t->error() );
68ccb5e5 300 $self->mk_file( $path, $output );
301}
302
45d74601 303sub _mk_information {
304 my $self = shift;
305 print qq/Change to application directory and Run "perl Makefile.PL" to make sure your install is complete\n/;
306}
307
68ccb5e5 308sub _mk_dirs {
309 my $self = shift;
310 $self->mk_dir( $self->{dir} );
311 $self->mk_dir( $self->{script} );
312 $self->{lib} = File::Spec->catdir( $self->{dir}, 'lib' );
313 $self->mk_dir( $self->{lib} );
314 $self->{root} = File::Spec->catdir( $self->{dir}, 'root' );
315 $self->mk_dir( $self->{root} );
316 $self->{static} = File::Spec->catdir( $self->{root}, 'static' );
317 $self->mk_dir( $self->{static} );
318 $self->{images} = File::Spec->catdir( $self->{static}, 'images' );
319 $self->mk_dir( $self->{images} );
320 $self->{t} = File::Spec->catdir( $self->{dir}, 't' );
321 $self->mk_dir( $self->{t} );
322
323 $self->{class} = File::Spec->catdir( split( /\:\:/, $self->{name} ) );
324 $self->{mod} = File::Spec->catdir( $self->{lib}, $self->{class} );
325 $self->mk_dir( $self->{mod} );
326
327 if ( $self->{short} ) {
328 $self->{m} = File::Spec->catdir( $self->{mod}, 'M' );
329 $self->mk_dir( $self->{m} );
330 $self->{v} = File::Spec->catdir( $self->{mod}, 'V' );
331 $self->mk_dir( $self->{v} );
332 $self->{c} = File::Spec->catdir( $self->{mod}, 'C' );
333 $self->mk_dir( $self->{c} );
334 }
335 else {
336 $self->{m} = File::Spec->catdir( $self->{mod}, 'Model' );
337 $self->mk_dir( $self->{m} );
338 $self->{v} = File::Spec->catdir( $self->{mod}, 'View' );
339 $self->mk_dir( $self->{v} );
340 $self->{c} = File::Spec->catdir( $self->{mod}, 'Controller' );
341 $self->mk_dir( $self->{c} );
342 }
343 my $name = $self->{name};
344 $self->{rootname} =
345 $self->{short} ? "$name\::C::Root" : "$name\::Controller::Root";
346 $self->{base} = File::Spec->rel2abs( $self->{dir} );
347}
348
349sub _mk_appclass {
350 my $self = shift;
351 my $mod = $self->{mod};
312ab89f 352 $self->render_sharedir_file( 'lib/appclass.tt', "$mod.pm" );
68ccb5e5 353}
354
355sub _mk_rootclass {
356 my $self = shift;
312ab89f 357 $self->render_sharedir_file( 'lib/MyApp/Controller/rootclass.tt',
68ccb5e5 358 File::Spec->catfile( $self->{c}, "Root.pm" ) );
359}
360
361sub _mk_makefile {
362 my $self = shift;
363 $self->{path} = File::Spec->catfile( 'lib', split( '::', $self->{name} ) );
364 $self->{path} .= '.pm';
365 my $dir = $self->{dir};
312ab89f 366 $self->render_sharedir_file( 'Makefile.PL.tt', "$dir\/Makefile.PL" );
68ccb5e5 367
368 if ( $self->{makefile} ) {
369
370 # deprecate the old Build.PL file when regenerating Makefile.PL
371 $self->_deprecate_file(
372 File::Spec->catdir( $self->{dir}, 'Build.PL' ) );
373 }
374}
375
376sub _mk_config {
377 my $self = shift;
378 my $dir = $self->{dir};
379 my $appprefix = $self->{appprefix};
312ab89f 380 $self->render_sharedir_file( 'myapp.conf.tt',
a4e6d745 381 File::Spec->catfile( $dir, "$appprefix.conf" ) );
68ccb5e5 382}
383
384sub _mk_readme {
385 my $self = shift;
386 my $dir = $self->{dir};
312ab89f 387 $self->render_sharedir_file( 'README.tt', "$dir\/README" );
68ccb5e5 388}
389
390sub _mk_changes {
391 my $self = shift;
392 my $dir = $self->{dir};
5b1ec88b 393 my $time = strftime('%Y-%m-%d %H:%M:%S', localtime time);
312ab89f 394 $self->render_sharedir_file( 'Changes.tt', "$dir\/Changes", { time => $time } );
68ccb5e5 395}
396
397sub _mk_apptest {
398 my $self = shift;
399 my $t = $self->{t};
312ab89f 400 $self->render_sharedir_file( 't/apptest.tt', "$t\/01app.t" );
401 $self->render_sharedir_file( 't/podtest.tt', "$t\/02pod.t" );
402 $self->render_sharedir_file( 't/podcoveragetest.tt', "$t\/03podcoverage.t" );
68ccb5e5 403}
404
405sub _mk_cgi {
406 my $self = shift;
407 my $script = $self->{script};
408 my $appprefix = $self->{appprefix};
312ab89f 409 $self->render_sharedir_file( 'script/cgi.tt', "$script\/$appprefix\_cgi.pl" );
68ccb5e5 410 chmod 0700, "$script/$appprefix\_cgi.pl";
411}
412
413sub _mk_fastcgi {
414 my $self = shift;
415 my $script = $self->{script};
416 my $appprefix = $self->{appprefix};
312ab89f 417 $self->render_sharedir_file( 'script/fastcgi.tt', "$script\/$appprefix\_fastcgi.pl" );
68ccb5e5 418 chmod 0700, "$script/$appprefix\_fastcgi.pl";
419}
420
421sub _mk_server {
422 my $self = shift;
423 my $script = $self->{script};
424 my $appprefix = $self->{appprefix};
312ab89f 425 $self->render_sharedir_file( 'script/server.tt', "$script\/$appprefix\_server.pl" );
68ccb5e5 426 chmod 0700, "$script/$appprefix\_server.pl";
427}
428
429sub _mk_test {
430 my $self = shift;
431 my $script = $self->{script};
432 my $appprefix = $self->{appprefix};
312ab89f 433 $self->render_sharedir_file( 'script/test.tt', "$script/$appprefix\_test.pl" );
68ccb5e5 434 chmod 0700, "$script/$appprefix\_test.pl";
435}
436
437sub _mk_create {
438 my $self = shift;
439 my $script = $self->{script};
440 my $appprefix = $self->{appprefix};
312ab89f 441 $self->render_sharedir_file( 'script/create.tt', "$script\/$appprefix\_create.pl" );
68ccb5e5 442 chmod 0700, "$script/$appprefix\_create.pl";
443}
444
445sub _mk_compclass {
446 my $self = shift;
447 my $file = $self->{file};
312ab89f 448 return $self->render_sharedir_file( 'compclass.tt', "$file" );
68ccb5e5 449}
450
451sub _mk_comptest {
452 my $self = shift;
453 my $test = $self->{test};
312ab89f 454 $self->render_sharedir_file( 'comptest.tt', "$test" );
68ccb5e5 455}
456
457sub _mk_images {
458 my $self = shift;
459 my $images = $self->{images};
460 my @images =
461 qw/catalyst_logo btn_120x50_built btn_120x50_built_shadow
462 btn_120x50_powered btn_120x50_powered_shadow btn_88x31_built
463 btn_88x31_built_shadow btn_88x31_powered btn_88x31_powered_shadow/;
464 for my $name (@images) {
312ab89f 465 my $image = $self->get_sharedir_file("root", "static", "images", "$name.png.bin");
68ccb5e5 466 $self->mk_file( File::Spec->catfile( $images, "$name.png" ), $image );
467 }
468}
469
470sub _mk_favicon {
471 my $self = shift;
472 my $root = $self->{root};
312ab89f 473 my $favicon = $self->get_sharedir_file( 'root', 'favicon.ico.bin' );
474 my $dest = File::Spec->catfile( $root, "favicon.ico" );
475 $self->mk_file( $dest, $favicon );
68ccb5e5 476
477}
478
479sub _deprecate_file {
480 my ( $self, $file ) = @_;
481 if ( -e $file ) {
482 my $oldcontent;
483 if ( my $f = IO::File->new("< $file") ) {
484 $oldcontent = join( '', (<$f>) );
485 }
486 my $newfile = $file . '.deprecated';
487 if ( my $f = IO::File->new("> $newfile") ) {
488 binmode $f;
489 print $f $oldcontent;
490 print qq/created "$newfile"\n/;
491 unlink $file;
492 print qq/removed "$file"\n/;
493 return 1;
494 }
495 Catalyst::Exception->throw(
496 message => qq/Couldn't create "$file", "$!"/ );
497 }
498}
499
312ab89f 500
501## this is so you don't have to do make install after every change to test
502sub _find_share_dir {
503 my ($self, $args) = @_;
504 my $share_name = $self->name;
505 if ($share_name =~ s!^/(.*?)/!!) {
506 my $dist = $1;
507 $args->{share_base_dir} = eval {
508 Dir->new(File::ShareDir::dist_dir($dist))
509 ->subdir('share');
510 };
511 if ($@) {
512 # not installed
513 my $file = __FILE__;
514 my $dir = Dir->new(dirname($file));
515 my $share_base;
516 while ($dir->parent) {
517 if (-d $dir->subdir('share') && -d $dir->subdir('share')->subdir('root')) {
518 $share_base = $dir->subdir('share')->subdir('root');
519 last;
520 }
521 $dir = $dir->parent;
522 }
523 confess "could not find sharebase by recursion. ended up at $dir, from $file"
524 unless $share_base;
525 $args->{share_base_dir} = $share_base;
526 }
527 }
528 my $base = $args->{share_base_dir}->subdir($share_name);
529 confess "No such share base directory ${base}"
530 unless -d $base;
531 $self->share_dir($base);
532};
533
46b64f53 5341;
312ab89f 535
fab70e0a 536=head1 DESCRIPTION
537
538This module is used by B<catalyst.pl> to create a set of scripts for a
539new catalyst application. The scripts each contain documentation and
540will output help on how to use them if called incorrectly or in some
541cases, with no arguments.
542
543It also provides some useful methods for a Helper module to call when
544creating a component. See L</METHODS>.
545
546=head1 SCRIPTS
547
548=head2 _create.pl
549
550Used to create new components for a catalyst application at the
551development stage.
552
553=head2 _server.pl
554
555The catalyst test server, starts an HTTPD which outputs debugging to
556the terminal.
557
558=head2 _test.pl
559
560A script for running tests from the command-line.
561
562=head2 _cgi.pl
563
564Run your application as a CGI.
565
566=head2 _fastcgi.pl
567
568Run the application as a fastcgi app. Either by hand, or call this
569from FastCgiServer in your http server config.
570
68ccb5e5 571=head1 HELPERS
572
fab70e0a 573The L</_create.pl> script creates application components using Helper
574modules. The Catalyst team provides a good number of Helper modules
575for you to use. You can also add your own.
576
68ccb5e5 577Helpers are classes that provide two methods.
578
579 * mk_compclass - creates the Component class
580 * mk_comptest - creates the Component test
581
fab70e0a 582So when you call C<scripts/myapp_create.pl view MyView TT>, create
583will try to execute Catalyst::Helper::View::TT->mk_compclass and
68ccb5e5 584Catalyst::Helper::View::TT->mk_comptest.
585
c4c50c2d 586See L<Catalyst::Helper::View::TT> and
587L<Catalyst::Helper::Model::DBIC::Schema> for examples.
68ccb5e5 588
589All helper classes should be under one of the following namespaces.
590
591 Catalyst::Helper::Model::
592 Catalyst::Helper::View::
593 Catalyst::Helper::Controller::
594
675fef06 595=head2 COMMON HELPERS
bc8d7994 596
597=over
598
599=item *
600
601L<Catalyst::Helper::Model::DBIC::Schema> - DBIx::Class models
602
603=item *
604
605L<Catalyst::Helper::View::TT> - Template Toolkit view
606
607=item *
608
609L<Catalyst::Helper::Model::LDAP>
610
611=item *
612
613L<Catalyst::Helper::Model::Adaptor> - wrap any class into a Catalyst model
614
615=back
616
617=head3 NOTE
618
675fef06 619The helpers will read author name from /etc/passwd by default. + To override, please export the AUTHOR variable.
bc8d7994 620
621=head1 METHODS
622
fab70e0a 623=head2 mk_compclass
624
625This method in your Helper module is called with C<$helper>
626which is a L<Catalyst::Helper> object, and whichever other arguments
627the user added to the command-line. You can use the $helper to call methods
628described below.
629
630If the Helper module does not contain a C<mk_compclass> method, it
631will fall back to calling L</render_file>, with an argument of
632C<compclass>.
633
634=head2 mk_comptest
635
636This method in your Helper module is called with C<$helper>
637which is a L<Catalyst::Helper> object, and whichever other arguments
638the user added to the command-line. You can use the $helper to call methods
639described below.
640
641If the Helper module does not contain a C<mk_compclass> method, it
642will fall back to calling L</render_file>, with an argument of
643C<comptest>.
644
645=head2 mk_stuff
646
647This method is called if the user does not supply any of the usual
648component types C<view>, C<controller>, C<model>. It is passed the
649C<$helper> object (an instance of L<Catalyst::Helper>), and any other
650arguments the user typed.
651
652There is no fallback for this method.
653
bc8d7994 654=head1 INTERNAL METHODS
fab70e0a 655
656These are the methods that the Helper classes can call on the
657<$helper> object passed to them.
658
28eb1300 659=head2 render_file ($file, $path, $vars)
fab70e0a 660
28eb1300 661Render and create a file from a template in DATA using Template
662Toolkit. $file is the relevent chunk of the __DATA__ section, $path is
663the path to the file and $vars is the hashref as expected by
664L<Template Toolkit|Template>.
fab70e0a 665
28eb1300 666=head2 get_file ($class, $file)
fab70e0a 667
668Fetch file contents from the DATA section. This is used internally by
28eb1300 669L</render_file>. $class is the name of the class to get the DATA
670section from. __PACKAGE__ or ( caller(0) )[0] might be sensible
671values for this.
fab70e0a 672
673=head2 mk_app
674
675Create the main application skeleton. This is called by L<catalyst.pl>.
676
28eb1300 677=head2 mk_component ($app)
fab70e0a 678
679This method is called by L<create.pl> to make new components
680for your application.
681
28eb1300 682=head3 mk_dir ($path)
fab70e0a 683
684Surprisingly, this function makes a directory.
685
28eb1300 686=head2 mk_file ($file, $content)
fab70e0a 687
688Writes content to a file. Called by L</render_file>.
689
28eb1300 690=head2 next_test ($test_name)
fab70e0a 691
692Calculates the name of the next numbered test file and returns it.
28eb1300 693Don't give the number or the .t suffix for the test name.
fab70e0a 694
312ab89f 695=head2 Dir
68ccb5e5 696
312ab89f 697Alias for L<Path::Class::Dir>
68ccb5e5 698
699=cut
68ccb5e5 700
312ab89f 701=head2 get_sharedir_file
68ccb5e5 702
312ab89f 703Method for getting a file out of share/
68ccb5e5 704
705=cut
68ccb5e5 706
312ab89f 707=head2 render_file_contents
68ccb5e5 708
312ab89f 709Process a L<Template::Toolkit> template.
68ccb5e5 710
711=cut
68ccb5e5 712
312ab89f 713=head2 render_sharedir_file
68ccb5e5 714
312ab89f 715Render a template/image file from our share directory
68ccb5e5 716
717=cut
68ccb5e5 718
68ccb5e5 719
312ab89f 720=head1 NOTE
68ccb5e5 721
312ab89f 722The helpers will read author name from /etc/passwd by default.
723To override, please export the AUTHOR variable.
68ccb5e5 724
312ab89f 725=head1 SEE ALSO
68ccb5e5 726
312ab89f 727L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
728L<Catalyst::Response>, L<Catalyst>
68ccb5e5 729
f64c718c 730=head1 AUTHORS
68ccb5e5 731
f64c718c 732Catalyst Contributors, see Catalyst.pm
68ccb5e5 733
68ccb5e5 734=head1 LICENSE
735
7cd3b67e 736This library is free software. You can redistribute it and/or modify
68ccb5e5 737it under the same terms as Perl itself.
738
312ab89f 739=begin pod_to_ignore
740
68ccb5e5 741=cut
742