Fixed additional file installation for multi level app names
[catagits/Catalyst-Runtime.git] / lib / Module / Install / Catalyst.pm
1 package Module::Install::Catalyst;
2
3 use strict;
4
5 our @ISA;
6 require Module::Install::Base;
7 @ISA = qw/Module::Install::Base/;
8
9 use File::Find;
10 use FindBin;
11 use File::Copy::Recursive 'rcopy';
12 use File::Spec ();
13
14 our @IGNORE =
15   qw/Build Build.PL Changes MANIFEST META.yml Makefile.PL Makefile README
16   _build blib lib script t inc/;
17 our @CLASSES   = ();
18 our $ENGINE    = 'CGI';
19 our $CORE      = 0;
20 our $MULTIARCH = 0;
21 our $SCRIPT;
22 our $USAGE;
23
24 =head1 NAME
25
26 Module::Install::Catalyst - Module::Install extension for Catalyst
27
28 =head1 SYNOPSIS
29
30 See L<Catalyst>
31
32 =head1 DESCRIPTION
33
34 L<Module::Install> extension for Catalyst.
35
36 =head1 METHODS
37
38 =head2 catalyst_files
39
40 =cut
41
42 sub catalyst_files {
43     my $self = shift;
44
45     chdir $FindBin::Bin;
46
47     my @files;
48     opendir CATDIR, '.';
49   CATFILES: for my $name ( readdir CATDIR ) {
50         for my $ignore (@IGNORE) {
51             next CATFILES if $name =~ /^$ignore$/;
52             next CATFILES if $name !~ /\w/;
53         }
54         push @files, $name;
55     }
56     closedir CATDIR;
57     my @path = split '-', $self->name;
58     for my $orig (@files) {
59         my $path = File::Spec->catdir( 'blib', 'lib', @path, $orig );
60         rcopy( $orig, $path );
61     }
62 }
63
64 =head2 catalyst_ignore_all(\@ignore)
65
66 =cut
67
68 sub catalyst_ignore_all {
69     my ( $self, $ignore ) = @_;
70     @IGNORE = @$ignore;
71 }
72
73 =head2 catalyst_ignore(\@ignore)
74
75 =cut
76
77 sub catalyst_ignore {
78     my ( $self, @ignore ) = @_;
79     push @IGNORE, @ignore;
80 }
81
82 =head2 catalyst_par($name)
83
84 =cut
85
86 # Workaround for a namespace conflict
87 sub catalyst_par { Catalyst::Module::Install::_catalyst_par(@_) }
88
89 =head2 catalyst_par_core($core)
90
91 =cut
92
93 sub catalyst_par_core {
94     my ( $self, $core ) = @_;
95     $core ? ( $CORE = $core ) : $CORE++;
96 }
97
98 =head2 catalyst_par_classes(@clases)
99
100 =cut
101
102 sub catalyst_par_classes {
103     my ( $self, @classes ) = @_;
104     push @CLASSES, @classes;
105 }
106
107 =head2 catalyst_par_engine($engine)
108
109 =cut
110
111 sub catalyst_par_engine {
112     my ( $self, $engine ) = @_;
113     $ENGINE = $engine;
114 }
115
116 =head2 catalyst_par_multiarch($multiarch)
117
118 =cut
119
120 sub catalyst_par_multiarch {
121     my ( $self, $multiarch ) = @_;
122     $multiarch ? ( $MULTIARCH = $multiarch ) : $MULTIARCH++;
123 }
124
125 =head2 catalyst_par_script($script)
126
127 =cut
128
129 sub catalyst_par_script {
130     my ( $self, $script ) = @_;
131     $SCRIPT = $script;
132 }
133
134 =head2 catalyst_par_usage($usage)
135
136 =cut
137
138 sub catalyst_par_usage {
139     my ( $self, $usage ) = @_;
140     $USAGE = $usage;
141 }
142
143 package Catalyst::Module::Install;
144
145 use strict;
146 use FindBin;
147 use File::Copy::Recursive 'rmove';
148 use File::Spec ();
149
150 sub _catalyst_par {
151     my ( $self, $par ) = @_;
152
153     my $name = $self->name;
154     $name =~ s/::/_/g;
155     $name = lc $name;
156     $par ||= "$name.par";
157     my $engine = $Module::Install::Catalyst::ENGINE || 'CGI';
158
159     # Check for PAR
160     eval "use PAR ()";
161     die "Please install PAR\n" if $@;
162     eval "use PAR::Packer ()";
163     die "Please install PAR::Packer\n" if $@;
164     eval "use App::Packer::PAR ()";
165     die "Please install App::Packer::PAR\n" if $@;
166     eval "use Module::ScanDeps ()";
167     die "Please install Module::ScanDeps\n" if $@;
168
169     my $root = $FindBin::Bin;
170     my $path = File::Spec->catfile( 'blib', 'lib', split( '::', $self->name ) );
171     $path .= '.pm';
172     unless ( -f $path ) {
173         print qq/Not writing PAR, "$path" doesn't exist\n/;
174         return 0;
175     }
176     print qq/Writing PAR "$par"\n/;
177     chdir File::Spec->catdir( $root, 'blib' );
178
179     my $par_pl = 'par.pl';
180     unlink $par_pl;
181
182     my $version = $Catalyst::VERSION;
183     my $class   = $self->name;
184
185     my $classes = '';
186     $classes .= "    require $_;\n" for @Catalyst::Module::Install::CLASSES;
187
188     unlink $par_pl;
189
190     my $usage = $Module::Install::Catalyst::USAGE || <<"EOF";
191 Usage:
192     [parl] $name\[.par] [script] [arguments]
193
194   Examples:
195     parl $name.par $name\_server.pl -r
196     myapp $name\_cgi.pl
197 EOF
198
199     my $script   = $Module::Install::Catalyst::SCRIPT;
200     my $tmp_file = IO::File->new("> $par_pl ");
201     print $tmp_file <<"EOF";
202 if ( \$ENV{PAR_PROGNAME} ) {
203     my \$zip = \$PAR::LibCache{\$ENV{PAR_PROGNAME}}
204         || Archive::Zip->new(__FILE__);
205     my \$script = '$script';
206     \$ARGV[0] ||= \$script if \$script;
207     if ( ( \@ARGV == 0 ) || ( \$ARGV[0] eq '-h' ) || ( \$ARGV[0] eq '-help' )) {
208         my \@members = \$zip->membersMatching('.*script/.*\.pl');
209         my \$list = "  Available scripts:\\n";
210         for my \$member ( \@members ) {
211             my \$name = \$member->fileName;
212             \$name =~ /(\\w+\\.pl)\$/;
213             \$name = \$1;
214             next if \$name =~ /^main\.pl\$/;
215             next if \$name =~ /^par\.pl\$/;
216             \$list .= "    \$name\\n";
217         }
218         die <<"END";
219 $usage
220 \$list
221 END
222     }
223     my \$file = shift \@ARGV;
224     \$file =~ s/^.*[\\/\\\\]//;
225     \$file =~ s/\\.[^.]*\$//i;
226     my \$member = eval { \$zip->memberNamed("./script/\$file.pl") };
227     die qq/Can't open perl script "\$file"\n/ unless \$member;
228     PAR::_run_member( \$member, 1 );
229 }
230 else {
231     require lib;
232     import lib 'lib';
233     \$ENV{CATALYST_ENGINE} = '$engine';
234     require $class;
235     import $class;
236     require Catalyst::Helper;
237     require Catalyst::Test;
238     require Catalyst::Engine::HTTP;
239     require Catalyst::Engine::CGI;
240     require Catalyst::Controller;
241     require Catalyst::Model;
242     require Catalyst::View;
243     require Getopt::Long;
244     require Pod::Usage;
245     require Pod::Text;
246     $classes
247 }
248 EOF
249     $tmp_file->close;
250
251     # Create package
252     local $SIG{__WARN__} = sub { };
253     open my $olderr, '>&STDERR';
254     open STDERR, '>', File::Spec->devnull;
255     my %opt = (
256         'x' => 1,
257         'n' => 0,
258         'o' => $par,
259         'a' => [ grep( !/par.pl/, glob '.' ) ],
260         'p' => 1,
261         'B' => $Module::Install::Catalyst::CORE,
262         'm' => $Module::Install::Catalyst::MULTIARCH
263     );
264     App::Packer::PAR->new(
265         frontend  => 'Module::ScanDeps',
266         backend   => 'PAR::Packer',
267         frontopts => \%opt,
268         backopts  => \%opt,
269         args      => ['par.pl'],
270     )->go;
271
272     open STDERR, '>&', $olderr;
273
274     unlink $par_pl;
275     chdir $root;
276     rmove( File::Spec->catfile( 'blib', $par ), $par );
277     return 1;
278 }
279
280 =head1 AUTHOR
281
282 Sebastian Riedel, C<sri@oook.de>
283
284 =head1 LICENSE
285
286 This library is free software, you can redistribute it and/or modify it under
287 the same terms as Perl itself.
288
289 =cut
290
291 1;