{"thread":{"id":"29824","subject":"[RFC/PATCH 2/5] gitweb: Prepare for splitting gitweb","startedAt":"2012-03-03T17:56:58Z","lastAt":"2012-03-08T14:06:06Z","messageCount":7,"participants":["Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"186000","messageId":"1330797423-22926-1-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":null,"subject":"[RFC/PATCH 0/5] gitweb: Proof of concept of PSGI interface","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-03T17:56:58Z","receivedAt":"2012-03-03T17:56:58Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"The major goal of this series is to make it possible for gitweb to run\nas PSGI application, even if non-native (emulated).\n\nPSGI[1][2] is an interface between Perl web applications and web servers.\nIt is accompanied by Plack, a Perl module and toolkit that contains PSGI\nmiddleware (e.g. for serving static files), helpers (e.g. 'plackup'\ncommand line launcher) and adapters to web servers (e.g. to CGI, FastCGI,\nor mod_perl).  PSGI and Plack are inspired by Python's WSGI and Ruby's Rack.\n\n[1]: http://plackperl.org\n[2]: http://search.cpan.org/perldoc?PSGI\n[3]: http://advent.plackperl.org\n\n\nFirst two patches are independent improvements, and make sense even\noutside this patch series.  Last patch is making use of gitweb as PSGI\nin \"git instaweb --httpd=plackup\".\n\n\nJakub Narebski (5):\n  gitweb: Jump do DONE_REQUEST not DONE_GITWEB on error\n  gitweb: Prepare for splitting gitweb\n  gitweb: Enable running gitweb as PSGI app, via CGI::Emulate::PSGI\n  gitweb.psgi: Allow passing arguments to Plack::Runner\n  git-instaweb: Use new PSGI interface mode of gitweb\n\n Documentation/gitweb.txt |   16 +++++++\n git-instaweb.sh          |   33 +++------------\n gitweb/INSTALL           |    3 +\n gitweb/Makefile          |   14 ++++++-\n gitweb/README            |   13 +++++-\n gitweb/gitweb.perl       |   98 +++++++++++++++++++++++++++++++++++++++++++---\n 6 files changed, 141 insertions(+), 36 deletions(-)\n\n-- \n1.7.9\n"},{"id":"186003","messageId":"1330797423-22926-2-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":"1330797423-22926-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCH 1/5] gitweb: Jump do DONE_REQUEST not DONE_GITWEB on error","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-03T17:56:59Z","receivedAt":"2012-03-03T17:56:59Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On error (die_error()), instead of ending gitweb process by non-local\njump to DONE_GITWEB label at the end of requests loop in run()\nsubroutine, just end current request by jumping to DONE_REQUESt at the\nend of run_request() subroutine.\n\nThis change should improve truly persistent deployment methods,\ncurrently only FastCGI but in the future also PSGI, as an error page\nwould no longer require reloading whole persistent environment, just\nend request.\n\nThis would allow to create new deployment mechanisms (for example\nPSGI) based on run_request() and not on run().\n\nNote that DONE_REQUEST label is removed because it is no longer used,\nand it wouldn't work correctly for PSGI anyway.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nWithout this we could not write to_psgi_app() in patch 3/5.\n\nThis patch has its value independently on PSGI support, though if it\nis to be accepted standalone, the commit message would have to be\nslighlty edited, so that the last two paragraphs of it read:\n\n \"This would allow to create new deployment mechanisms based on\n  run_request() and not on run().\n\n  DONE_REQUEST label is removed because it is no longer used.\"\n\n gitweb/gitweb.perl |    9 +++++----\n 1 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex e2e6a73..2cca2cd 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1195,6 +1195,10 @@ sub run_request {\n \tconfigure_gitweb_features();\n \n \tdispatch();\n+\n+\n+ DONE_REQUEST:\n+\t1;\n }\n \n our $is_last_request = sub { 1 };\n@@ -1252,9 +1256,6 @@ sub run {\n \n \t\tlast REQUEST if ($is_last_request->());\n \t}\n-\n- DONE_GITWEB:\n-\t1;\n }\n \n run();\n@@ -4195,7 +4196,7 @@ EOF\n \tprint \"</div>\\n\";\n \n \tgit_footer_html();\n-\tgoto DONE_GITWEB\n+\tgoto DONE_REQUEST\n \t\tunless ($opts{'-error_handler'});\n }\n \n-- \n1.7.9\n"},{"id":"185999","messageId":"1330797423-22926-3-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":"1330797423-22926-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCH 2/5] gitweb: Prepare for splitting gitweb","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-03T17:57:00Z","receivedAt":"2012-03-03T17:57:00Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Prepare gitweb for having been split into modules that are to be\ninstalled alongside gitweb in 'lib/' subdirectory, by adding\n\n  use lib __DIR__.'/lib';\n\nto gitweb.perl (to main gitweb script), and preparing for putting\nmodules (relative path) in $(GITWEB_MODULES) in gitweb/Makefile.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis patch is the beginning of splitting gitweb (with its 8000+\nlines, and more than 240kB) into modules, and is useful independently\nof being in this patch series.\n\nSidenote: it is needed for __DIR__ only here.\n\n gitweb/Makefile    |   14 +++++++++++++-\n gitweb/gitweb.perl |    8 ++++++++\n 2 files changed, 21 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/Makefile b/gitweb/Makefile\nindex cd194d0..549e7dc 100644\n--- a/gitweb/Makefile\n+++ b/gitweb/Makefile\n@@ -59,6 +59,7 @@ PERL_PATH  ?= /usr/bin/perl\n bindir_SQ = $(subst ','\\'',$(bindir))#'\n gitwebdir_SQ = $(subst ','\\'',$(gitwebdir))#'\n gitwebstaticdir_SQ = $(subst ','\\'',$(gitwebdir)/static)#'\n+gitweblibdir_SQ = $(subst ','\\'',$(gitwebdir)/lib)#'\n SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH))#'\n PERL_PATH_SQ  = $(subst ','\\'',$(PERL_PATH))#'\n DESTDIR_SQ    = $(subst ','\\'',$(DESTDIR))#'\n@@ -178,12 +179,23 @@ test-installed:\n \n ### Installation rules\n \n-install: all\n+install: all install-modules\n \t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitwebdir_SQ)'\n \t$(INSTALL) -m 755 $(GITWEB_PROGRAMS) '$(DESTDIR_SQ)$(gitwebdir_SQ)'\n \t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitwebstaticdir_SQ)'\n \t$(INSTALL) -m 644 $(GITWEB_FILES) '$(DESTDIR_SQ)$(gitwebstaticdir_SQ)'\n \n+install-modules:\n+\tinstall_dirs=\"$(sort $(dir $(GITWEB_MODULES)))\" && \\\n+\tfor dir in $$install_dirs; do \\\n+\t\ttest -d '$(DESTDIR_SQ)$(gitwebdir_SQ)/$$dir' || \\\n+\t\t$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitwebdir_SQ)/$$dir'; \\\n+\tdone\n+\tgitweb_modules=\"$(GITWEB_MODULES)\" && \\\n+\tfor mod in $$gitweb_modules; do \\\n+\t\t$(INSTALL) -m 644 $$mod '$(DESTDIR_SQ)$(gitwebdir_SQ)/$$(dirname $$mod)'; \\\n+\tdone\n+\n ### Cleaning rules\n \n clean:\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 2cca2cd..22efec2 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -10,6 +10,14 @@\n use 5.008;\n use strict;\n use warnings;\n+\n+use File::Spec;\n+# __DIR__ is taken from Dir::Self __DIR__ fragment\n+sub __DIR__ () {\n+\tFile::Spec->rel2abs(join '', (File::Spec->splitpath(__FILE__))[0, 1]);\n+}\n+use lib __DIR__ . '/lib';\n+\n use CGI qw(:standard :escapeHTML -nosticky);\n use CGI::Util qw(unescape);\n use CGI::Carp qw(fatalsToBrowser set_message);\n-- \n1.7.9\n"},{"id":"186001","messageId":"1330797423-22926-4-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":"1330797423-22926-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCH 3/5] gitweb: Enable running gitweb as PSGI app, via CGI::Emulate::PSGI","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-03T17:57:01Z","receivedAt":"2012-03-03T17:57:01Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This commit makes it possible to run gitweb as a PSGI application\n(see http://plackperl.org), using any of PSGI web servers.  This\nincludes ability to run gitweb from command line via Plack::Runner\nmodule; just run \"./gitweb.cgi --psgi\" and point web browser\nto http://0:5000\n\nGitweb uses CGI mode by default; to trigger PSGI mode one must either\npass `--psgi` or `--plackup` option to gitweb script, or the script\nmust be run with *.psgi filename (either copy/rename script, or make\nsymlink ending with *.psgi e.g. gitweb.psgi).\n\nBesides running gitweb itself, converting its run_request() from CGI\nto PSGI via CGI::Emulate::PSGI, gitweb as PSGI app also serves static\nfiles: scripts, stylesheets and images via Plack::Middleware::Static.\nCurrently it assumes that positions and URLs of those assets are left\nat their default values, namely that URLs end with \"/static/<file>\",\nand that files can be found in \"static/\" directory relative to the\ngitweb script itself.  This assumption should be relaxed in future.\n\nCurrently \"git instaweb --httpd=plackup\" doesn't (yet!) use this newly\nintroduced feature: it is left for future commit.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThe major part of this series.\n\n\"./gitweb.cgi --psgi\" runs web server on http://0:5000/\n\n Documentation/gitweb.txt |   16 +++++++++\n gitweb/INSTALL           |    3 ++\n gitweb/README            |   13 ++++++--\n gitweb/gitweb.perl       |   80 ++++++++++++++++++++++++++++++++++++++++++++-\n 4 files changed, 107 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/gitweb.txt b/Documentation/gitweb.txt\nindex 605a085..157903b 100644\n--- a/Documentation/gitweb.txt\n+++ b/Documentation/gitweb.txt\n@@ -473,6 +473,22 @@ With that configuration the full path to browse repositories would be:\n \n   http://server/gitweb\n \n+As PSGI using plackup\n+~~~~~~~~~~~~~~~~~~~~~\n+Gitweb can run as PSGI app (via emulation with *CGI::Emulate::PSGI*(3pm)).\n+First you need to rename, copy or symlink gitweb.cgi to gitweb.psgi.\n+You can run gitweb as a PSGI application from 'plackup' command line\n+utility, using any *PSGI*(3) web server (see http://plackperl.org for\n+a list), for example:\n+\n+    $ plackup --server HTTP::Server::Simple --port 8080 \\\n+      --host 127.0.0.1 gitweb.psgi\n+\n+With that configuration the full path to browse repositories would be:\n+\n+  http://127.0.0.1:8080/\n+\n+See *plackup*(1) manpage for more details.\n \n ADVANCED WEB SERVER SETUP\n -------------------------\ndiff --git a/gitweb/INSTALL b/gitweb/INSTALL\nindex 6d45406..9f55ab4 100644\n--- a/gitweb/INSTALL\n+++ b/gitweb/INSTALL\n@@ -36,6 +36,9 @@ Requirements\n The following optional Perl modules are required for extra features\n  - Digest::MD5 - for gravatar support\n  - CGI::Fast and FCGI - for running gitweb as FastCGI script\n+ - CGI::Emulate::PSGI, Plack::Builder, Plack::Middleware::Static\n+   for running gitweb as PSGI application, and Plack::Runner to\n+   make it runnable as a standalone script\n  - HTML::TagCloud - for fancy tag cloud in project list view\n  - HTTP::Date or Time::ParseDate - to support If-Modified-Since for feeds\n \ndiff --git a/gitweb/README b/gitweb/README\nindex 6da4778..a435f9b 100644\n--- a/gitweb/README\n+++ b/gitweb/README\n@@ -56,9 +56,16 @@ See also gitweb.conf(5) manpage.\n Web server configuration\n ------------------------\n Gitweb can be run as CGI script, as legacy mod_perl application (using\n-ModPerl::Registry), and as FastCGI script.  You can find some simple examples\n-in \"Example web server configuration\" section in INSTALL file for gitweb (in\n-gitweb/INSTALL).\n+ModPerl::Registry), as FastCGI script, and as PSGI application.  You\n+can find some simple examples in \"Example web server configuration\"\n+section in INSTALL file for gitweb (in gitweb/INSTALL).\n+\n+Note that to run as FastCGI script gitweb must be run with *.fcgi\n+extension or with `--fastcgi` / `--fcgi` parameter on command line.\n+To run as PSGI application gitweb must be run with *.psgi extension,\n+or with `--psgi` / `--plackup` parameter on command line, or from\n+PSGI web server which sets 'PLACK_ENV' or 'PLACK_SERVER' environment\n+variable.\n \n See \"Webserver configuration\" and \"Advanced web server setup\" sections in\n gitweb(1) manpage.\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 22efec2..0dbdd15 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1221,16 +1221,22 @@ sub configure_as_fcgi {\n \t# let each child service 100 requests\n \tour $is_last_request = sub { ++$request_number > 100 };\n }\n+sub configure_as_psgi {\n+\tour $CGI = 'PSGI'; # fake\n+}\n sub evaluate_argv {\n \tmy $script_name = $ENV{'SCRIPT_NAME'} || $ENV{'SCRIPT_FILENAME'} || __FILE__;\n \tconfigure_as_fcgi()\n \t\tif $script_name =~ /\\.fcgi$/;\n+\tconfigure_as_psgi()\n+\t\tif $script_name =~ /\\.psgi$/;\n \n \treturn unless (@ARGV);\n \n \trequire Getopt::Long;\n \tGetopt::Long::GetOptions(\n \t\t'fastcgi|fcgi|f' => \\&configure_as_fcgi,\n+\t\t'psgi|plack'     => \\&configure_as_psgi,\n \t\t'nproc|n=i' => sub {\n \t\t\tmy ($arg, $val) = @_;\n \t\t\treturn unless eval { require FCGI::ProcManager; 1; };\n@@ -1244,8 +1250,78 @@ sub evaluate_argv {\n \t);\n }\n \n+# it is very similar to run() subroutine, but it would be hard to\n+# extract common code; note that $*_hook variables can be set only\n+# for FastCGI, so they are absent here\n+sub to_psgi_app {\n+\trequire CGI::Emulate::PSGI;\n+\n+\tour $CGI = 'CGI';\n+\tour $first_request = 1;\n+\n+\tmy $app = CGI::Emulate::PSGI->handler(sub {\n+\t\tCGI::initialize_globals();\n+\t\tour $cgi = CGI->new();\n+\n+\t\trun_request();\n+\n+\t\t$first_request = 0;\n+\t});\n+\treturn $app;\n+}\n+\n+sub build_psgi_app {\n+\trequire Plack::Builder;\n+\trequire Plack::Middleware::Static;\n+\n+\tmy $sigchld_mw = sub {\n+\t\tmy $app = shift;\n+\t\tsub {\n+\t\t\tmy $env = shift;\n+\t\t\tlocal $SIG{'CHLD'} = 'DEFAULT';\n+\t\t\tlocal $SIG{'CLD'}  = 'DEFAULT';\n+\t\t\t$app->($env);\n+\t\t};\n+\t};\n+\n+\t# you're supposed to \"add\" middleware from outer to inner.\n+\t# note: Plack::Builder DSL (builder, enable_if, enable) won't work\n+\t# with \"require Plack::Builder\" outside BEGIN section.\n+\tmy $app = to_psgi_app();\n+\t$app = Plack::Middleware::Static->wrap($app,\n+\t\tpath => qr{(?:^|/)static/.*\\.(?:js|css|png)$},\n+\t\troot => __DIR__,\n+\t\tencoding => 'utf-8', # encoding for 'text/plain' files\n+\t);\n+\t$app = $sigchld_mw->($app)\n+\t\tif (defined $SIG{'CHLD'} && $SIG{'CHLD'} eq 'IGNORE');\n+\n+\treturn $app;\n+}\n+\n+sub run_psgi_app {\n+\tmy $app = build_psgi_app();\n+\n+\t# make it runnable as standalone app,\n+\t# like it would be run via 'plackup' utility.\n+\t# PLACK_ENV is set by plackup etc.\n+\tif ($ENV{'PLACK_ENV'} || $ENV{'PLACK_SERVER'}) {\n+\t\treturn $app;\n+\t}\telse {\n+\t\trequire Plack::Runner;\n+\n+\t\tmy $runner = Plack::Runner->new();\n+\t\t$runner->parse_options(qw(--env deployment),\n+\t\t                       qw(--host 127.0.0.1));\n+\t\t$runner->run($app);\n+\t}\n+}\n+\n sub run {\n \tevaluate_argv();\n+\tif ($CGI eq 'PSGI' || $ENV{'PLACK_ENV'} || $ENV{'PLACK_SERVER'}) {\n+\t\treturn run_psgi_app();\n+\t}\n \n \t$first_request = 1;\n \t$pre_listen_hook->()\n@@ -1266,12 +1342,12 @@ sub run {\n \t}\n }\n \n-run();\n+our $app = run();\n \n if (defined caller) {\n \t# wrapped in a subroutine processing requests,\n \t# e.g. mod_perl with ModPerl::Registry, or PSGI with Plack::App::WrapCGI\n-\treturn;\n+\treturn $app;\n } else {\n \t# pure CGI script, serving single request\n \texit;\n-- \n1.7.9\n"},{"id":"186004","messageId":"1330797423-22926-5-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":"1330797423-22926-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCH 4/5] gitweb.psgi: Allow passing arguments to Plack::Runner","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-03T17:57:02Z","receivedAt":"2012-03-03T17:57:02Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Command options after first '--' are passed literally to Plack::Runner\nas arguments, in addition to default ones used.  This way you can\nselect PSGI server, host, port, etc.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nCould be squashed with 4/5, now that I realized that it is that simple.\n\n gitweb/gitweb.perl |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 0dbdd15..6bd7b08 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1312,7 +1312,8 @@ sub run_psgi_app {\n \n \t\tmy $runner = Plack::Runner->new();\n \t\t$runner->parse_options(qw(--env deployment),\n-\t\t                       qw(--host 127.0.0.1));\n+\t\t                       qw(--host 127.0.0.1),\n+\t\t                       @ARGV);\n \t\t$runner->run($app);\n \t}\n }\n-- \n1.7.9\n"},{"id":"186002","messageId":"1330797423-22926-6-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":"1330797423-22926-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCH 5/5] git-instaweb: Use new PSGI interface mode of gitweb","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-03T17:57:03Z","receivedAt":"2012-03-03T17:57:03Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Now that gitweb supports PSGI interface itself, use it instead of\nPlack::App::WrapCGI.\n\nNote that gitweb as PSGI serves static files and ensures correct\nhandling of SIGCHLD, but the wrapper is still needed for logging,\nmimetype handling (probably unnecessary), and selecting host and port.\nIt is now named gitweb-wrapper.psgi and not gitweb.psgi, though.\n\nThe advantage of previous version is that it uses persistent mode\n(similar to FastCGI); important if $per_request_config is false or\ncoderef.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nShould make git-instaweb plackup mode better.\n\n git-instaweb.sh |   33 +++++++--------------------------\n 1 files changed, 7 insertions(+), 26 deletions(-)\n\ndiff --git a/git-instaweb.sh b/git-instaweb.sh\nindex 01a1b05..58e142a 100755\n--- a/git-instaweb.sh\n+++ b/git-instaweb.sh\n@@ -53,8 +53,8 @@ resolve_full_httpd () {\n \t\tfi\n \t\t;;\n \t*plackup*)\n-\t\t# server is started by running via generated gitweb.psgi in $fqgitdir/gitweb\n-\t\tfull_httpd=\"$fqgitdir/gitweb/gitweb.psgi\"\n+\t\t# server is started by running via generated gitweb-wrapper.psgi in $fqgitdir/gitweb\n+\t\tfull_httpd=\"$fqgitdir/gitweb/gitweb-wrapper.psgi\"\n \t\thttpd_only=\"${httpd%% *}\" # cut on first space\n \t\treturn\n \t\t;;\n@@ -434,7 +434,7 @@ EOF\n plackup_conf () {\n \t# generate a standalone 'plackup' server script in $fqgitdir/gitweb\n \t# with embedded configuration; it does not use \"$conf\" file\n-\tcat > \"$fqgitdir/gitweb/gitweb.psgi\" <<EOF\n+\tcat > \"$fqgitdir/gitweb/gitweb-wrapper.psgi\" <<EOF\n #!$PERL\n \n # gitweb - simple web interface to track changes in git repositories\n@@ -445,8 +445,7 @@ use strict;\n use IO::Handle;\n use Plack::MIME;\n use Plack::Builder;\n-use Plack::App::WrapCGI;\n-use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb\n+use Plack::Util;\n \n # mimetype mapping (from lighttpd_conf)\n Plack::MIME->add_type(\n@@ -538,25 +537,7 @@ my \\$app = builder {\n \t\t\t\\$app->(\\$env);\n \t\t}\n \t};\n-\t# gitweb currently doesn't work with $SIG{CHLD} set to 'IGNORE',\n-\t# because it uses 'close $fd or die...' on piped filehandle $fh\n-\t# (which causes the parent process to wait for child to finish).\n-\tenable_if { \\$SIG{'CHLD'} eq 'IGNORE' } sub {\n-\t\tmy \\$app = shift;\n-\t\tsub {\n-\t\t\tmy \\$env = shift;\n-\t\t\tlocal \\$SIG{'CHLD'} = 'DEFAULT';\n-\t\t\tlocal \\$SIG{'CLD'}  = 'DEFAULT';\n-\t\t\t\\$app->(\\$env);\n-\t\t}\n-\t};\n-\t# serve static files, i.e. stylesheet, images, script\n-\tenable 'Static',\n-\t\tpath => sub { m!\\.(js|css|png)\\$! && s!^/gitweb/!! },\n-\t\troot => \"$root/\",\n-\t\tencoding => 'utf-8'; # encoding for 'text/plain' files\n-\t# convert CGI application to PSGI app\n-\tPlack::App::WrapCGI->new(script => \"$root/gitweb.cgi\")->to_app;\n+\tPlack::Util::load_psgi(\"$root/gitweb.cgi\");\n };\n \n # make it runnable as standalone app,\n@@ -574,8 +555,8 @@ if (caller) {\n __END__\n EOF\n \n-\tchmod a+x \"$fqgitdir/gitweb/gitweb.psgi\"\n-\t# configuration is embedded in server script file, gitweb.psgi\n+\tchmod a+x \"$fqgitdir/gitweb/gitweb-wrapper.psgi\"\n+\t# configuration is embedded in server script file, gitweb-wrapper.psgi\n \trm -f \"$conf\"\n }\n \n-- \n1.7.9\n"},{"id":"186452","messageId":"1331215566-11637-1-git-send-email-jnareb@gmail.com","threadId":"29824","inReplyTo":"1330797423-22926-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCH 6/5] gitweb.psgi: Use installed static files, if they are available","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2012-03-08T14:06:06Z","receivedAt":"2012-03-08T14:06:06Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"When gitweb is running as PSGI app, it must itself take care of\nserving static files: stylesheets, script, images that are required\nto render gitweb output.\n\nThis commit makes gitweb (in PSGI mode) use installed static files\nfrom $(gitwebstaticdir) if such directory exists.  Before this commit\ngitweb served static files from 'static/' directory relative to\nposition of gitweb script itself (to __DIR__).\n\nThis allows to use gitweb in PSGI mode even if static files are\ninstalled to non-standard place.\n\nNote that mechanism of serving is slightly different: the one with\n__DIR__ uses Plack::Middleware::Static, while the installdir one uses\nURLMap-ped set of Plack::App::File.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis probably would have to be reworked, so that using Plack::Middleware::Static\nis preferred over set of Plack::App::File (which I think is slightly slower).\n\n gitweb/Makefile    |    7 +++++--\n gitweb/gitweb.perl |   38 ++++++++++++++++++++++++++++++--------\n 2 files changed, 35 insertions(+), 10 deletions(-)\n\ndiff --git a/gitweb/Makefile b/gitweb/Makefile\nindex 549e7dc..6f673ff 100644\n--- a/gitweb/Makefile\n+++ b/gitweb/Makefile\n@@ -13,6 +13,8 @@ all::\n prefix ?= $(HOME)\n bindir ?= $(prefix)/bin\n gitwebdir ?= /var/www/cgi-bin\n+gitwebstaticdir ?= $(gitwebdir)/static\n+gitweblibdir ?= $(gitwebdir)/lib\n \n RM ?= rm -f\n INSTALL ?= install\n@@ -58,8 +60,8 @@ PERL_PATH  ?= /usr/bin/perl\n # Shell quote;\n bindir_SQ = $(subst ','\\'',$(bindir))#'\n gitwebdir_SQ = $(subst ','\\'',$(gitwebdir))#'\n-gitwebstaticdir_SQ = $(subst ','\\'',$(gitwebdir)/static)#'\n-gitweblibdir_SQ = $(subst ','\\'',$(gitwebdir)/lib)#'\n+gitwebstaticdir_SQ = $(subst ','\\'',$(gitwebstaticdir))#'\n+gitweblibdir_SQ = $(subst ','\\'',$(gitweblibdir))#'\n SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH))#'\n PERL_PATH_SQ  = $(subst ','\\'',$(PERL_PATH))#'\n DESTDIR_SQ    = $(subst ','\\'',$(DESTDIR))#'\n@@ -130,6 +132,7 @@ GITWEB_JSLIB_FILES += static/js/blame_incremental.js\n GITWEB_REPLACE = \\\n \t-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \\\n \t-e 's|++GIT_BINDIR++|$(bindir)|g' \\\n+\t-e 's|++GITWEBSTATICDIR++|$(gitwebstaticdir)|g' \\\n \t-e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \\\n \t-e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \\\n \t-e 's|++GITWEB_CONFIG_COMMON++|$(GITWEB_CONFIG_COMMON)|g' \\\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 6bd7b08..f871090 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1271,9 +1271,10 @@ sub to_psgi_app {\n }\n \n sub build_psgi_app {\n-\trequire Plack::Builder;\n-\trequire Plack::Middleware::Static;\n-\n+\t# gitweb currently doesn't work with $SIG{CHLD} set to 'IGNORE',\n+\t# because it uses 'close $fd or die...' on piped filehandle $fh\n+\t# (which causes the parent process to wait for child to finish).\n+\t# this middleware is enabled only if $SIG{CHLD} is 'IGNORE'.\n \tmy $sigchld_mw = sub {\n \t\tmy $app = shift;\n \t\tsub {\n@@ -1288,14 +1289,35 @@ sub build_psgi_app {\n \t# note: Plack::Builder DSL (builder, enable_if, enable) won't work\n \t# with \"require Plack::Builder\" outside BEGIN section.\n \tmy $app = to_psgi_app();\n-\t$app = Plack::Middleware::Static->wrap($app,\n-\t\tpath => qr{(?:^|/)static/.*\\.(?:js|css|png)$},\n-\t\troot => __DIR__,\n-\t\tencoding => 'utf-8', # encoding for 'text/plain' files\n-\t);\n \t$app = $sigchld_mw->($app)\n \t\tif (defined $SIG{'CHLD'} && $SIG{'CHLD'} eq 'IGNORE');\n \n+\tif (-d \"++GITWEBSTATICDIR++\") {\n+\t\trequire Plack::App::URLMap;\n+\t\trequire Plack::App::File;\n+\n+\t\tmy $urlmap = Plack::App::URLMap->new();\n+\t\t$urlmap->map(\"/\" => $app);\n+\t\tforeach my $static_url (@stylesheets, $stylesheet, $logo, $favicon, $javascript) {\n+\t\t\tnext if (!defined $static_url || $static_url eq \"\");\n+\n+\t\t\t(my $static_file = $static_url) =~ s!^.*/!!; # basename\n+\t\t\t$static_file = \"++GITWEBSTATICDIR++/$static_file\";\n+\t\t\t$urlmap->map($static_url => Plack::App::File->new(file => $static_file));\n+\t\t}\n+\t\t$app = $urlmap->to_app();\n+\n+\t} else {\n+\t\trequire Plack::Middleware::Static;\n+\n+\t\t$app = Plack::Middleware::Static->wrap($app,\n+\t\t\tpath => qr{(?:^|/)static/.*\\.(?:js|css|png)$},\n+\t\t\troot => __DIR__,\n+\t\t\tencoding => 'utf-8', # encoding for 'text/plain' files\n+\t\t);\n+\n+\t}\n+\n \treturn $app;\n }\n \n-- \n1.7.9\n"}]}