git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'
@ 2010-05-19 17:31 Jakub Narebski
  2010-05-19 20:52 ` Jakub Narebski
  0 siblings, 1 reply; 12+ messages in thread
From: Jakub Narebski @ 2010-05-19 17:31 UTC (permalink / raw
  To: git; +Cc: Jakub Narebski, Eric Wong

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; it uses Plack::Runner module.  It uses HTTP::Server::PSGI as a web
server by default.

git-instaweb generates gitweb.psgi wrapper, which uses Plack::App::WrapCGI
to compile a CGI script into a PSGI application using CGI::Compile and
CGI::Emulate::PSGI, and runs it with any PSGI server as a PSGI
application.

To run git-instaweb with '--httpd=plackup', you need to have instaled
Plack core, CGI::Emulate::PSGI, CGI::Compile, and available for a Perl
script (e.g. by setting PERL5LIB environment variable).

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Compared to earlier version (only mentioned, but not sent to git
mailing list, if I remember correctly), instead of configuring plackup
from command line (by modifying $httpd variable), the configuration is
embedded in generated gitweb.psgi file.  Also instead of using plackup,
the generated gitweb.psgi is made into standalone app, running server
(so $full_httpd is full path to gitweb.psgi).

RFC is because when when running

  $ ./git-instaweb --httpd=plackup --browser=lynx

I get the following error

  Looking up 127.0.0.1:1234
  Making HTTP connection to 127.0.0.1:1234
  Alert!: Unable to connect to remote host.

  lynx: Can't access startfile http://127.0.0.1:1234/
  http://127.0.0.1:1234

But running 'lynx http://127.0.0.1:1234/' after this works correctly
without problems.  Running './.git/gitweb/gitweb.psgi' doesn't cause
any problems either.  WTF?

HELP!!!

 Documentation/git-instaweb.txt |    2 +-
 git-instaweb.sh                |   52 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 4 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..dd82955 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -46,6 +46,13 @@ resolve_full_httpd () {
 			httpd="$httpd -f"
 		fi
 		;;
+	*plackup*)
+		# Plack::Runner etc must be in $PERL5LIB 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,9 +90,9 @@ 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
-		$full_httpd "$fqgitdir/gitweb/httpd.conf" &
+	*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" 2>"$fqgitdir/error_log" &
 		#Save the pid before doing anything else (we'll print it later)
 		pid=$!
 
@@ -370,6 +377,42 @@ 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 Plack::Builder;
+use Plack::App::WrapCGI;
+use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb
+
+my \$app = builder {
+	# 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(--port $port),
+	                       "$local" ? qw(--host 127.0.0.1) : ());
+	\$runner->run(\$app);
+}
+GITWEB_PSGI_EOF
+
+	chmod a+x "$fqgitdir/gitweb/gitweb.psgi"
+	rm -f "$fqgitdir/gitweb/gitweb.psgi.tmp" "$conf"
+}
 
 script='
 s#^(my|our) \$projectroot =.*#$1 \$projectroot = "'$(dirname "$fqgitdir")'";#;
@@ -419,6 +462,9 @@ webrick)
 *mongoose*)
 	mongoose_conf
 	;;
+*plackup*)
+	plackup_conf
+	;;
 *)
 	echo "Unknown httpd specified: $httpd"
 	exit 1
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'
  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-23  9:31   ` [RFC/PATCH] " Eric Wong
  0 siblings, 2 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-19 20:52 UTC (permalink / raw
  To: git; +Cc: Eric Wong

On Wed, 19 May 2010, Jakub Narebski wrote:

> ---
[...]
> RFC is because when when running
> 
>   $ ./git-instaweb --httpd=plackup --browser=lynx
> 
> I get the following error
> 
>   Looking up 127.0.0.1:1234
>   Making HTTP connection to 127.0.0.1:1234
>   Alert!: Unable to connect to remote host.
> 
>   lynx: Can't access startfile http://127.0.0.1:1234/
>   http://127.0.0.1:1234
> 
> But running 'lynx http://127.0.0.1:1234/' after this works correctly
> without problems.  Running './.git/gitweb/gitweb.psgi' doesn't cause
> any problems either.  WTF?

I think I know what might be happening here.  The plackup / Plack::Runner
needs some time to setup and start running HTTP::Server::PSGI based web
server.  When it is ready to serve requests (web pages), it prints to stderr

  <server>: Accepting connections at http://<host>:<port>/

In the case of .git/gitweb/gitweb.psgi script generated by git-instaweb it
is:

  HTTP::Server::PSGI: Accepting connections at http://0:1234/

But plackup / Plack::Runner is run in background (HTTP::Server::PSGI does
not support '--daemonize'), and most probably the web browser is started
before web server is not ready.


Do you have any idea on how to synchronize those two processes, the web
server and the web client (web browser), so that web browser is run only
after web server prints that it is ready to accept connection?

TIA.

> @@ -83,9 +90,9 @@ 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
> -		$full_httpd "$fqgitdir/gitweb/httpd.conf" &
> +	*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" 2>"$fqgitdir/error_log" &
>  		#Save the pid before doing anything else (we'll print it later)
>  		pid=$!
>  

-- 
Jakub Narebski
Poland

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCHv2 (RFC)] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-19 20:52 ` Jakub Narebski
@ 2010-05-20 11:56   ` Jakub Narebski
  2010-05-20 21:55     ` [RFC/PATCHv3] " Jakub Narebski
  2010-05-23  9:31   ` [RFC/PATCH] " Eric Wong
  1 sibling, 1 reply; 12+ messages in thread
From: Jakub Narebski @ 2010-05-20 11:56 UTC (permalink / raw
  To: git; +Cc: Jakub Narebski, Eric Wong

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>
---
It lives^W works!  I have added 'httpd_is_ready' function, which
ensures that server is fully started before running web browser.
Currently it is non-trivial only for '--httpd=plackup'.


Currently gitweb.psgi wrapper uses Perl she-bang line, and
Plack::Runner module (if gitweb.psgi is run as a standalone script) to
configure used PSGI server in a server-agnostic way.

Attempts which didn't work or wouldn't work:

* Configuring plackup via command line options, i.e. setting $httpd
  to e.g.

     httpd="plackup --port=$port --host=127.0.0.1"

  But this wouldn't preserve options across server restart.

* Using

    #!/usr/bin/env plackup --port=$port --host=127.0.0.1

  as a she-bang line for gitweb.psgi wrapper.  It doesn't work because
  (in most cases) system passes everything after interpreter name as
  a _single_ option; in this case it would try to run

    /usr/bin/env 'plackup --port=$port --host=127.0.0.1' ...

  It also requires for plackup to be in $PATH.

* Using

    #!$PLACKUP --port=$port --host=127.0.0.1

  as a she-bang line for gitweb.psgi wrapper, after finding full path
  to 'plackup' and putting it in $PLACKUP variable (similar to $PERL).
  It doesn't work because (in most cases) system passes everything
  after interpreter name as a _single_ option; in this case it would
  try to run

    /path/to/plackup '--port=$port --host=127.0.0.1' ...

  Well, it would work if git-instaweb is run without '--local'... 

 Documentation/git-instaweb.txt |    2 +-
 git-instaweb.sh                |   71 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 67 insertions(+), 6 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..f69cb71 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,9 +90,9 @@ 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
-		$full_httpd "$fqgitdir/gitweb/httpd.conf" &
+	*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" 2>"$fqgitdir/error_log" &
 		#Save the pid before doing anything else (we'll print it later)
 		pid=$!
 
@@ -112,6 +119,21 @@ stop_httpd () {
 	test -f "$fqgitdir/pid" && kill $(cat "$fqgitdir/pid")
 }
 
+httpd_is_ready () {
+	case "$httpd" in
+	*plackup*)
+		echo -n "Waiting for '$httpd' to start"
+		while ! grep 'Accepting connections' "$fqgitdir/error_log" >/dev/null 2>&1
+		do
+			sleep 1
+			echo -n "."
+		done
+		echo " (done)"
+		;;
+	esac
+	true
+}
+
 while test $# != 0
 do
 	case "$1" in
@@ -370,6 +392,42 @@ 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 Plack::Builder;
+use Plack::App::WrapCGI;
+use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb
+
+my \$app = builder {
+	# 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(--port $port),
+	                       "$local" ? qw(--host 127.0.0.1) : ());
+	\$runner->run(\$app);
+}
+GITWEB_PSGI_EOF
+
+	chmod a+x "$fqgitdir/gitweb/gitweb.psgi"
+	rm -f "$fqgitdir/gitweb/gitweb.psgi.tmp" "$conf"
+}
 
 script='
 s#^(my|our) \$projectroot =.*#$1 \$projectroot = "'$(dirname "$fqgitdir")'";#;
@@ -419,6 +477,9 @@ webrick)
 *mongoose*)
 	mongoose_conf
 	;;
+*plackup*)
+	plackup_conf
+	;;
 *)
 	echo "Unknown httpd specified: $httpd"
 	exit 1
@@ -429,7 +490,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

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-20 11:56   ` [PATCHv2 (RFC)] " Jakub Narebski
@ 2010-05-20 21:55     ` Jakub Narebski
  2010-05-22 21:30       ` Jakub Narebski
  2010-05-25  9:02       ` Jakub Narebski
  0 siblings, 2 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-20 21:55 UTC (permalink / raw
  To: git; +Cc: Jakub Narebski, Eric Wong

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

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-20 21:55     ` [RFC/PATCHv3] " Jakub Narebski
@ 2010-05-22 21:30       ` Jakub Narebski
  2010-05-23  9:19         ` Eric Wong
  2010-05-23 12:38         ` Ævar Arnfjörð Bjarmason
  2010-05-25  9:02       ` Jakub Narebski
  1 sibling, 2 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-22 21:30 UTC (permalink / raw
  To: git; +Cc: Eric Wong

On Thu, 20 May 2010, Jakub Narebski wrote:

> The configuration for 'plackup' is currently embedded in generated
> gitweb.psgi wrapper, instead of using httpd.conf ($conf).

A question: is this solution acceptable?  Or should the configuration
(port, address if git-instaweb was run with '--local', root) be in
a separate file.

Webrick, which is in similar situation, uses httpd.conf config file in 
YAML.  Unfortunately there is no config / serialization reader in Perl
core, so if we have to go this route either the config file would have
to be in Perl, or gitweb.psgi wrapper would have to include some simple
config file parsing.

-- 
Jakub Narebski
Poland

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-22 21:30       ` 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
  1 sibling, 1 reply; 12+ messages in thread
From: Eric Wong @ 2010-05-23  9:19 UTC (permalink / raw
  To: Jakub Narebski; +Cc: git

Jakub Narebski <jnareb@gmail.com> wrote:
> On Thu, 20 May 2010, Jakub Narebski wrote:
> 
> > The configuration for 'plackup' is currently embedded in generated
> > gitweb.psgi wrapper, instead of using httpd.conf ($conf).
> 
> A question: is this solution acceptable?  Or should the configuration
> (port, address if git-instaweb was run with '--local', root) be in
> a separate file.

Hi Jakub,

Yes, the psgi wrapper is acceptable and probably ideal.

My understanding is that the .psgi file is analogous to a .ru file in
the (Ruby) Rack world[1], and having only a .ru file is probably how I
would add Rack support to git-instaweb if WEBrick weren't in Ruby
core[2].

> Webrick, which is in similar situation, uses httpd.conf config file in 
> YAML.  Unfortunately there is no config / serialization reader in Perl
> core, so if we have to go this route either the config file would have
> to be in Perl, or gitweb.psgi wrapper would have to include some simple
> config file parsing.

I don't think we need parsing in the gitweb.psgi wrapper, we'll just
consider gitweb.psgi the config file.  This is also the case for
Rack .ru files, which can be made executable and have a shebang
pointing to "rackup".


[1] - I'm not familiar with Plack/PSGI at all, but I've been dabbling
      quite a bit in Rack over the past year or two.

[2] - of course since WEBrick is in Ruby core and WEBrick supports CGI
      scripts out-of-the-box (unlike Rack), adding Rack support to
      instaweb would be a waste of time.

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-19 20:52 ` Jakub Narebski
  2010-05-20 11:56   ` [PATCHv2 (RFC)] " Jakub Narebski
@ 2010-05-23  9:31   ` Eric Wong
  2010-05-23 20:21     ` Jakub Narebski
  1 sibling, 1 reply; 12+ messages in thread
From: Eric Wong @ 2010-05-23  9:31 UTC (permalink / raw
  To: Jakub Narebski; +Cc: git

Jakub Narebski <jnareb@gmail.com> wrote:
> Do you have any idea on how to synchronize those two processes, the web
> server and the web client (web browser), so that web browser is run only
> after web server prints that it is ready to accept connection?

Your polling http_is_ready() function is fine, and really the only
portable solution across all servers (and OSes).

But if your webserver lets you run arbitrary code hooks after it
binds the listen socket, what I do when writing integration tests
is have it open a FIFO for writing.

Adapted and abridged from the Rainbows! web server test suite, the
following config snippet is from the config file for the Rainbows! web
server:
---------------- rainbows.conf.rb -----------------
after_fork do |server, worker|
  # test script will block while reading from the FIFO,
  # so notify the script on the first worker we spawn
  # by opening the FIFO
  if worker.nr == 0
    File.open("/path/to/fifo", "wb") { |fp| fp.syswrite "START" }
  end
end
---------------------------------------------------

And then in the test script:
----------- my-integration-test.sh ----------------
set -e
mkfifo /path/to/fifo
# start the server
rainbows --daemonize --config-file rainbows.conf.rb

# "cat /path/to/fifo" will block until the after_fork hook is called
# in rainbows.conf.rb
test xSTART = x"$(cat /path/to/fifo)"

# server is up, run the rest of the tests...
---------------------------------------------------

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-23  9:19         ` Eric Wong
@ 2010-05-23 11:17           ` Jakub Narebski
  0 siblings, 0 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-23 11:17 UTC (permalink / raw
  To: Eric Wong; +Cc: git

On Sun, 23 May 2010, Eric Wong wrote:
> Jakub Narebski <jnareb@gmail.com> wrote:
> > On Thu, 20 May 2010, Jakub Narebski wrote:
> > 
> > > The configuration for 'plackup' is currently embedded in generated
> > > gitweb.psgi wrapper, instead of using httpd.conf ($conf).
> > 
> > A question: is this solution acceptable?  Or should the configuration
> > (port, address if git-instaweb was run with '--local', root) be in
> > a separate file.
> 
> Hi Jakub,
> 
> Yes, the psgi wrapper is acceptable and probably ideal.
> 
> My understanding is that the .psgi file is analogous to a .ru file in
> the (Ruby) Rack world[1], and having only a .ru file is probably how I
> would add Rack support to git-instaweb if WEBrick weren't in Ruby
> core[2].

Yes, .psgi file in the (Perl) PSGI/Plack world is, as I understand it,
analogous to .ru file in the (Ruby) Rack world.  PSGI/Plack was inspired
by WSGI from Python world and Rack from Ruby world.

There is no web server in Perl core, although probably HTTP::Server::Simple
and HTTP::Engine comes close.  Well, there is HTTP::Server::Brick inspired
by WEBrick...

Using PSGI/Plack (via wrapper around CGI) allows easily to serve
gitweb's static files (stylesheet, images, etc.), gives persistent
environment (although this probably doesn't matter much for
git-instaweb), and allows for easy switching between different
PSGI-capable (e.g. via PSGI handlers) web servers, including the default
standalone HTTP::Server::PSGI (aka Standalone), HTTP::Server::Simple,
preforking Starlet or Starman, currently via PLACK_SERVER environment
variable.

> > Webrick, which is in similar situation, uses httpd.conf config file in 
> > YAML.  Unfortunately there is no config / serialization reader in Perl
> > core, so if we have to go this route either the config file would have
> > to be in Perl, or gitweb.psgi wrapper would have to include some simple
> > config file parsing.
> 
> I don't think we need parsing in the gitweb.psgi wrapper, we'll just
> consider gitweb.psgi the config file.  

Well, if it is all right, I would keep it as it is now (rebased on top
of Pavan's work related to GSoC 2010).  If we would want to keep config
separate from wrapper (e.g. by installing wrappers in $(gitwebdir)
together with gitweb.cgi, but keeping config files in ~/.gitweb or
.git/gitweb), we can split it later.

> This is also the case for Rack .ru files, which can be made executable
> and have a shebang pointing to "rackup".

Well, generated gitweb.psgi wrapper could have e.g.

  #!/usr/bin/env plackup

or

  #!$PLACKUP

(after putting full path to 'plackup' in $PLACKUP) as a she-bang line
('plackup' is PSGI/Plack equivalent inspired by 'rackup')... if not for
the fact that (as I wrote earlier) different web servers supported by
'plackup' utility have different ways of configuring them.  The common
API is 'plackup' command line options.

However in most operating systems everything after the interpreter in
the she-bang line is passed as *single* option, so for example
generating first line of gitweb.psgi wrapper as

  #!/usr/bin/evn plackup --port=1234 --host=127.0.0.1

wouldn't work.  That is why I used Plack::Runner instead, the module
behind 'plackup'.

As a nice side effect now you don't need to have 'plackup' in $PATH; you
only need to have Plack::Runner in $PERL5LIB (or equivalent), but you
need to have other required modules there anyway.

> [1] - I'm not familiar with Plack/PSGI at all, but I've been dabbling
>       quite a bit in Rack over the past year or two.
> 
> [2] - of course since WEBrick is in Ruby core and WEBrick supports CGI
>       scripts out-of-the-box (unlike Rack), adding Rack support to
>       instaweb would be a waste of time.

-- 
Jakub Narebski
Poland

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via  'plackup'
  2010-05-22 21:30       ` Jakub Narebski
  2010-05-23  9:19         ` Eric Wong
@ 2010-05-23 12:38         ` Ævar Arnfjörð Bjarmason
  2010-05-25  0:11           ` Jakub Narebski
  1 sibling, 1 reply; 12+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-23 12:38 UTC (permalink / raw
  To: Jakub Narebski; +Cc: git, Eric Wong

2010/5/22 Jakub Narebski <jnareb@gmail.com>:
> Webrick, which is in similar situation, uses httpd.conf config file in
> YAML.  Unfortunately there is no config / serialization reader in Perl
> core, so if we have to go this route either the config file would have
> to be in Perl, or gitweb.psgi wrapper would have to include some simple
> config file parsing.

You could easily do (pseudocode):

    unless (eval { require Config::Any; 1 }) {
        do $conf_file;
    } else {
        my $parser = Config::Any->new( ... );
         $parser->docnf( $conf_file );
     }

Then you'd read (eval) a perl config file by default, but remain
compatible with saner config formats for users prepared to install
things from the CPAN.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCH] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-23  9:31   ` [RFC/PATCH] " Eric Wong
@ 2010-05-23 20:21     ` Jakub Narebski
  0 siblings, 0 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-23 20:21 UTC (permalink / raw
  To: Eric Wong; +Cc: git

On Sun, 23 May 2010, Eric Wong wrote:
> Jakub Narebski <jnareb@gmail.com> wrote:
> >
> > Do you have any idea on how to synchronize those two processes, the web
> > server and the web client (web browser), so that web browser is run only
> > after web server prints that it is ready to accept connection?
> 
> Your polling http_is_ready() function is fine, and really the only
> portable solution across all servers (and OSes).

Well, even if we use the solution below it would be good fallback for
those web servers, for which the solution below cannot be used.

> 
> But if your webserver lets you run arbitrary code hooks after it
> binds the listen socket, what I do when writing integration tests
> is have it open a FIFO for writing.

I was thinking about 'flock' function in Perl (and similar in other
languages), and '/usr/bin/flock' utility from util-linux.  But using
FIFO as a semaphore might be a better idea: it is slighly more portable,
I guess.

Anyway, Plack handlers have (undocumented!) 'server_ready' option to web
servers, containing callback (code reference).  It can be set via
parse_options method of Plack::Runner, for example.  It is used by
'plackup' to print

  $server: Accepting connections at $proto://$host:$port

in the (default) "development" mode.

> 
> Adapted and abridged from the Rainbows! web server test suite, the
> following config snippet is from the config file for the Rainbows! web
> server:
> ---------------- rainbows.conf.rb -----------------
> after_fork do |server, worker|
>   # test script will block while reading from the FIFO,
>   # so notify the script on the first worker we spawn
>   # by opening the FIFO
>   if worker.nr == 0
>     File.open("/path/to/fifo", "wb") { |fp| fp.syswrite "START" }
>   end
> end
> ---------------------------------------------------
> 
> And then in the test script:
> ----------- my-integration-test.sh ----------------
> set -e
> mkfifo /path/to/fifo
> # start the server
> rainbows --daemonize --config-file rainbows.conf.rb
> 
> # "cat /path/to/fifo" will block until the after_fork hook is called
> # in rainbows.conf.rb
> test xSTART = x"$(cat /path/to/fifo)"
> 
> # server is up, run the rest of the tests...
> ---------------------------------------------------

I wonder how portable is that technique...

It certainly could be done in gitweb.psgi; the question is if it is it
worth it...

-- 
Jakub Narebski
Poland

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via  'plackup'
  2010-05-23 12:38         ` Ævar Arnfjörð Bjarmason
@ 2010-05-25  0:11           ` Jakub Narebski
  0 siblings, 0 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-25  0:11 UTC (permalink / raw
  To: Ævar Arnfjörð Bjarmason; +Cc: git, Eric Wong

On Sun, 23 May 2010, Ævar Arnfjörð Bjarmason wrote:
> 2010/5/22 Jakub Narebski <jnareb@gmail.com>:
> >
> > Webrick, which is in similar situation, uses httpd.conf config file in
> > YAML.  Unfortunately there is no config / serialization reader in Perl
> > core, so if we have to go this route either the config file would have
> > to be in Perl, or gitweb.psgi wrapper would have to include some simple
> > config file parsing.
> 
> You could easily do (pseudocode):
> 
>     unless (eval { require Config::Any; 1 }) {
>     	do $conf_file;
>     } else {
>     	my $parser = Config::Any->new( ... );
>     	$parser->docnf( $conf_file );
>     }
> 
> Then you'd read (eval) a perl config file by default, but remain
> compatible with saner config formats for users prepared to install
> things from the CPAN.

I was thinking more about something like that:

  my @opts = qw(--env deployment);
  while (<>) {
  	chomp;
  	next unless $_;  # skip empty lines
  	next if /^\s*#/; # skip comments
  	if (/^\s*(.*?)\s*=\s*(.*)\s*$/) {
  		push @opts, '--'.lc($1), $2;
  	}
  }

where httpd.conf would look like this:

  port = 1234
  host = 127.0.0.1

Anyway, if such code is to be be added, it would be added in a separate
commit.
-- 
Jakub Narebski
Poland

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC/PATCHv3] git-instaweb: Add support for running gitweb via 'plackup'
  2010-05-20 21:55     ` [RFC/PATCHv3] " Jakub Narebski
  2010-05-22 21:30       ` Jakub Narebski
@ 2010-05-25  9:02       ` Jakub Narebski
  1 sibling, 0 replies; 12+ messages in thread
From: Jakub Narebski @ 2010-05-25  9:02 UTC (permalink / raw
  To: git; +Cc: Eric Wong

On Thu, 20 May 2010, Jakub Narebski wrote:
> ---
> 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.

I'll wait with resending it as a patch series for Pavan work on
git-instaweb to be in, to not force him to do additional work on
the new 'plackup'-related code in git-instaweb.

> 
> Also, it somwehat lacks documentation.

Hmmm... where should the documentation about requirements etc.
of specific supported by git-instaweb web servers be added?

-- 
Jakub Narebski
Poland

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-05-25  9:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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     ` [RFC/PATCHv3] " Jakub Narebski
2010-05-22 21:30       ` 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

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).