{"thread":{"id":"23844","subject":"[RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'","startedAt":"2010-05-19T17:31:38Z","lastAt":"2010-05-25T09:02:44Z","messageCount":12,"participants":["Jakub Narebski","Eric Wong","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"141916","messageId":"1274290298-19245-1-git-send-email-jnareb@gmail.com","threadId":"23844","inReplyTo":null,"subject":"[RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-19T17:31:38Z","receivedAt":"2010-05-19T17:31:38Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"PSGI is an interface between Perl web applications and web servers, and\nPlack is a Perl module and toolkit that contains PSGI middleware, helpers\nand adapters to web servers; see http://plackperl.org\n\nPSGI and Plack are inspired by Python's WSGI and Ruby's Rack.\n\nPlack core distribution includes HTTP::Server::PSGI, a reference PSGI\nstandalone web server implementation.  plackup is a command line launcher\nto run PSGI applications from command line, connecting web app to a web\nserver; it uses Plack::Runner module.  It uses HTTP::Server::PSGI as a web\nserver by default.\n\ngit-instaweb generates gitweb.psgi wrapper, which uses Plack::App::WrapCGI\nto compile a CGI script into a PSGI application using CGI::Compile and\nCGI::Emulate::PSGI, and runs it with any PSGI server as a PSGI\napplication.\n\nTo run git-instaweb with '--httpd=plackup', you need to have instaled\nPlack core, CGI::Emulate::PSGI, CGI::Compile, and available for a Perl\nscript (e.g. by setting PERL5LIB environment variable).\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nCompared to earlier version (only mentioned, but not sent to git\nmailing list, if I remember correctly), instead of configuring plackup\nfrom command line (by modifying $httpd variable), the configuration is\nembedded in generated gitweb.psgi file.  Also instead of using plackup,\nthe generated gitweb.psgi is made into standalone app, running server\n(so $full_httpd is full path to gitweb.psgi).\n\nRFC is because when when running\n\n  $ ./git-instaweb --httpd=plackup --browser=lynx\n\nI get the following error\n\n  Looking up 127.0.0.1:1234\n  Making HTTP connection to 127.0.0.1:1234\n  Alert!: Unable to connect to remote host.\n\n  lynx: Can't access startfile http://127.0.0.1:1234/\n  http://127.0.0.1:1234\n\nBut running 'lynx http://127.0.0.1:1234/' after this works correctly\nwithout problems.  Running './.git/gitweb/gitweb.psgi' doesn't cause\nany problems either.  WTF?\n\nHELP!!!\n\n Documentation/git-instaweb.txt |    2 +-\n git-instaweb.sh                |   52 +++++++++++++++++++++++++++++++++++++--\n 2 files changed, 50 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt\nindex a1f17df..2c3c4d2 100644\n--- a/Documentation/git-instaweb.txt\n+++ b/Documentation/git-instaweb.txt\n@@ -29,7 +29,7 @@ OPTIONS\n \tThe HTTP daemon command-line that will be executed.\n \tCommand-line options may be specified here, and the\n \tconfiguration file will be added at the end of the command-line.\n-\tCurrently apache2, lighttpd, mongoose and webrick are supported.\n+\tCurrently apache2, lighttpd, mongoose, plackup and webrick are supported.\n \t(Default: lighttpd)\n \n -m::\ndiff --git a/git-instaweb.sh b/git-instaweb.sh\nindex f608014..dd82955 100755\n--- a/git-instaweb.sh\n+++ b/git-instaweb.sh\n@@ -46,6 +46,13 @@ resolve_full_httpd () {\n \t\t\thttpd=\"$httpd -f\"\n \t\tfi\n \t\t;;\n+\t*plackup*)\n+\t\t# Plack::Runner etc must be in $PERL5LIB of user, currently\n+\t\t# server is started by running via generated gitweb.psgi in $fqgitdir/gitweb\n+\t\tbind=\n+\t\tfull_httpd=\"$fqgitdir/gitweb/gitweb.psgi\"\n+\t\treturn\n+\t\t;;\n \tesac\n \n \thttpd_only=\"$(echo $httpd | cut -f1 -d' ')\"\n@@ -83,9 +90,9 @@ start_httpd () {\n \n \t# don't quote $full_httpd, there can be arguments to it (-f)\n \tcase \"$httpd\" in\n-\t*mongoose*)\n-\t\t#The mongoose server doesn't have a daemon mode so we'll have to fork it\n-\t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" &\n+\t*mongoose*|*plackup*)\n+\t\t#The mongoose server and plackup don't have a daemon mode so we'll have to fork it\n+\t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" 2>\"$fqgitdir/error_log\" &\n \t\t#Save the pid before doing anything else (we'll print it later)\n \t\tpid=$!\n \n@@ -370,6 +377,42 @@ mime_types\t.gz=application/x-gzip,.tar.gz=application/x-tgz,.tgz=application/x-t\n EOF\n }\n \n+plackup_conf () {\n+\tcat > \"$fqgitdir/gitweb/gitweb.psgi\" <<GITWEB_PSGI_EOF\n+#!$PERL\n+\n+# gitweb - simple web interface to track changes in git repositories\n+#          PSGI wrapper (see http://plackperl.org)\n+\n+use strict;\n+\n+use Plack::Builder;\n+use Plack::App::WrapCGI;\n+use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb\n+\n+my \\$app = builder {\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 => \"$fqgitdir/gitweb/\";\n+\t# convert CGI application to PSGI app\n+\tPlack::App::WrapCGI->new(script => \"$fqgitdir/gitweb/gitweb.cgi\")->to_app;\n+};\n+\n+# make it runnable as standalone app, like via plackup\n+if (__FILE__ eq \\$0) {\n+\trequire Plack::Runner;\n+\n+\tmy \\$runner = Plack::Runner->new();\n+\t\\$runner->parse_options(qw(--port $port),\n+\t                       \"$local\" ? qw(--host 127.0.0.1) : ());\n+\t\\$runner->run(\\$app);\n+}\n+GITWEB_PSGI_EOF\n+\n+\tchmod a+x \"$fqgitdir/gitweb/gitweb.psgi\"\n+\trm -f \"$fqgitdir/gitweb/gitweb.psgi.tmp\" \"$conf\"\n+}\n \n script='\n s#^(my|our) \\$projectroot =.*#$1 \\$projectroot = \"'$(dirname \"$fqgitdir\")'\";#;\n@@ -419,6 +462,9 @@ webrick)\n *mongoose*)\n \tmongoose_conf\n \t;;\n+*plackup*)\n+\tplackup_conf\n+\t;;\n *)\n \techo \"Unknown httpd specified: $httpd\"\n \texit 1\n-- \n1.7.0.1\n"},{"id":"141927","messageId":"201005192252.49461.jnareb@gmail.com","threadId":"23844","inReplyTo":"1274290298-19245-1-git-send-email-jnareb@gmail.com","subject":"Re: [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-19T20:52:46Z","receivedAt":"2010-05-19T20:52:46Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Wed, 19 May 2010, Jakub Narebski wrote:\n\n> ---\n[...]\n> RFC is because when when running\n> \n>   $ ./git-instaweb --httpd=plackup --browser=lynx\n> \n> I get the following error\n> \n>   Looking up 127.0.0.1:1234\n>   Making HTTP connection to 127.0.0.1:1234\n>   Alert!: Unable to connect to remote host.\n> \n>   lynx: Can't access startfile http://127.0.0.1:1234/\n>   http://127.0.0.1:1234\n> \n> But running 'lynx http://127.0.0.1:1234/' after this works correctly\n> without problems.  Running './.git/gitweb/gitweb.psgi' doesn't cause\n> any problems either.  WTF?\n\nI think I know what might be happening here.  The plackup / Plack::Runner\nneeds some time to setup and start running HTTP::Server::PSGI based web\nserver.  When it is ready to serve requests (web pages), it prints to stderr\n\n  <server>: Accepting connections at http://<host>:<port>/\n\nIn the case of .git/gitweb/gitweb.psgi script generated by git-instaweb it\nis:\n\n  HTTP::Server::PSGI: Accepting connections at http://0:1234/\n\nBut plackup / Plack::Runner is run in background (HTTP::Server::PSGI does\nnot support '--daemonize'), and most probably the web browser is started\nbefore web server is not ready.\n\n\nDo you have any idea on how to synchronize those two processes, the web\nserver and the web client (web browser), so that web browser is run only\nafter web server prints that it is ready to accept connection?\n\nTIA.\n\n> @@ -83,9 +90,9 @@ start_httpd () {\n>  \n>  \t# don't quote $full_httpd, there can be arguments to it (-f)\n>  \tcase \"$httpd\" in\n> -\t*mongoose*)\n> -\t\t#The mongoose server doesn't have a daemon mode so we'll have to fork it\n> -\t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" &\n> +\t*mongoose*|*plackup*)\n> +\t\t#The mongoose server and plackup don't have a daemon mode so we'll have to fork it\n> +\t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" 2>\"$fqgitdir/error_log\" &\n>  \t\t#Save the pid before doing anything else (we'll print it later)\n>  \t\tpid=$!\n>  \n\n-- \nJakub Narebski\nPoland\n"},{"id":"141960","messageId":"1274356584-2400-1-git-send-email-jnareb@gmail.com","threadId":"23844","inReplyTo":"201005192252.49461.jnareb@gmail.com","subject":"[PATCHv2 (RFC)] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-20T11:56:24Z","receivedAt":"2010-05-20T11:56:24Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"PSGI is an interface between Perl web applications and web servers, and\nPlack is a Perl module and toolkit that contains PSGI middleware, helpers\nand adapters to web servers; see http://plackperl.org\n\nPSGI and Plack are inspired by Python's WSGI and Ruby's Rack.\n\nPlack core distribution includes HTTP::Server::PSGI, a reference PSGI\nstandalone web server implementation.  plackup is a command line launcher\nto run PSGI applications from command line, connecting web app to a web\nserver via Plack::Runner module.  By default it uses HTTP::Server::PSGI\nas a web server.\n\ngit-instaweb generates gitweb.psgi wrapper (in $GIT_DIR/gitweb).  This\nwrapper uses Plack::App::WrapCGI to compile gitweb.cgi (which is a CGI\nscript) into a PSGI application using CGI::Compile and CGI::Emulate::PSGI.\ngit-instaweb then runs this wrapper, using by default HTTP::Server::PSGI\nstandalone Perl server.\n\nThe configuration for 'plackup' is currently embedded in generated\ngitweb.psgi wrapper, instead of using httpd.conf ($conf).\n\n\nTo run git-instaweb with '--httpd=plackup', you need to have instaled\nPlack core, CGI::Emulate::PSGI, CGI::Compile.  Those modules have to be\navailable for Perl scripts (which can be done for example by setting\nPERL5LIB environment variable).  This is currently not documented.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nIt lives^W works!  I have added 'httpd_is_ready' function, which\nensures that server is fully started before running web browser.\nCurrently it is non-trivial only for '--httpd=plackup'.\n\n\nCurrently gitweb.psgi wrapper uses Perl she-bang line, and\nPlack::Runner module (if gitweb.psgi is run as a standalone script) to\nconfigure used PSGI server in a server-agnostic way.\n\nAttempts which didn't work or wouldn't work:\n\n* Configuring plackup via command line options, i.e. setting $httpd\n  to e.g.\n\n     httpd=\"plackup --port=$port --host=127.0.0.1\"\n\n  But this wouldn't preserve options across server restart.\n\n* Using\n\n    #!/usr/bin/env plackup --port=$port --host=127.0.0.1\n\n  as a she-bang line for gitweb.psgi wrapper.  It doesn't work because\n  (in most cases) system passes everything after interpreter name as\n  a _single_ option; in this case it would try to run\n\n    /usr/bin/env 'plackup --port=$port --host=127.0.0.1' ...\n\n  It also requires for plackup to be in $PATH.\n\n* Using\n\n    #!$PLACKUP --port=$port --host=127.0.0.1\n\n  as a she-bang line for gitweb.psgi wrapper, after finding full path\n  to 'plackup' and putting it in $PLACKUP variable (similar to $PERL).\n  It doesn't work because (in most cases) system passes everything\n  after interpreter name as a _single_ option; in this case it would\n  try to run\n\n    /path/to/plackup '--port=$port --host=127.0.0.1' ...\n\n  Well, it would work if git-instaweb is run without '--local'... \n\n Documentation/git-instaweb.txt |    2 +-\n git-instaweb.sh                |   71 +++++++++++++++++++++++++++++++++++++---\n 2 files changed, 67 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt\nindex a1f17df..2c3c4d2 100644\n--- a/Documentation/git-instaweb.txt\n+++ b/Documentation/git-instaweb.txt\n@@ -29,7 +29,7 @@ OPTIONS\n \tThe HTTP daemon command-line that will be executed.\n \tCommand-line options may be specified here, and the\n \tconfiguration file will be added at the end of the command-line.\n-\tCurrently apache2, lighttpd, mongoose and webrick are supported.\n+\tCurrently apache2, lighttpd, mongoose, plackup and webrick are supported.\n \t(Default: lighttpd)\n \n -m::\ndiff --git a/git-instaweb.sh b/git-instaweb.sh\nindex f608014..f69cb71 100755\n--- a/git-instaweb.sh\n+++ b/git-instaweb.sh\n@@ -46,6 +46,13 @@ resolve_full_httpd () {\n \t\t\thttpd=\"$httpd -f\"\n \t\tfi\n \t\t;;\n+\t*plackup*)\n+\t\t# 'plackup must be in $PATH of user, currently\n+\t\t# server is started by running via generated gitweb.psgi in $fqgitdir/gitweb\n+\t\tbind=\n+\t\tfull_httpd=\"$fqgitdir/gitweb/gitweb.psgi\"\n+\t\treturn\n+\t\t;;\n \tesac\n \n \thttpd_only=\"$(echo $httpd | cut -f1 -d' ')\"\n@@ -83,9 +90,9 @@ start_httpd () {\n \n \t# don't quote $full_httpd, there can be arguments to it (-f)\n \tcase \"$httpd\" in\n-\t*mongoose*)\n-\t\t#The mongoose server doesn't have a daemon mode so we'll have to fork it\n-\t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" &\n+\t*mongoose*|*plackup*)\n+\t\t#The mongoose server and plackup don't have a daemon mode so we'll have to fork it\n+\t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" 2>\"$fqgitdir/error_log\" &\n \t\t#Save the pid before doing anything else (we'll print it later)\n \t\tpid=$!\n \n@@ -112,6 +119,21 @@ stop_httpd () {\n \ttest -f \"$fqgitdir/pid\" && kill $(cat \"$fqgitdir/pid\")\n }\n \n+httpd_is_ready () {\n+\tcase \"$httpd\" in\n+\t*plackup*)\n+\t\techo -n \"Waiting for '$httpd' to start\"\n+\t\twhile ! grep 'Accepting connections' \"$fqgitdir/error_log\" >/dev/null 2>&1\n+\t\tdo\n+\t\t\tsleep 1\n+\t\t\techo -n \".\"\n+\t\tdone\n+\t\techo \" (done)\"\n+\t\t;;\n+\tesac\n+\ttrue\n+}\n+\n while test $# != 0\n do\n \tcase \"$1\" in\n@@ -370,6 +392,42 @@ mime_types\t.gz=application/x-gzip,.tar.gz=application/x-tgz,.tgz=application/x-t\n EOF\n }\n \n+plackup_conf () {\n+\tcat > \"$fqgitdir/gitweb/gitweb.psgi\" <<GITWEB_PSGI_EOF\n+#!$PERL\n+\n+# gitweb - simple web interface to track changes in git repositories\n+#          PSGI wrapper (see http://plackperl.org)\n+\n+use strict;\n+\n+use Plack::Builder;\n+use Plack::App::WrapCGI;\n+use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb\n+\n+my \\$app = builder {\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 => \"$fqgitdir/gitweb/\";\n+\t# convert CGI application to PSGI app\n+\tPlack::App::WrapCGI->new(script => \"$fqgitdir/gitweb/gitweb.cgi\")->to_app;\n+};\n+\n+# make it runnable as standalone app, like via plackup\n+if (__FILE__ eq \\$0) {\n+\trequire Plack::Runner;\n+\n+\tmy \\$runner = Plack::Runner->new();\n+\t\\$runner->parse_options(qw(--port $port),\n+\t                       \"$local\" ? qw(--host 127.0.0.1) : ());\n+\t\\$runner->run(\\$app);\n+}\n+GITWEB_PSGI_EOF\n+\n+\tchmod a+x \"$fqgitdir/gitweb/gitweb.psgi\"\n+\trm -f \"$fqgitdir/gitweb/gitweb.psgi.tmp\" \"$conf\"\n+}\n \n script='\n s#^(my|our) \\$projectroot =.*#$1 \\$projectroot = \"'$(dirname \"$fqgitdir\")'\";#;\n@@ -419,6 +477,9 @@ webrick)\n *mongoose*)\n \tmongoose_conf\n \t;;\n+*plackup*)\n+\tplackup_conf\n+\t;;\n *)\n \techo \"Unknown httpd specified: $httpd\"\n \texit 1\n@@ -429,7 +490,7 @@ start_httpd\n url=http://127.0.0.1:$port\n \n if test -n \"$browser\"; then\n-\tgit web--browse -b \"$browser\" $url || echo $url\n+\thttpd_is_ready && git web--browse -b \"$browser\" $url || echo $url\n else\n-\tgit web--browse -c \"instaweb.browser\" $url || echo $url\n+\thttpd_is_ready && git web--browse -c \"instaweb.browser\" $url || echo $url\n fi\n-- \n1.7.0.1\n"},{"id":"141989","messageId":"1274392538-29687-1-git-send-email-jnareb@gmail.com","threadId":"23844","inReplyTo":"1274356584-2400-1-git-send-email-jnareb@gmail.com","subject":"[RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-20T21:55:38Z","receivedAt":"2010-05-20T21:55:38Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"PSGI is an interface between Perl web applications and web servers, and\nPlack is a Perl module and toolkit that contains PSGI middleware, helpers\nand adapters to web servers; see http://plackperl.org\n\nPSGI and Plack are inspired by Python's WSGI and Ruby's Rack.\n\nPlack core distribution includes HTTP::Server::PSGI, a reference PSGI\nstandalone web server implementation.  plackup is a command line launcher\nto run PSGI applications from command line, connecting web app to a web\nserver via Plack::Runner module.  By default it uses HTTP::Server::PSGI\nas a web server.\n\ngit-instaweb generates gitweb.psgi wrapper (in $GIT_DIR/gitweb).  This\nwrapper uses Plack::App::WrapCGI to compile gitweb.cgi (which is a CGI\nscript) into a PSGI application using CGI::Compile and CGI::Emulate::PSGI.\ngit-instaweb then runs this wrapper, using by default HTTP::Server::PSGI\nstandalone Perl server.\n\nThe configuration for 'plackup' is currently embedded in generated\ngitweb.psgi wrapper, instead of using httpd.conf ($conf).\n\n\nTo run git-instaweb with '--httpd=plackup', you need to have instaled\nPlack core, CGI::Emulate::PSGI, CGI::Compile.  Those modules have to be\navailable for Perl scripts (which can be done for example by setting\nPERL5LIB environment variable).  This is currently not documented.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis is an RFC because it should be split into three patches:\n* a patch which makes git-instaweb remove pid-file after stopping server,\n* a patch adding and using httpd_is_ready function,\n* finally, a patch adding support for 'plackup' Perl web server.\n\nAlso, it somwehat lacks documentation.\n\n\nDifferences from previous version (v2):\n* Make 'plackup' / Plack::Runner run in 'deployment' mode, and not in\n  default 'development' mode.\n\n* Use generic httpd_is_ready function, which checks if web server is\n  available by checking if it connect to INET port $port on localhost.\n\n* Instead of running 'plackup' / Plack::Runner in the default development\n  mode, and redirecting its stderr to \"$fqgitdir/error_log\", use the same\n  files for access log and for error log as for other web servers.\n\n* Make if possible to run 'plackup' on HTTP::Server::Simple::PSGI, by\n  setting PLACK_SERVER environment variable to HTTP::Server::Simple,\n  even though it sets $SIG{CHLD} to 'IGNORE', which would be\n  incompatibile with gitweb (see comments in code).\n\n* A few cleanups.\n\n\n Documentation/git-instaweb.txt |    2 +-\n git-instaweb.sh                |  102 ++++++++++++++++++++++++++++++++++++++--\n 2 files changed, 99 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt\nindex a1f17df..2c3c4d2 100644\n--- a/Documentation/git-instaweb.txt\n+++ b/Documentation/git-instaweb.txt\n@@ -29,7 +29,7 @@ OPTIONS\n \tThe HTTP daemon command-line that will be executed.\n \tCommand-line options may be specified here, and the\n \tconfiguration file will be added at the end of the command-line.\n-\tCurrently apache2, lighttpd, mongoose and webrick are supported.\n+\tCurrently apache2, lighttpd, mongoose, plackup and webrick are supported.\n \t(Default: lighttpd)\n \n -m::\ndiff --git a/git-instaweb.sh b/git-instaweb.sh\nindex f608014..a198bd2 100755\n--- a/git-instaweb.sh\n+++ b/git-instaweb.sh\n@@ -46,6 +46,13 @@ resolve_full_httpd () {\n \t\t\thttpd=\"$httpd -f\"\n \t\tfi\n \t\t;;\n+\t*plackup*)\n+\t\t# 'plackup must be in $PATH of user, currently\n+\t\t# server is started by running via generated gitweb.psgi in $fqgitdir/gitweb\n+\t\tbind=\n+\t\tfull_httpd=\"$fqgitdir/gitweb/gitweb.psgi\"\n+\t\treturn\n+\t\t;;\n \tesac\n \n \thttpd_only=\"$(echo $httpd | cut -f1 -d' ')\"\n@@ -83,8 +90,8 @@ start_httpd () {\n \n \t# don't quote $full_httpd, there can be arguments to it (-f)\n \tcase \"$httpd\" in\n-\t*mongoose*)\n-\t\t#The mongoose server doesn't have a daemon mode so we'll have to fork it\n+\t*mongoose*|*plackup*)\n+\t\t#The mongoose server and plackup don't have a daemon mode so we'll have to fork it\n \t\t$full_httpd \"$fqgitdir/gitweb/httpd.conf\" &\n \t\t#Save the pid before doing anything else (we'll print it later)\n \t\tpid=$!\n@@ -110,6 +117,20 @@ EOF\n \n stop_httpd () {\n \ttest -f \"$fqgitdir/pid\" && kill $(cat \"$fqgitdir/pid\")\n+\trm -f \"$fqgitdir/pid\"\n+}\n+\n+httpd_is_ready () {\n+\t\"$PERL\" -MIO::Socket::INET -e \"\n+local \\$| = 1; # turn on autoflush\n+exit if (IO::Socket::INET->new('127.0.0.1:$port'));\n+print 'Waiting for \\'$httpd\\' to start ..';\n+do {\n+\tprint '.';\n+\tsleep(1);\n+} until (IO::Socket::INET->new('127.0.0.1:$port'));\n+print qq! (done)\\n!;\n+\"\n }\n \n while test $# != 0\n@@ -370,6 +391,76 @@ mime_types\t.gz=application/x-gzip,.tar.gz=application/x-tgz,.tgz=application/x-t\n EOF\n }\n \n+plackup_conf () {\n+\tcat > \"$fqgitdir/gitweb/gitweb.psgi\" <<GITWEB_PSGI_EOF\n+#!$PERL\n+\n+# gitweb - simple web interface to track changes in git repositories\n+#          PSGI wrapper (see http://plackperl.org)\n+\n+use strict;\n+\n+use IO::Handle;\n+use Plack::Builder;\n+use Plack::App::WrapCGI;\n+use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb\n+\n+\n+my \\$app = builder {\n+\topen my \\$access_log_fh, '>', \"$fqgitdir/gitweb/access.log\"\n+\t\tor die \"Couldn't open access log '$fqgitdir/gitweb/access.log': \\$!\";\n+\topen my \\$error_log_fh,  '>', \"$fqgitdir/gitweb/error.log\"\n+\t\tor die \"Couldn't open error log '$fqgitdir/gitweb/error.log': \\$!\";\n+\n+\t\\$access_log_fh->autoflush(1);\n+\t\\$error_log_fh->autoflush(1);\n+\n+\t# write errors to error.log, access to access.log\n+\tenable 'AccessLog',\n+\t\tformat => \"combined\",\n+\t\tlogger => sub { print \\$access_log_fh @_; };\n+\tenable sub {\n+\t\tmy \\$app = shift;\n+\t\tsub {\n+\t\t\tmy \\$env = shift;\n+\t\t\t\\$env->{'psgi.errors'} = \\$error_log_fh;\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 pipe\n+\t# (which in turn uses wait / waitpid).\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 => \"$fqgitdir/gitweb/\";\n+\t# convert CGI application to PSGI app\n+\tPlack::App::WrapCGI->new(script => \"$fqgitdir/gitweb/gitweb.cgi\")->to_app;\n+};\n+\n+# make it runnable as standalone app, like via plackup\n+if (__FILE__ eq \\$0) {\n+\trequire Plack::Runner;\n+\n+\tmy \\$runner = Plack::Runner->new();\n+\t\\$runner->parse_options(qw(--env deployment --port $port),\n+\t                       \"$local\" ? qw(--host 127.0.0.1) : ());\n+\t\\$runner->run(\\$app);\n+}\n+GITWEB_PSGI_EOF\n+\n+\tchmod a+x \"$fqgitdir/gitweb/gitweb.psgi\"\n+\trm -f \"$conf\"\n+}\n \n script='\n s#^(my|our) \\$projectroot =.*#$1 \\$projectroot = \"'$(dirname \"$fqgitdir\")'\";#;\n@@ -419,6 +510,9 @@ webrick)\n *mongoose*)\n \tmongoose_conf\n \t;;\n+*plackup*)\n+\tplackup_conf\n+\t;;\n *)\n \techo \"Unknown httpd specified: $httpd\"\n \texit 1\n@@ -429,7 +523,7 @@ start_httpd\n url=http://127.0.0.1:$port\n \n if test -n \"$browser\"; then\n-\tgit web--browse -b \"$browser\" $url || echo $url\n+\thttpd_is_ready && git web--browse -b \"$browser\" $url || echo $url\n else\n-\tgit web--browse -c \"instaweb.browser\" $url || echo $url\n+\thttpd_is_ready && git web--browse -c \"instaweb.browser\" $url || echo $url\n fi\n-- \n1.7.0.1\n"},{"id":"142119","messageId":"201005222330.43532.jnareb@gmail.com","threadId":"23844","inReplyTo":"1274392538-29687-1-git-send-email-jnareb@gmail.com","subject":"Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-22T21:30:42Z","receivedAt":"2010-05-22T21:30:42Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Thu, 20 May 2010, Jakub Narebski wrote:\n\n> The configuration for 'plackup' is currently embedded in generated\n> gitweb.psgi wrapper, instead of using httpd.conf ($conf).\n\nA question: is this solution acceptable?  Or should the configuration\n(port, address if git-instaweb was run with '--local', root) be in\na separate file.\n\nWebrick, which is in similar situation, uses httpd.conf config file in \nYAML.  Unfortunately there is no config / serialization reader in Perl\ncore, so if we have to go this route either the config file would have\nto be in Perl, or gitweb.psgi wrapper would have to include some simple\nconfig file parsing.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"142136","messageId":"20100523091812.GA3426@dcvr.yhbt.net","threadId":"23844","inReplyTo":"201005222330.43532.jnareb@gmail.com","subject":"Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2010-05-23T09:19:08Z","receivedAt":"2010-05-23T09:19:08Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Jakub Narebski <jnareb@gmail.com> wrote:\n> On Thu, 20 May 2010, Jakub Narebski wrote:\n> \n> > The configuration for 'plackup' is currently embedded in generated\n> > gitweb.psgi wrapper, instead of using httpd.conf ($conf).\n> \n> A question: is this solution acceptable?  Or should the configuration\n> (port, address if git-instaweb was run with '--local', root) be in\n> a separate file.\n\nHi Jakub,\n\nYes, the psgi wrapper is acceptable and probably ideal.\n\nMy understanding is that the .psgi file is analogous to a .ru file in\nthe (Ruby) Rack world[1], and having only a .ru file is probably how I\nwould add Rack support to git-instaweb if WEBrick weren't in Ruby\ncore[2].\n\n> Webrick, which is in similar situation, uses httpd.conf config file in \n> YAML.  Unfortunately there is no config / serialization reader in Perl\n> core, so if we have to go this route either the config file would have\n> to be in Perl, or gitweb.psgi wrapper would have to include some simple\n> config file parsing.\n\nI don't think we need parsing in the gitweb.psgi wrapper, we'll just\nconsider gitweb.psgi the config file.  This is also the case for\nRack .ru files, which can be made executable and have a shebang\npointing to \"rackup\".\n\n\n[1] - I'm not familiar with Plack/PSGI at all, but I've been dabbling\n      quite a bit in Rack over the past year or two.\n\n[2] - of course since WEBrick is in Ruby core and WEBrick supports CGI\n      scripts out-of-the-box (unlike Rack), adding Rack support to\n      instaweb would be a waste of time.\n\n-- \nEric Wong\n"},{"id":"142140","messageId":"20100523093120.GB3426@dcvr.yhbt.net","threadId":"23844","inReplyTo":"201005192252.49461.jnareb@gmail.com","subject":"Re: [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2010-05-23T09:31:20Z","receivedAt":"2010-05-23T09:31:20Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Jakub Narebski <jnareb@gmail.com> wrote:\n> Do you have any idea on how to synchronize those two processes, the web\n> server and the web client (web browser), so that web browser is run only\n> after web server prints that it is ready to accept connection?\n\nYour polling http_is_ready() function is fine, and really the only\nportable solution across all servers (and OSes).\n\nBut if your webserver lets you run arbitrary code hooks after it\nbinds the listen socket, what I do when writing integration tests\nis have it open a FIFO for writing.\n\nAdapted and abridged from the Rainbows! web server test suite, the\nfollowing config snippet is from the config file for the Rainbows! web\nserver:\n---------------- rainbows.conf.rb -----------------\nafter_fork do |server, worker|\n  # test script will block while reading from the FIFO,\n  # so notify the script on the first worker we spawn\n  # by opening the FIFO\n  if worker.nr == 0\n    File.open(\"/path/to/fifo\", \"wb\") { |fp| fp.syswrite \"START\" }\n  end\nend\n---------------------------------------------------\n\nAnd then in the test script:\n----------- my-integration-test.sh ----------------\nset -e\nmkfifo /path/to/fifo\n# start the server\nrainbows --daemonize --config-file rainbows.conf.rb\n\n# \"cat /path/to/fifo\" will block until the after_fork hook is called\n# in rainbows.conf.rb\ntest xSTART = x\"$(cat /path/to/fifo)\"\n\n# server is up, run the rest of the tests...\n---------------------------------------------------\n\n-- \nEric Wong\n"},{"id":"142146","messageId":"201005231317.08599.jnareb@gmail.com","threadId":"23844","inReplyTo":"20100523091812.GA3426@dcvr.yhbt.net","subject":"Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-23T11:17:07Z","receivedAt":"2010-05-23T11:17:07Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Sun, 23 May 2010, Eric Wong wrote:\n> Jakub Narebski <jnareb@gmail.com> wrote:\n> > On Thu, 20 May 2010, Jakub Narebski wrote:\n> > \n> > > The configuration for 'plackup' is currently embedded in generated\n> > > gitweb.psgi wrapper, instead of using httpd.conf ($conf).\n> > \n> > A question: is this solution acceptable?  Or should the configuration\n> > (port, address if git-instaweb was run with '--local', root) be in\n> > a separate file.\n> \n> Hi Jakub,\n> \n> Yes, the psgi wrapper is acceptable and probably ideal.\n> \n> My understanding is that the .psgi file is analogous to a .ru file in\n> the (Ruby) Rack world[1], and having only a .ru file is probably how I\n> would add Rack support to git-instaweb if WEBrick weren't in Ruby\n> core[2].\n\nYes, .psgi file in the (Perl) PSGI/Plack world is, as I understand it,\nanalogous to .ru file in the (Ruby) Rack world.  PSGI/Plack was inspired\nby WSGI from Python world and Rack from Ruby world.\n\nThere is no web server in Perl core, although probably HTTP::Server::Simple\nand HTTP::Engine comes close.  Well, there is HTTP::Server::Brick inspired\nby WEBrick...\n\nUsing PSGI/Plack (via wrapper around CGI) allows easily to serve\ngitweb's static files (stylesheet, images, etc.), gives persistent\nenvironment (although this probably doesn't matter much for\ngit-instaweb), and allows for easy switching between different\nPSGI-capable (e.g. via PSGI handlers) web servers, including the default\nstandalone HTTP::Server::PSGI (aka Standalone), HTTP::Server::Simple,\npreforking Starlet or Starman, currently via PLACK_SERVER environment\nvariable.\n\n> > Webrick, which is in similar situation, uses httpd.conf config file in \n> > YAML.  Unfortunately there is no config / serialization reader in Perl\n> > core, so if we have to go this route either the config file would have\n> > to be in Perl, or gitweb.psgi wrapper would have to include some simple\n> > config file parsing.\n> \n> I don't think we need parsing in the gitweb.psgi wrapper, we'll just\n> consider gitweb.psgi the config file.  \n\nWell, if it is all right, I would keep it as it is now (rebased on top\nof Pavan's work related to GSoC 2010).  If we would want to keep config\nseparate from wrapper (e.g. by installing wrappers in $(gitwebdir)\ntogether with gitweb.cgi, but keeping config files in ~/.gitweb or\n.git/gitweb), we can split it later.\n\n> This is also the case for Rack .ru files, which can be made executable\n> and have a shebang pointing to \"rackup\".\n\nWell, generated gitweb.psgi wrapper could have e.g.\n\n  #!/usr/bin/env plackup\n\nor\n\n  #!$PLACKUP\n\n(after putting full path to 'plackup' in $PLACKUP) as a she-bang line\n('plackup' is PSGI/Plack equivalent inspired by 'rackup')... if not for\nthe fact that (as I wrote earlier) different web servers supported by\n'plackup' utility have different ways of configuring them.  The common\nAPI is 'plackup' command line options.\n\nHowever in most operating systems everything after the interpreter in\nthe she-bang line is passed as *single* option, so for example\ngenerating first line of gitweb.psgi wrapper as\n\n  #!/usr/bin/evn plackup --port=1234 --host=127.0.0.1\n\nwouldn't work.  That is why I used Plack::Runner instead, the module\nbehind 'plackup'.\n\nAs a nice side effect now you don't need to have 'plackup' in $PATH; you\nonly need to have Plack::Runner in $PERL5LIB (or equivalent), but you\nneed to have other required modules there anyway.\n\n> [1] - I'm not familiar with Plack/PSGI at all, but I've been dabbling\n>       quite a bit in Rack over the past year or two.\n> \n> [2] - of course since WEBrick is in Ruby core and WEBrick supports CGI\n>       scripts out-of-the-box (unlike Rack), adding Rack support to\n>       instaweb would be a waste of time.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"142148","messageId":"AANLkTikSXOrF-mS3XzVAohgoNXXNZwN3jBw6Sh4TnK6M@mail.gmail.com","threadId":"23844","inReplyTo":"201005222330.43532.jnareb@gmail.com","subject":"Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-05-23T12:38:02Z","receivedAt":"2010-05-23T12:38:02Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"2010/5/22 Jakub Narebski <jnareb@gmail.com>:\n> Webrick, which is in similar situation, uses httpd.conf config file in\n> YAML.  Unfortunately there is no config / serialization reader in Perl\n> core, so if we have to go this route either the config file would have\n> to be in Perl, or gitweb.psgi wrapper would have to include some simple\n> config file parsing.\n\nYou could easily do (pseudocode):\n\n    unless (eval { require Config::Any; 1 }) {\n        do $conf_file;\n    } else {\n        my $parser = Config::Any->new( ... );\n         $parser->docnf( $conf_file );\n     }\n\nThen you'd read (eval) a perl config file by default, but remain\ncompatible with saner config formats for users prepared to install\nthings from the CPAN.\n"},{"id":"142155","messageId":"201005232221.36103.jnareb@gmail.com","threadId":"23844","inReplyTo":"20100523093120.GB3426@dcvr.yhbt.net","subject":"Re: [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-23T20:21:34Z","receivedAt":"2010-05-23T20:21:34Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Sun, 23 May 2010, Eric Wong wrote:\n> Jakub Narebski <jnareb@gmail.com> wrote:\n> >\n> > Do you have any idea on how to synchronize those two processes, the web\n> > server and the web client (web browser), so that web browser is run only\n> > after web server prints that it is ready to accept connection?\n> \n> Your polling http_is_ready() function is fine, and really the only\n> portable solution across all servers (and OSes).\n\nWell, even if we use the solution below it would be good fallback for\nthose web servers, for which the solution below cannot be used.\n\n> \n> But if your webserver lets you run arbitrary code hooks after it\n> binds the listen socket, what I do when writing integration tests\n> is have it open a FIFO for writing.\n\nI was thinking about 'flock' function in Perl (and similar in other\nlanguages), and '/usr/bin/flock' utility from util-linux.  But using\nFIFO as a semaphore might be a better idea: it is slighly more portable,\nI guess.\n\nAnyway, Plack handlers have (undocumented!) 'server_ready' option to web\nservers, containing callback (code reference).  It can be set via\nparse_options method of Plack::Runner, for example.  It is used by\n'plackup' to print\n\n  $server: Accepting connections at $proto://$host:$port\n\nin the (default) \"development\" mode.\n\n> \n> Adapted and abridged from the Rainbows! web server test suite, the\n> following config snippet is from the config file for the Rainbows! web\n> server:\n> ---------------- rainbows.conf.rb -----------------\n> after_fork do |server, worker|\n>   # test script will block while reading from the FIFO,\n>   # so notify the script on the first worker we spawn\n>   # by opening the FIFO\n>   if worker.nr == 0\n>     File.open(\"/path/to/fifo\", \"wb\") { |fp| fp.syswrite \"START\" }\n>   end\n> end\n> ---------------------------------------------------\n> \n> And then in the test script:\n> ----------- my-integration-test.sh ----------------\n> set -e\n> mkfifo /path/to/fifo\n> # start the server\n> rainbows --daemonize --config-file rainbows.conf.rb\n> \n> # \"cat /path/to/fifo\" will block until the after_fork hook is called\n> # in rainbows.conf.rb\n> test xSTART = x\"$(cat /path/to/fifo)\"\n> \n> # server is up, run the rest of the tests...\n> ---------------------------------------------------\n\nI wonder how portable is that technique...\n\nIt certainly could be done in gitweb.psgi; the question is if it is it\nworth it...\n\n-- \nJakub Narebski\nPoland\n"},{"id":"142224","messageId":"201005250211.04469.jnareb@gmail.com","threadId":"23844","inReplyTo":"AANLkTikSXOrF-mS3XzVAohgoNXXNZwN3jBw6Sh4TnK6M@mail.gmail.com","subject":"Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-25T00:11:02Z","receivedAt":"2010-05-25T00:11:02Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Sun, 23 May 2010, Ævar Arnfjörð Bjarmason wrote:\n> 2010/5/22 Jakub Narebski <jnareb@gmail.com>:\n> >\n> > Webrick, which is in similar situation, uses httpd.conf config file in\n> > YAML.  Unfortunately there is no config / serialization reader in Perl\n> > core, so if we have to go this route either the config file would have\n> > to be in Perl, or gitweb.psgi wrapper would have to include some simple\n> > config file parsing.\n> \n> You could easily do (pseudocode):\n> \n>     unless (eval { require Config::Any; 1 }) {\n>     \tdo $conf_file;\n>     } else {\n>     \tmy $parser = Config::Any->new( ... );\n>     \t$parser->docnf( $conf_file );\n>     }\n> \n> Then you'd read (eval) a perl config file by default, but remain\n> compatible with saner config formats for users prepared to install\n> things from the CPAN.\n\nI was thinking more about something like that:\n\n  my @opts = qw(--env deployment);\n  while (<>) {\n  \tchomp;\n  \tnext unless $_;  # skip empty lines\n  \tnext if /^\\s*#/; # skip comments\n  \tif (/^\\s*(.*?)\\s*=\\s*(.*)\\s*$/) {\n  \t\tpush @opts, '--'.lc($1), $2;\n  \t}\n  }\n\nwhere httpd.conf would look like this:\n\n  port = 1234\n  host = 127.0.0.1\n\nAnyway, if such code is to be be added, it would be added in a separate\ncommit.\n-- \nJakub Narebski\nPoland\n"},{"id":"142259","messageId":"201005251102.45182.jnareb@gmail.com","threadId":"23844","inReplyTo":"1274392538-29687-1-git-send-email-jnareb@gmail.com","subject":"Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-25T09:02:44Z","receivedAt":"2010-05-25T09:02:44Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Thu, 20 May 2010, Jakub Narebski wrote:\n> ---\n> This is an RFC because it should be split into three patches:\n> * a patch which makes git-instaweb remove pid-file after stopping server,\n> * a patch adding and using httpd_is_ready function,\n> * finally, a patch adding support for 'plackup' Perl web server.\n\nI'll wait with resending it as a patch series for Pavan work on\ngit-instaweb to be in, to not force him to do additional work on\nthe new 'plackup'-related code in git-instaweb.\n\n> \n> Also, it somwehat lacks documentation.\n\nHmmm... where should the documentation about requirements etc.\nof specific supported by git-instaweb web servers be added?\n\n-- \nJakub Narebski\nPoland\n"}]}