From: Jakub Narebski <jnareb@gmail.com>
To: git@vger.kernel.org
Cc: Jakub Narebski <jnareb@gmail.com>, Eric Wong <normalperson@yhbt.net>
Subject: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'
Date: Thu, 20 May 2010 23:55:38 +0200 [thread overview]
Message-ID: <1274392538-29687-1-git-send-email-jnareb@gmail.com> (raw)
In-Reply-To: <1274356584-2400-1-git-send-email-jnareb@gmail.com>
PSGI is an interface between Perl web applications and web servers, and
Plack is a Perl module and toolkit that contains PSGI middleware, helpers
and adapters to web servers; see http://plackperl.org
PSGI and Plack are inspired by Python's WSGI and Ruby's Rack.
Plack core distribution includes HTTP::Server::PSGI, a reference PSGI
standalone web server implementation. plackup is a command line launcher
to run PSGI applications from command line, connecting web app to a web
server via Plack::Runner module. By default it uses HTTP::Server::PSGI
as a web server.
git-instaweb generates gitweb.psgi wrapper (in $GIT_DIR/gitweb). This
wrapper uses Plack::App::WrapCGI to compile gitweb.cgi (which is a CGI
script) into a PSGI application using CGI::Compile and CGI::Emulate::PSGI.
git-instaweb then runs this wrapper, using by default HTTP::Server::PSGI
standalone Perl server.
The configuration for 'plackup' is currently embedded in generated
gitweb.psgi wrapper, instead of using httpd.conf ($conf).
To run git-instaweb with '--httpd=plackup', you need to have instaled
Plack core, CGI::Emulate::PSGI, CGI::Compile. Those modules have to be
available for Perl scripts (which can be done for example by setting
PERL5LIB environment variable). This is currently not documented.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This is an RFC because it should be split into three patches:
* a patch which makes git-instaweb remove pid-file after stopping server,
* a patch adding and using httpd_is_ready function,
* finally, a patch adding support for 'plackup' Perl web server.
Also, it somwehat lacks documentation.
Differences from previous version (v2):
* Make 'plackup' / Plack::Runner run in 'deployment' mode, and not in
default 'development' mode.
* Use generic httpd_is_ready function, which checks if web server is
available by checking if it connect to INET port $port on localhost.
* Instead of running 'plackup' / Plack::Runner in the default development
mode, and redirecting its stderr to "$fqgitdir/error_log", use the same
files for access log and for error log as for other web servers.
* Make if possible to run 'plackup' on HTTP::Server::Simple::PSGI, by
setting PLACK_SERVER environment variable to HTTP::Server::Simple,
even though it sets $SIG{CHLD} to 'IGNORE', which would be
incompatibile with gitweb (see comments in code).
* A few cleanups.
Documentation/git-instaweb.txt | 2 +-
git-instaweb.sh | 102 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 99 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt
index a1f17df..2c3c4d2 100644
--- a/Documentation/git-instaweb.txt
+++ b/Documentation/git-instaweb.txt
@@ -29,7 +29,7 @@ OPTIONS
The HTTP daemon command-line that will be executed.
Command-line options may be specified here, and the
configuration file will be added at the end of the command-line.
- Currently apache2, lighttpd, mongoose and webrick are supported.
+ Currently apache2, lighttpd, mongoose, plackup and webrick are supported.
(Default: lighttpd)
-m::
diff --git a/git-instaweb.sh b/git-instaweb.sh
index f608014..a198bd2 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -46,6 +46,13 @@ resolve_full_httpd () {
httpd="$httpd -f"
fi
;;
+ *plackup*)
+ # 'plackup must be in $PATH of user, currently
+ # server is started by running via generated gitweb.psgi in $fqgitdir/gitweb
+ bind=
+ full_httpd="$fqgitdir/gitweb/gitweb.psgi"
+ return
+ ;;
esac
httpd_only="$(echo $httpd | cut -f1 -d' ')"
@@ -83,8 +90,8 @@ start_httpd () {
# don't quote $full_httpd, there can be arguments to it (-f)
case "$httpd" in
- *mongoose*)
- #The mongoose server doesn't have a daemon mode so we'll have to fork it
+ *mongoose*|*plackup*)
+ #The mongoose server and plackup don't have a daemon mode so we'll have to fork it
$full_httpd "$fqgitdir/gitweb/httpd.conf" &
#Save the pid before doing anything else (we'll print it later)
pid=$!
@@ -110,6 +117,20 @@ EOF
stop_httpd () {
test -f "$fqgitdir/pid" && kill $(cat "$fqgitdir/pid")
+ rm -f "$fqgitdir/pid"
+}
+
+httpd_is_ready () {
+ "$PERL" -MIO::Socket::INET -e "
+local \$| = 1; # turn on autoflush
+exit if (IO::Socket::INET->new('127.0.0.1:$port'));
+print 'Waiting for \'$httpd\' to start ..';
+do {
+ print '.';
+ sleep(1);
+} until (IO::Socket::INET->new('127.0.0.1:$port'));
+print qq! (done)\n!;
+"
}
while test $# != 0
@@ -370,6 +391,76 @@ mime_types .gz=application/x-gzip,.tar.gz=application/x-tgz,.tgz=application/x-t
EOF
}
+plackup_conf () {
+ cat > "$fqgitdir/gitweb/gitweb.psgi" <<GITWEB_PSGI_EOF
+#!$PERL
+
+# gitweb - simple web interface to track changes in git repositories
+# PSGI wrapper (see http://plackperl.org)
+
+use strict;
+
+use IO::Handle;
+use Plack::Builder;
+use Plack::App::WrapCGI;
+use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb
+
+
+my \$app = builder {
+ open my \$access_log_fh, '>', "$fqgitdir/gitweb/access.log"
+ or die "Couldn't open access log '$fqgitdir/gitweb/access.log': \$!";
+ open my \$error_log_fh, '>', "$fqgitdir/gitweb/error.log"
+ or die "Couldn't open error log '$fqgitdir/gitweb/error.log': \$!";
+
+ \$access_log_fh->autoflush(1);
+ \$error_log_fh->autoflush(1);
+
+ # write errors to error.log, access to access.log
+ enable 'AccessLog',
+ format => "combined",
+ logger => sub { print \$access_log_fh @_; };
+ enable sub {
+ my \$app = shift;
+ sub {
+ my \$env = shift;
+ \$env->{'psgi.errors'} = \$error_log_fh;
+ \$app->(\$env);
+ }
+ };
+ # gitweb currently doesn't work with $SIG{CHLD} set to 'IGNORE',
+ # because it uses 'close $fd or die...' on pipe
+ # (which in turn uses wait / waitpid).
+ enable_if { \$SIG{'CHLD'} eq 'IGNORE' } sub {
+ my \$app = shift;
+ sub {
+ my \$env = shift;
+ local \$SIG{'CHLD'} = 'DEFAULT';
+ local \$SIG{'CLD'} = 'DEFAULT';
+ \$app->(\$env);
+ }
+ };
+ # serve static files, i.e. stylesheet, images, script
+ enable 'Static',
+ path => sub { m!\.(js|css|png)\$! && s!^/gitweb/!! },
+ root => "$fqgitdir/gitweb/";
+ # convert CGI application to PSGI app
+ Plack::App::WrapCGI->new(script => "$fqgitdir/gitweb/gitweb.cgi")->to_app;
+};
+
+# make it runnable as standalone app, like via plackup
+if (__FILE__ eq \$0) {
+ require Plack::Runner;
+
+ my \$runner = Plack::Runner->new();
+ \$runner->parse_options(qw(--env deployment --port $port),
+ "$local" ? qw(--host 127.0.0.1) : ());
+ \$runner->run(\$app);
+}
+GITWEB_PSGI_EOF
+
+ chmod a+x "$fqgitdir/gitweb/gitweb.psgi"
+ rm -f "$conf"
+}
script='
s#^(my|our) \$projectroot =.*#$1 \$projectroot = "'$(dirname "$fqgitdir")'";#;
@@ -419,6 +510,9 @@ webrick)
*mongoose*)
mongoose_conf
;;
+*plackup*)
+ plackup_conf
+ ;;
*)
echo "Unknown httpd specified: $httpd"
exit 1
@@ -429,7 +523,7 @@ start_httpd
url=http://127.0.0.1:$port
if test -n "$browser"; then
- git web--browse -b "$browser" $url || echo $url
+ httpd_is_ready && git web--browse -b "$browser" $url || echo $url
else
- git web--browse -c "instaweb.browser" $url || echo $url
+ httpd_is_ready && git web--browse -c "instaweb.browser" $url || echo $url
fi
--
1.7.0.1
next prev parent reply other threads:[~2010-05-20 21:54 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-19 17:31 [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup' Jakub Narebski
2010-05-19 20:52 ` Jakub Narebski
2010-05-20 11:56 ` [PATCHv2 (RFC)] " Jakub Narebski
2010-05-20 21:55 ` Jakub Narebski [this message]
2010-05-22 21:30 ` [RFC/PATCHv3] " Jakub Narebski
2010-05-23 9:19 ` Eric Wong
2010-05-23 11:17 ` Jakub Narebski
2010-05-23 12:38 ` Ævar Arnfjörð Bjarmason
2010-05-25 0:11 ` Jakub Narebski
2010-05-25 9:02 ` Jakub Narebski
2010-05-23 9:31 ` [RFC/PATCH] " Eric Wong
2010-05-23 20:21 ` Jakub Narebski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1274392538-29687-1-git-send-email-jnareb@gmail.com \
--to=jnareb@gmail.com \
--cc=git@vger.kernel.org \
--cc=normalperson@yhbt.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).