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