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