Store the script options in the engine.
Tomas Doran [Sun, 24 Jul 2011 22:25:52 +0000 (23:25 +0100)]
Pass all normal script options by default.

This enables applications which have custom script options
(e.g. Gitalist) to get at the options the user gave at app startup,
without needed horrible code to stash the options in global or
environment variables.

lib/Catalyst.pm
lib/Catalyst/Engine.pm
lib/Catalyst/Script/FastCGI.pm
lib/Catalyst/Script/Server.pm
lib/Catalyst/ScriptRole.pm
t/aggregate/unit_core_script_cgi.t
t/aggregate/unit_core_script_fastcgi.t
t/aggregate/unit_core_script_run_options.t [new file with mode: 0644]
t/aggregate/unit_core_script_server.t
t/lib/ScriptTestApp.pm [new file with mode: 0644]
t/lib/ScriptTestApp/Controller/Root.pm [new file with mode: 0644]

index a3d8f9e..ed77ef8 100644 (file)
@@ -75,7 +75,7 @@ our $GO        = Catalyst::Exception::Go->new;
 __PACKAGE__->mk_classdata($_)
   for qw/components arguments dispatcher engine log dispatcher_class
   engine_loader context_class request_class response_class stats_class
-  setup_finished _psgi_app loading_psgi_file/;
+  setup_finished _psgi_app loading_psgi_file run_options/;
 
 __PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
 __PACKAGE__->request_class('Catalyst::Request');
@@ -1573,6 +1573,16 @@ sub welcome_message {
 EOF
 }
 
+=head2 run_options
+
+Contains a hash of options passed from the application script, including
+the original ARGV the script receieved, the processed values from that
+ARGV and any extra arguments to the script which were not processed.
+
+This can be used to add custom options to your application's scripts
+and setup your application differently depending on the values of these
+options.
+
 =head1 INTERNAL METHODS
 
 These methods are not meant to be used by end users.
index 1e56bdc..2a5f5f7 100644 (file)
@@ -833,6 +833,7 @@ sub run {
         # instead the $app->handle method is called per request.
         $app->log->warn("Not supplied a Plack engine, falling back to engine auto-loader (are your scripts ancient?)")
     }
+    $app->run_options($options);
     $server->run($psgi, $options);
 }
 
index fcc431a..ba6ab9b 100644 (file)
@@ -105,11 +105,12 @@ sub _plack_loader_args {
     return %args;
 }
 
-sub _application_args {
-    my ($self) = shift;
+around _application_args => sub {
+    my ($orig, $self) = @_;
     return (
         $self->listen,
         {
+            %{ $self->$orig },
             nproc       => $self->nproc,
             pidfile     => $self->pidfile,
             manager     => $self->manager,
@@ -118,7 +119,7 @@ sub _application_args {
             proc_title  => $self->proc_title,
         }
     );
-}
+};
 
 __PACKAGE__->meta->make_immutable;
 1;
index 1f4f80e..4e87191 100644 (file)
@@ -260,13 +260,13 @@ sub _plack_loader_args {
     );
 }
 
-sub _application_args {
-    my ($self) = shift;
+around _application_args => sub {
+    my ($orig, $self) = @_;
     return (
         $self->port,
         $self->host,
         {
-           argv => $self->ARGV,
+           %{ $self->$orig },
            map { $_ => $self->$_ } qw/
                 fork
                 keepalive
@@ -274,10 +274,12 @@ sub _application_args {
                 pidfile
                 keepalive
                 follow_symlinks
+                port
+                host
             /,
         },
     );
-}
+};
 
 __PACKAGE__->meta->make_immutable;
 1;
index e5231e7..1874ea7 100644 (file)
@@ -62,7 +62,11 @@ sub run {
 }
 
 sub _application_args {
-    ()
+    my $self = shift;
+    return {
+        argv => $self->ARGV,
+        extra_argv => $self->extra_argv,
+    }
 }
 
 sub _plack_loader_args {
@@ -71,13 +75,15 @@ sub _plack_loader_args {
     return (port => $app_args[0]);
 }
 
+sub _plack_engine_name {}
+
 sub _run_application {
     my $self = shift;
     my $app = $self->application_name;
     Class::MOP::load_class($app);
     my $server;
-    if (my $e = $self->can('_plack_engine_name') ) {
-        $server = $self->load_engine($self->$e, $self->_plack_loader_args);
+    if (my $e = $self->_plack_engine_name ) {
+        $server = $self->load_engine($e, $self->_plack_loader_args);
     }
     else {
         $server = $self->autoload_engine($self->_plack_loader_args);
index ffadb8a..697f2ad 100644 (file)
@@ -17,6 +17,8 @@ lives_ok {
 shift @TestAppToTestScripts::RUN_ARGS;
 my $server = pop @TestAppToTestScripts::RUN_ARGS;
 like ref($server), qr/^Plack::Handler/, 'Is a Plack::Handler';
-is_deeply \@TestAppToTestScripts::RUN_ARGS, [], "no args";
+is ref(delete($TestAppToTestScripts::RUN_ARGS[0]->{argv})), 'ARRAY';
+is ref(delete($TestAppToTestScripts::RUN_ARGS[0]->{extra_argv})), 'ARRAY';
+is_deeply \@TestAppToTestScripts::RUN_ARGS, [{}], "no args";
 
 done_testing;
index 2dde9d9..93f1c16 100644 (file)
@@ -37,8 +37,15 @@ sub testOption {
     } "new_with_options";
     # First element of RUN_ARGS will be the script name, which we don't care about
     shift @TestAppToTestScripts::RUN_ARGS;
+
     my $server = pop @TestAppToTestScripts::RUN_ARGS;
     is $server, $fake_handler, 'Loaded Plack handler gets passed to the app';
+
+    if (scalar(@TestAppToTestScripts::RUN_ARGS) && ref($TestAppToTestScripts::RUN_ARGS[-1]) eq "HASH") {
+        is ref(delete($TestAppToTestScripts::RUN_ARGS[-1]->{argv})), 'ARRAY';
+        is ref(delete($TestAppToTestScripts::RUN_ARGS[-1]->{extra_argv})), 'ARRAY';
+    }
+
     is_deeply \@TestAppToTestScripts::RUN_ARGS, $resultarray, "is_deeply comparison";
 }
 
diff --git a/t/aggregate/unit_core_script_run_options.t b/t/aggregate/unit_core_script_run_options.t
new file mode 100644 (file)
index 0000000..ff34a2c
--- /dev/null
@@ -0,0 +1,40 @@
+use strict;
+use warnings;
+use Test::More;
+use FindBin qw/$Bin/;
+use IO::Handle;
+use Try::Tiny;
+use File::Temp qw/ tempfile /;
+use lib "$Bin/../lib";
+
+use_ok('Catalyst::ScriptRunner');
+use_ok('ScriptTestApp');
+
+is ScriptTestApp->run_options, undef;
+
+my ($fh, $fn) = tempfile();
+
+binmode( $fh );
+binmode( STDOUT );
+
+local @ARGV = ();
+local %ENV;
+
+my $saved;
+open( $saved, '>&'. STDOUT->fileno )
+    or croak("Can't dup stdout: $!");
+open( STDOUT, '>&='. $fh->fileno )
+    or croak("Can't open stdout: $!");
+local $SIG{__WARN__} = sub {}; # Shut up warnings...
+try { Catalyst::ScriptRunner->run('ScriptTestApp', 'CGI'); pass("Ran ok") }
+catch { fail "Failed to run $_" };
+
+STDOUT->flush
+    or croak("Can't flush stdout: $!");
+
+open( STDOUT, '>&'. fileno($saved) )
+    or croak("Can't restore stdout: $!");
+
+is_deeply ScriptTestApp->run_options, { argv => [], extra_argv => [] };
+
+done_testing;
index 7cd6fb4..7121db4 100644 (file)
@@ -25,19 +25,19 @@ testOption( [ qw// ], ['3000', undef, opthash()] );
 # help           -? -help --help           -? --help
 # debug          -d -debug --debug         -d --debug
 # host           -host --host              --host
-testOption( [ qw/--host testhost/ ], ['3000', 'testhost', opthash()] );
-testOption( [ qw/-h testhost/ ], ['3000', 'testhost', opthash()] );
+testOption( [ qw/--host testhost/ ], ['3000', 'testhost', opthash(host => 'testhost')] );
+testOption( [ qw/-h testhost/ ], ['3000', 'testhost', opthash(host => 'testhost')] );
 
 # port           -p -port --port           -l --listen
-testOption( [ qw/-p 3001/ ], ['3001', undef, opthash()] );
-testOption( [ qw/--port 3001/ ], ['3001', undef, opthash()] );
+testOption( [ qw/-p 3001/ ], ['3001', undef, opthash(port => 3001)] );
+testOption( [ qw/--port 3001/ ], ['3001', undef, opthash(port => 3001)] );
 {
     local $ENV{TESTAPPTOTESTSCRIPTS_PORT} = 5000;
-    testOption( [ qw// ], [5000, undef, opthash()] );
+    testOption( [ qw// ], [5000, undef, opthash(port => 5000)] );
 }
 {
     local $ENV{CATALYST_PORT} = 5000;
-    testOption( [ qw// ], [5000, undef, opthash()] );
+    testOption( [ qw// ], [5000, undef, opthash(port => 5000)] );
 }
 
 if (try { require Starman; 1; }) {
@@ -127,9 +127,9 @@ sub testOption {
     $run_args[-1]->{pidfile} = $run_args[-1]->{pidfile}->file->stringify
       if scalar(@run_args) && $run_args[-1]->{pidfile};
 
-
     # Mangle argv into the options..
     $resultarray->[-1]->{argv} = $argstring;
+    $resultarray->[-1]->{extra_argv} = [];
     is_deeply \@run_args, $resultarray, "is_deeply comparison " . join(' ', @$argstring);
 }
 
@@ -190,6 +190,8 @@ sub opthash {
         'follow_symlinks' => 0,
         'background' => 0,
         'keepalive' => 0,
+        port => 3000,
+        host => undef,
         @_,
     };
 }
diff --git a/t/lib/ScriptTestApp.pm b/t/lib/ScriptTestApp.pm
new file mode 100644 (file)
index 0000000..c19a4e0
--- /dev/null
@@ -0,0 +1,8 @@
+package ScriptTestApp;
+use Moose;
+
+extends 'Catalyst';
+
+__PACKAGE__->setup;
+1;
+
diff --git a/t/lib/ScriptTestApp/Controller/Root.pm b/t/lib/ScriptTestApp/Controller/Root.pm
new file mode 100644 (file)
index 0000000..f88ce33
--- /dev/null
@@ -0,0 +1,10 @@
+package ScriptTestApp::Controller::Root;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller' }
+
+sub default : Chained('/') PathPart('') Args() {}
+
+1;
+