Updated PAR support to use "make catalyst_par", packages are no longer written by...
[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 {
88     my ( $self, $par ) = @_;
89     print <<EOF;
90 *** Module::Install::Catalyst
91 EOF
92     my $name  = $self->name;
93     my $usage = $USAGE;
94     $usage =~ s/"/\\"/g;
95     my $class_string = join "', '", @CLASSES;
96     $class_string = "'$class_string'" if $class_string;
97     $self->postamble(<<EOF);
98 catalyst_par :: all
99 \t\$(NOECHO) \$(PERL) -Ilib -Minc::Module::Install -MModule::Install::Catalyst -e"Catalyst::Module::Install::_catalyst_par( '$par', '$name', { CLASSES => [$class_string], CORE => $CORE, ENGINE => '$ENGINE', MULTIARCH => $MULTIARCH, SCRIPT => '$SCRIPT', USAGE => q#$usage# } )"
100 EOF
101     print <<EOF;
102 Please run "make catalyst_par" to create the PAR package!
103 *** Module::Install::Catalyst finished.
104 EOF
105 }
106
107 =head2 catalyst_par_core($core)
108
109 =cut
110
111 sub catalyst_par_core {
112     my ( $self, $core ) = @_;
113     $core ? ( $CORE = $core ) : $CORE++;
114 }
115
116 =head2 catalyst_par_classes(@clases)
117
118 =cut
119
120 sub catalyst_par_classes {
121     my ( $self, @classes ) = @_;
122     push @CLASSES, @classes;
123 }
124
125 =head2 catalyst_par_engine($engine)
126
127 =cut
128
129 sub catalyst_par_engine {
130     my ( $self, $engine ) = @_;
131     $ENGINE = $engine;
132 }
133
134 =head2 catalyst_par_multiarch($multiarch)
135
136 =cut
137
138 sub catalyst_par_multiarch {
139     my ( $self, $multiarch ) = @_;
140     $multiarch ? ( $MULTIARCH = $multiarch ) : $MULTIARCH++;
141 }
142
143 =head2 catalyst_par_script($script)
144
145 =cut
146
147 sub catalyst_par_script {
148     my ( $self, $script ) = @_;
149     $SCRIPT = $script;
150 }
151
152 =head2 catalyst_par_usage($usage)
153
154 =cut
155
156 sub catalyst_par_usage {
157     my ( $self, $usage ) = @_;
158     $USAGE = $usage;
159 }
160
161 package Catalyst::Module::Install;
162
163 use strict;
164 use FindBin;
165 use File::Copy::Recursive 'rmove';
166 use File::Spec ();
167
168 sub _catalyst_par {
169     my ( $par, $class_name, $opts ) = @_;
170
171     my $ENGINE    = $opts->{ENGINE};
172     my $CLASSES   = $opts->{CLASSES} || [];
173     my $USAGE     = $opts->{USAGE};
174     my $SCRIPT    = $opts->{SCRIPT};
175     my $MULTIARCH = $opts->{MULTIARCH};
176     my $CORE      = $opts->{CORE};
177
178     my $name = $class_name;
179     $name =~ s/::/_/g;
180     $name = lc $name;
181     $par ||= "$name.par";
182     my $engine = $ENGINE || 'CGI';
183
184     # Check for PAR
185     eval "use PAR ()";
186     die "Please install PAR\n" if $@;
187     eval "use PAR::Packer ()";
188     die "Please install PAR::Packer\n" if $@;
189     eval "use App::Packer::PAR ()";
190     die "Please install App::Packer::PAR\n" if $@;
191     eval "use Module::ScanDeps ()";
192     die "Please install Module::ScanDeps\n" if $@;
193
194     my $root = $FindBin::Bin;
195     my $path = File::Spec->catfile( 'blib', 'lib', split( '::', $class_name ) );
196     $path .= '.pm';
197     unless ( -f $path ) {
198         print qq/Not writing PAR, "$path" doesn't exist\n/;
199         return 0;
200     }
201     print qq/Writing PAR "$par"\n/;
202     chdir File::Spec->catdir( $root, 'blib' );
203
204     my $par_pl = 'par.pl';
205     unlink $par_pl;
206
207     my $version = $Catalyst::VERSION;
208     my $class   = $class_name;
209
210     my $classes = '';
211     $classes .= "    require $_;\n" for @$CLASSES;
212
213     unlink $par_pl;
214
215     my $usage = $USAGE || <<"EOF";
216 Usage:
217     [parl] $name\[.par] [script] [arguments]
218
219   Examples:
220     parl $name.par $name\_server.pl -r
221     myapp $name\_cgi.pl
222 EOF
223
224     my $script   = $SCRIPT;
225     my $tmp_file = IO::File->new("> $par_pl ");
226     print $tmp_file <<"EOF";
227 if ( \$ENV{PAR_PROGNAME} ) {
228     my \$zip = \$PAR::LibCache{\$ENV{PAR_PROGNAME}}
229         || Archive::Zip->new(__FILE__);
230     my \$script = '$script';
231     \$ARGV[0] ||= \$script if \$script;
232     if ( ( \@ARGV == 0 ) || ( \$ARGV[0] eq '-h' ) || ( \$ARGV[0] eq '-help' )) {
233         my \@members = \$zip->membersMatching('.*script/.*\.pl');
234         my \$list = "  Available scripts:\\n";
235         for my \$member ( \@members ) {
236             my \$name = \$member->fileName;
237             \$name =~ /(\\w+\\.pl)\$/;
238             \$name = \$1;
239             next if \$name =~ /^main\.pl\$/;
240             next if \$name =~ /^par\.pl\$/;
241             \$list .= "    \$name\\n";
242         }
243         die <<"END";
244 $usage
245 \$list
246 END
247     }
248     my \$file = shift \@ARGV;
249     \$file =~ s/^.*[\\/\\\\]//;
250     \$file =~ s/\\.[^.]*\$//i;
251     my \$member = eval { \$zip->memberNamed("./script/\$file.pl") };
252     die qq/Can't open perl script "\$file"\n/ unless \$member;
253     PAR::_run_member( \$member, 1 );
254 }
255 else {
256     require lib;
257     import lib 'lib';
258     \$ENV{CATALYST_ENGINE} = '$engine';
259     require $class;
260     import $class;
261     require Catalyst::Helper;
262     require Catalyst::Test;
263     require Catalyst::Engine::HTTP;
264     require Catalyst::Engine::CGI;
265     require Catalyst::Controller;
266     require Catalyst::Model;
267     require Catalyst::View;
268     require Getopt::Long;
269     require Pod::Usage;
270     require Pod::Text;
271     $classes
272 }
273 EOF
274     $tmp_file->close;
275
276     # Create package
277     local $SIG{__WARN__} = sub { };
278     open my $olderr, '>&STDERR';
279     open STDERR, '>', File::Spec->devnull;
280     my %opt = (
281         'x' => 1,
282         'n' => 0,
283         'o' => $par,
284         'a' => [ grep( !/par.pl/, glob '.' ) ],
285         'p' => 1,
286         'B' => $CORE,
287         'm' => $MULTIARCH
288     );
289     App::Packer::PAR->new(
290         frontend  => 'Module::ScanDeps',
291         backend   => 'PAR::Packer',
292         frontopts => \%opt,
293         backopts  => \%opt,
294         args      => ['par.pl'],
295     )->go;
296
297     open STDERR, '>&', $olderr;
298
299     unlink $par_pl;
300     chdir $root;
301     rmove( File::Spec->catfile( 'blib', $par ), $par );
302     return 1;
303 }
304
305 =head1 AUTHOR
306
307 Sebastian Riedel, C<sri@oook.de>
308
309 =head1 LICENSE
310
311 This library is free software, you can redistribute it and/or modify it under
312 the same terms as Perl itself.
313
314 =cut
315
316 1;