Merge branch 'dl/honor-cflags-in-hdr-check'
[git/git.git] / git-instaweb.sh
CommitLineData
a51d37c1
EW
1#!/bin/sh
2#
3# Copyright (c) 2006 Eric Wong
4#
c2db2e0e 5
c5699693 6PERL='@@PERL@@'
c2db2e0e 7OPTIONS_KEEPDASHDASH=
51ba8ce3 8OPTIONS_STUCKLONG=
c2db2e0e 9OPTIONS_SPEC="\
1b1dd23f 10git instaweb [options] (--start | --stop | --restart)
c2db2e0e
PH
11--
12l,local only bind on 127.0.0.1
13p,port= the port to bind to
14d,httpd= the command to launch
15b,browser= the browser to launch
16m,module-path= the module path (only needed for apache2)
17 Action
18stop stop the web server
19start start the web server
20restart restart the web server
21"
a51d37c1 22
130e475e 23SUBDIRECTORY_OK=Yes
a51d37c1
EW
24. git-sh-setup
25
b2bc9a30 26fqgitdir="$GIT_DIR"
43d60d2e
FP
27local="$(git config --bool --get instaweb.local)"
28httpd="$(git config --get instaweb.httpd)"
c0cb4ed3 29root="$(git config --get instaweb.gitwebdir)"
43d60d2e
FP
30port=$(git config --get instaweb.port)
31module_path="$(git config --get instaweb.modulepath)"
c0175f92 32action="browse"
a51d37c1 33
9126425d 34conf="$GIT_DIR/gitweb/httpd.conf"
a51d37c1
EW
35
36# Defaults:
37
82e5a82f 38# if installed, it doesn't need further configuration (module_path)
a51d37c1
EW
39test -z "$httpd" && httpd='lighttpd -f'
40
c0cb4ed3
PKS
41# Default is @@GITWEBDIR@@
42test -z "$root" && root='@@GITWEBDIR@@'
43
a51d37c1
EW
44# any untaken local port will do...
45test -z "$port" && port=1234
46
43d60d2e
FP
47resolve_full_httpd () {
48 case "$httpd" in
4bdf8599
DM
49 *apache2*|*lighttpd*|*httpd*)
50 # yes, *httpd* covers *lighttpd* above, but it is there for clarity
43d60d2e 51 # ensure that the apache2/lighttpd command ends with "-f"
e1622bfc 52 if ! echo "$httpd" | sane_grep -- '-f *$' >/dev/null 2>&1
43d60d2e
FP
53 then
54 httpd="$httpd -f"
55 fi
56 ;;
78646987
JN
57 *plackup*)
58 # server is started by running via generated gitweb.psgi in $fqgitdir/gitweb
59 full_httpd="$fqgitdir/gitweb/gitweb.psgi"
60 httpd_only="${httpd%% *}" # cut on first space
61 return
62 ;;
422bff28 63 *webrick*)
f46e1304 64 # server is started by running via generated webrick.rb in
422bff28 65 # $fqgitdir/gitweb
f46e1304 66 full_httpd="$fqgitdir/gitweb/webrick.rb"
422bff28
EW
67 httpd_only="${httpd%% *}" # cut on first space
68 return
69 ;;
2eb14bb2
AZ
70 *python*)
71 # server is started by running via generated gitweb.py in
72 # $fqgitdir/gitweb
73 full_httpd="$fqgitdir/gitweb/gitweb.py"
74 httpd_only="${httpd%% *}" # cut on first space
75 return
76 ;;
43d60d2e
FP
77 esac
78
79 httpd_only="$(echo $httpd | cut -f1 -d' ')"
e47eec8f 80 if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null 2>&1;; esac
a51d37c1 81 then
43d60d2e 82 full_httpd=$httpd
a51d37c1
EW
83 else
84 # many httpds are installed in /usr/sbin or /usr/local/sbin
85 # these days and those are not in most users $PATHs
14b45b66
MD
86 # in addition, we may have generated a server script
87 # in $fqgitdir/gitweb.
c0cb4ed3 88 for i in /usr/local/sbin /usr/sbin "$root" "$fqgitdir/gitweb"
a51d37c1
EW
89 do
90 if test -x "$i/$httpd_only"
91 then
43d60d2e 92 full_httpd=$i/$httpd
a51d37c1
EW
93 return
94 fi
95 done
43d60d2e
FP
96
97 echo >&2 "$httpd_only not found. Install $httpd_only or use" \
98 "--httpd to specify another httpd daemon."
f281e3a1 99 exit 1
a51d37c1 100 fi
43d60d2e
FP
101}
102
103start_httpd () {
0b624b4c
SB
104 if test -f "$fqgitdir/pid"; then
105 say "Instance already running. Restarting..."
106 stop_httpd
107 fi
108
43d60d2e
FP
109 # here $httpd should have a meaningful value
110 resolve_full_httpd
5ad6d387
JN
111 mkdir -p "$fqgitdir/gitweb/$httpd_only"
112 conf="$fqgitdir/gitweb/$httpd_only.conf"
113
114 # generate correct config file if it doesn't exist
115 test -f "$conf" || configure_httpd
116 test -f "$fqgitdir/gitweb/gitweb_config.perl" || gitweb_conf
43d60d2e
FP
117
118 # don't quote $full_httpd, there can be arguments to it (-f)
0ded4758 119 case "$httpd" in
2eb14bb2 120 *mongoose*|*plackup*|*python*)
78646987 121 #These servers don't have a daemon mode so we'll have to fork it
48bf76ca 122 $full_httpd "$conf" &
0ded4758
WL
123 #Save the pid before doing anything else (we'll print it later)
124 pid=$!
125
126 if test $? != 0; then
127 echo "Could not execute http daemon $httpd."
128 exit 1
129 fi
130
131 cat > "$fqgitdir/pid" <<EOF
132$pid
133EOF
134 ;;
135 *)
48bf76ca 136 $full_httpd "$conf"
0ded4758
WL
137 if test $? != 0; then
138 echo "Could not execute http daemon $httpd."
139 exit 1
140 fi
141 ;;
142 esac
a51d37c1
EW
143}
144
145stop_httpd () {
43d60d2e 146 test -f "$fqgitdir/pid" && kill $(cat "$fqgitdir/pid")
d1127622 147 rm -f "$fqgitdir/pid"
a51d37c1
EW
148}
149
d94775e1
JN
150httpd_is_ready () {
151 "$PERL" -MIO::Socket::INET -e "
152local \$| = 1; # turn on autoflush
153exit if (IO::Socket::INET->new('127.0.0.1:$port'));
154print 'Waiting for \'$httpd\' to start ..';
155do {
156 print '.';
157 sleep(1);
158} until (IO::Socket::INET->new('127.0.0.1:$port'));
159print qq! (done)\n!;
160"
161}
162
822f7c73 163while test $# != 0
a51d37c1
EW
164do
165 case "$1" in
166 --stop|stop)
c0175f92 167 action="stop"
a51d37c1
EW
168 ;;
169 --start|start)
c0175f92 170 action="start"
a51d37c1
EW
171 ;;
172 --restart|restart)
c0175f92 173 action="restart"
a51d37c1 174 ;;
c2db2e0e 175 -l|--local)
a51d37c1
EW
176 local=true
177 ;;
c2db2e0e
PH
178 -d|--httpd)
179 shift
180 httpd="$1"
181 ;;
182 -b|--browser)
183 shift
184 browser="$1"
a51d37c1 185 ;;
c2db2e0e
PH
186 -p|--port)
187 shift
188 port="$1"
a51d37c1 189 ;;
c2db2e0e
PH
190 -m|--module-path)
191 shift
192 module_path="$1"
a51d37c1 193 ;;
c2db2e0e 194 --)
a51d37c1
EW
195 ;;
196 *)
197 usage
198 ;;
199 esac
200 shift
201done
202
203mkdir -p "$GIT_DIR/gitweb/tmp"
43d60d2e 204GIT_EXEC_PATH="$(git --exec-path)"
a51d37c1 205GIT_DIR="$fqgitdir"
c0cb4ed3
PKS
206GITWEB_CONFIG="$fqgitdir/gitweb/gitweb_config.perl"
207export GIT_EXEC_PATH GIT_DIR GITWEB_CONFIG
a51d37c1 208
425b78e8 209webrick_conf () {
422bff28
EW
210 # webrick seems to have no way of passing arbitrary environment
211 # variables to the underlying CGI executable, so we wrap the
212 # actual gitweb.cgi using a shell script to force it
213 wrapper="$fqgitdir/gitweb/$httpd/wrapper.sh"
214 cat > "$wrapper" <<EOF
ff7a9dc2 215#!@SHELL_PATH@
422bff28
EW
216# we use this shell script wrapper around the real gitweb.cgi since
217# there appears to be no other way to pass arbitrary environment variables
218# into the CGI process
219GIT_EXEC_PATH=$GIT_EXEC_PATH GIT_DIR=$GIT_DIR GITWEB_CONFIG=$GITWEB_CONFIG
220export GIT_EXEC_PATH GIT_DIR GITWEB_CONFIG
221exec $root/gitweb.cgi
222EOF
223 chmod +x "$wrapper"
224
225 # This assumes _ruby_ is in the user's $PATH. that's _one_
226 # portable way to run ruby, which could be installed anywhere, really.
425b78e8
MD
227 # generate a standalone server script in $fqgitdir/gitweb.
228 cat >"$fqgitdir/gitweb/$httpd.rb" <<EOF
f46e1304 229#!/usr/bin/env ruby
425b78e8 230require 'webrick'
e9323e7f 231require 'logger'
f46e1304
EW
232options = {
233 :Port => $port,
234 :DocumentRoot => "$root",
e9323e7f
EW
235 :Logger => Logger.new('$fqgitdir/gitweb/error.log'),
236 :AccessLog => [
237 [ Logger.new('$fqgitdir/gitweb/access.log'),
238 WEBrick::AccessLog::COMBINED_LOG_FORMAT ]
239 ],
f46e1304
EW
240 :DirectoryIndex => ["gitweb.cgi"],
241 :CGIInterpreter => "$wrapper",
242 :StartCallback => lambda do
243 File.open("$fqgitdir/pid", "w") { |f| f.puts Process.pid }
244 end,
245 :ServerType => WEBrick::Daemon,
246}
247options[:BindAddress] = '127.0.0.1' if "$local" == "true"
425b78e8
MD
248server = WEBrick::HTTPServer.new(options)
249['INT', 'TERM'].each do |signal|
250 trap(signal) {server.shutdown}
251end
252server.start
253EOF
f46e1304
EW
254 chmod +x "$fqgitdir/gitweb/$httpd.rb"
255 # configuration is embedded in server script file, webrick.rb
256 rm -f "$conf"
425b78e8
MD
257}
258
a51d37c1
EW
259lighttpd_conf () {
260 cat > "$conf" <<EOF
c0cb4ed3 261server.document-root = "$root"
a51d37c1 262server.port = $port
e47eec8f 263server.modules = ( "mod_setenv", "mod_cgi" )
a51d37c1
EW
264server.indexfiles = ( "gitweb.cgi" )
265server.pid-file = "$fqgitdir/pid"
be5347b3 266server.errorlog = "$fqgitdir/gitweb/$httpd_only/error.log"
e47eec8f
RJ
267
268# to enable, add "mod_access", "mod_accesslog" to server.modules
269# variable above and uncomment this
be5347b3 270#accesslog.filename = "$fqgitdir/gitweb/$httpd_only/access.log"
e47eec8f 271
c0cb4ed3 272setenv.add-environment = ( "PATH" => env.PATH, "GITWEB_CONFIG" => env.GITWEB_CONFIG )
e47eec8f 273
a51d37c1 274cgi.assign = ( ".cgi" => "" )
e47eec8f
RJ
275
276# mimetype mapping
277mimetype.assign = (
278 ".pdf" => "application/pdf",
279 ".sig" => "application/pgp-signature",
280 ".spl" => "application/futuresplash",
281 ".class" => "application/octet-stream",
282 ".ps" => "application/postscript",
283 ".torrent" => "application/x-bittorrent",
284 ".dvi" => "application/x-dvi",
285 ".gz" => "application/x-gzip",
286 ".pac" => "application/x-ns-proxy-autoconfig",
287 ".swf" => "application/x-shockwave-flash",
288 ".tar.gz" => "application/x-tgz",
289 ".tgz" => "application/x-tgz",
290 ".tar" => "application/x-tar",
291 ".zip" => "application/zip",
292 ".mp3" => "audio/mpeg",
293 ".m3u" => "audio/x-mpegurl",
294 ".wma" => "audio/x-ms-wma",
295 ".wax" => "audio/x-ms-wax",
296 ".ogg" => "application/ogg",
297 ".wav" => "audio/x-wav",
298 ".gif" => "image/gif",
299 ".jpg" => "image/jpeg",
300 ".jpeg" => "image/jpeg",
301 ".png" => "image/png",
302 ".xbm" => "image/x-xbitmap",
303 ".xpm" => "image/x-xpixmap",
304 ".xwd" => "image/x-xwindowdump",
305 ".css" => "text/css",
306 ".html" => "text/html",
307 ".htm" => "text/html",
308 ".js" => "text/javascript",
309 ".asc" => "text/plain",
310 ".c" => "text/plain",
311 ".cpp" => "text/plain",
312 ".log" => "text/plain",
313 ".conf" => "text/plain",
314 ".text" => "text/plain",
315 ".txt" => "text/plain",
316 ".dtd" => "text/xml",
317 ".xml" => "text/xml",
318 ".mpeg" => "video/mpeg",
319 ".mpg" => "video/mpeg",
320 ".mov" => "video/quicktime",
321 ".qt" => "video/quicktime",
322 ".avi" => "video/x-msvideo",
323 ".asf" => "video/x-ms-asf",
324 ".asx" => "video/x-ms-asf",
325 ".wmv" => "video/x-ms-wmv",
326 ".bz2" => "application/x-bzip",
327 ".tbz" => "application/x-bzip-compressed-tar",
328 ".tar.bz2" => "application/x-bzip-compressed-tar",
329 "" => "text/plain"
330 )
a51d37c1 331EOF
9126425d 332 test x"$local" = xtrue && echo 'server.bind = "127.0.0.1"' >> "$conf"
a51d37c1
EW
333}
334
335apache2_conf () {
1976311a
SK
336 for candidate in \
337 /etc/httpd \
338 /usr/lib/apache2 \
339 /usr/lib/httpd ;
340 do
341 if test -d "$candidate/modules"
342 then
343 module_path="$candidate/modules"
344 break
345 fi
346 done
a51d37c1 347 bind=
9126425d 348 test x"$local" = xtrue && bind='127.0.0.1:'
e24c76bf 349 echo 'text/css css' > "$fqgitdir/mime.types"
a51d37c1 350 cat > "$conf" <<EOF
44a167b0 351ServerName "git-instaweb"
c0cb4ed3
PKS
352ServerRoot "$root"
353DocumentRoot "$root"
be5347b3
PKS
354ErrorLog "$fqgitdir/gitweb/$httpd_only/error.log"
355CustomLog "$fqgitdir/gitweb/$httpd_only/access.log" combined
a51d37c1
EW
356PidFile "$fqgitdir/pid"
357Listen $bind$port
44a167b0
EW
358EOF
359
f8ee1f02
JM
360 for mod in mpm_event mpm_prefork mpm_worker
361 do
362 if test -e $module_path/mod_${mod}.so
363 then
364 echo "LoadModule ${mod}_module " \
365 "$module_path/mod_${mod}.so" >> "$conf"
366 # only one mpm module permitted
367 break
368 fi
369 done
757b1249 370 for mod in mime dir env log_config authz_core unixd
4bdf8599
DM
371 do
372 if test -e $module_path/mod_${mod}.so
373 then
44a167b0
EW
374 echo "LoadModule ${mod}_module " \
375 "$module_path/mod_${mod}.so" >> "$conf"
376 fi
377 done
378 cat >> "$conf" <<EOF
e24c76bf 379TypesConfig "$fqgitdir/mime.types"
a51d37c1
EW
380DirectoryIndex gitweb.cgi
381EOF
382
383 # check to see if Dennis Stosberg's mod_perl compatibility patch
384 # (<20060621130708.Gcbc6e5c@leonov.stosberg.net>) has been applied
e1622bfc 385 if test -f "$module_path/mod_perl.so" &&
c0cb4ed3 386 sane_grep 'MOD_PERL' "$root/gitweb.cgi" >/dev/null
a51d37c1
EW
387 then
388 # favor mod_perl if available
389 cat >> "$conf" <<EOF
390LoadModule perl_module $module_path/mod_perl.so
391PerlPassEnv GIT_DIR
2989f516 392PerlPassEnv GIT_EXEC_PATH
c0cb4ed3 393PerlPassEnv GITWEB_CONFIG
a51d37c1
EW
394<Location /gitweb.cgi>
395 SetHandler perl-script
396 PerlResponseHandler ModPerl::Registry
397 PerlOptions +ParseHeaders
398 Options +ExecCGI
399</Location>
400EOF
401 else
402 # plain-old CGI
43d60d2e 403 resolve_full_httpd
9524cf29 404 list_mods=$(echo "$full_httpd" | sed 's/-f$/-l/')
e1622bfc 405 $list_mods | sane_grep 'mod_cgi\.c' >/dev/null 2>&1 || \
10d1432a
MR
406 if test -f "$module_path/mod_cgi.so"
407 then
408 echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
409 else
410 $list_mods | grep 'mod_cgid\.c' >/dev/null 2>&1 || \
411 if test -f "$module_path/mod_cgid.so"
412 then
413 echo "LoadModule cgid_module $module_path/mod_cgid.so" \
414 >> "$conf"
415 else
416 echo "You have no CGI support!"
417 exit 2
418 fi
419 echo "ScriptSock logs/gitweb.sock" >> "$conf"
420 fi
a51d37c1 421 cat >> "$conf" <<EOF
2989f516
DM
422PassEnv GIT_DIR
423PassEnv GIT_EXEC_PATH
424PassEnv GITWEB_CONFIG
a51d37c1
EW
425AddHandler cgi-script .cgi
426<Location /gitweb.cgi>
427 Options +ExecCGI
428</Location>
429EOF
430 fi
431}
432
0ded4758
WL
433mongoose_conf() {
434 cat > "$conf" <<EOF
435# Mongoose web server configuration file.
436# Lines starting with '#' and empty lines are ignored.
437# For detailed description of every option, visit
438# http://code.google.com/p/mongoose/wiki/MongooseManual
439
c0cb4ed3 440root $root
0ded4758
WL
441ports $port
442index_files gitweb.cgi
443#ssl_cert $fqgitdir/gitweb/ssl_cert.pem
be5347b3
PKS
444error_log $fqgitdir/gitweb/$httpd_only/error.log
445access_log $fqgitdir/gitweb/$httpd_only/access.log
0ded4758
WL
446
447#cgi setup
c0cb4ed3 448cgi_env PATH=$PATH,GIT_DIR=$GIT_DIR,GIT_EXEC_PATH=$GIT_EXEC_PATH,GITWEB_CONFIG=$GITWEB_CONFIG
0ded4758
WL
449cgi_interp $PERL
450cgi_ext cgi,pl
451
452# mimetype mapping
453mime_types .gz=application/x-gzip,.tar.gz=application/x-tgz,.tgz=application/x-tgz,.tar=application/x-tar,.zip=application/zip,.gif=image/gif,.jpg=image/jpeg,.jpeg=image/jpeg,.png=image/png,.css=text/css,.html=text/html,.htm=text/html,.js=text/javascript,.c=text/plain,.cpp=text/plain,.log=text/plain,.conf=text/plain,.text=text/plain,.txt=text/plain,.dtd=text/xml,.bz2=application/x-bzip,.tbz=application/x-bzip-compressed-tar,.tar.bz2=application/x-bzip-compressed-tar
454EOF
455}
456
78646987
JN
457plackup_conf () {
458 # generate a standalone 'plackup' server script in $fqgitdir/gitweb
459 # with embedded configuration; it does not use "$conf" file
460 cat > "$fqgitdir/gitweb/gitweb.psgi" <<EOF
461#!$PERL
462
463# gitweb - simple web interface to track changes in git repositories
464# PSGI wrapper and server starter (see http://plackperl.org)
465
466use strict;
467
468use IO::Handle;
469use Plack::MIME;
470use Plack::Builder;
471use Plack::App::WrapCGI;
472use CGI::Emulate::PSGI 0.07; # minimum version required to work with gitweb
473
474# mimetype mapping (from lighttpd_conf)
475Plack::MIME->add_type(
476 ".pdf" => "application/pdf",
477 ".sig" => "application/pgp-signature",
478 ".spl" => "application/futuresplash",
479 ".class" => "application/octet-stream",
480 ".ps" => "application/postscript",
481 ".torrent" => "application/x-bittorrent",
482 ".dvi" => "application/x-dvi",
483 ".gz" => "application/x-gzip",
484 ".pac" => "application/x-ns-proxy-autoconfig",
485 ".swf" => "application/x-shockwave-flash",
486 ".tar.gz" => "application/x-tgz",
487 ".tgz" => "application/x-tgz",
488 ".tar" => "application/x-tar",
489 ".zip" => "application/zip",
490 ".mp3" => "audio/mpeg",
491 ".m3u" => "audio/x-mpegurl",
492 ".wma" => "audio/x-ms-wma",
493 ".wax" => "audio/x-ms-wax",
494 ".ogg" => "application/ogg",
495 ".wav" => "audio/x-wav",
496 ".gif" => "image/gif",
497 ".jpg" => "image/jpeg",
498 ".jpeg" => "image/jpeg",
499 ".png" => "image/png",
500 ".xbm" => "image/x-xbitmap",
501 ".xpm" => "image/x-xpixmap",
502 ".xwd" => "image/x-xwindowdump",
503 ".css" => "text/css",
504 ".html" => "text/html",
505 ".htm" => "text/html",
506 ".js" => "text/javascript",
507 ".asc" => "text/plain",
508 ".c" => "text/plain",
509 ".cpp" => "text/plain",
510 ".log" => "text/plain",
511 ".conf" => "text/plain",
512 ".text" => "text/plain",
513 ".txt" => "text/plain",
514 ".dtd" => "text/xml",
515 ".xml" => "text/xml",
516 ".mpeg" => "video/mpeg",
517 ".mpg" => "video/mpeg",
518 ".mov" => "video/quicktime",
519 ".qt" => "video/quicktime",
520 ".avi" => "video/x-msvideo",
521 ".asf" => "video/x-ms-asf",
522 ".asx" => "video/x-ms-asf",
523 ".wmv" => "video/x-ms-wmv",
524 ".bz2" => "application/x-bzip",
525 ".tbz" => "application/x-bzip-compressed-tar",
526 ".tar.bz2" => "application/x-bzip-compressed-tar",
527 "" => "text/plain"
528);
529
530my \$app = builder {
531 # to be able to override \$SIG{__WARN__} to log build time warnings
532 use CGI::Carp; # it sets \$SIG{__WARN__} itself
533
534 my \$logdir = "$fqgitdir/gitweb/$httpd_only";
535 open my \$access_log_fh, '>>', "\$logdir/access.log"
536 or die "Couldn't open access log '\$logdir/access.log': \$!";
537 open my \$error_log_fh, '>>', "\$logdir/error.log"
538 or die "Couldn't open error log '\$logdir/error.log': \$!";
539
540 \$access_log_fh->autoflush(1);
541 \$error_log_fh->autoflush(1);
542
543 # redirect build time warnings to error.log
544 \$SIG{'__WARN__'} = sub {
545 my \$msg = shift;
546 # timestamp warning like in CGI::Carp::warn
547 my \$stamp = CGI::Carp::stamp();
548 \$msg =~ s/^/\$stamp/gm;
549 print \$error_log_fh \$msg;
550 };
551
552 # write errors to error.log, access to access.log
553 enable 'AccessLog',
554 format => "combined",
555 logger => sub { print \$access_log_fh @_; };
556 enable sub {
557 my \$app = shift;
558 sub {
559 my \$env = shift;
560 \$env->{'psgi.errors'} = \$error_log_fh;
561 \$app->(\$env);
562 }
563 };
564 # gitweb currently doesn't work with $SIG{CHLD} set to 'IGNORE',
565 # because it uses 'close $fd or die...' on piped filehandle $fh
566 # (which causes the parent process to wait for child to finish).
567 enable_if { \$SIG{'CHLD'} eq 'IGNORE' } sub {
568 my \$app = shift;
569 sub {
570 my \$env = shift;
571 local \$SIG{'CHLD'} = 'DEFAULT';
572 local \$SIG{'CLD'} = 'DEFAULT';
573 \$app->(\$env);
574 }
575 };
576 # serve static files, i.e. stylesheet, images, script
577 enable 'Static',
578 path => sub { m!\.(js|css|png)\$! && s!^/gitweb/!! },
579 root => "$root/",
580 encoding => 'utf-8'; # encoding for 'text/plain' files
581 # convert CGI application to PSGI app
582 Plack::App::WrapCGI->new(script => "$root/gitweb.cgi")->to_app;
583};
584
585# make it runnable as standalone app,
586# like it would be run via 'plackup' utility
20e7ab8a
JN
587if (caller) {
588 return \$app;
589} else {
78646987
JN
590 require Plack::Runner;
591
592 my \$runner = Plack::Runner->new();
593 \$runner->parse_options(qw(--env deployment --port $port),
20e7ab8a 594 "$local" ? qw(--host 127.0.0.1) : ());
78646987
JN
595 \$runner->run(\$app);
596}
597__END__
598EOF
599
600 chmod a+x "$fqgitdir/gitweb/gitweb.psgi"
601 # configuration is embedded in server script file, gitweb.psgi
602 rm -f "$conf"
603}
604
2eb14bb2
AZ
605python_conf() {
606 # Python's builtin http.server and its CGI support is very limited.
607 # CGI handler is capable of running CGI script only from inside a directory.
608 # Trying to set cgi_directories=["/"] will add double slash to SCRIPT_NAME
609 # and that in turn breaks gitweb's relative link generation.
610
611 # create a simple web root where $fqgitdir/gitweb/$httpd_only is our root
612 mkdir -p "$fqgitdir/gitweb/$httpd_only/cgi-bin"
613 # Python http.server follows the symlinks
614 ln -sf "$root/gitweb.cgi" "$fqgitdir/gitweb/$httpd_only/cgi-bin/gitweb.cgi"
615 ln -sf "$root/static" "$fqgitdir/gitweb/$httpd_only/"
616
617 # generate a standalone 'python http.server' script in $fqgitdir/gitweb
618 # This asumes that python is in user's $PATH
619 # This script is Python 2 and 3 compatible
620 cat > "$fqgitdir/gitweb/gitweb.py" <<EOF
621#!/usr/bin/env python
622import os
623import sys
624
625# Open log file in line buffering mode
626accesslogfile = open("$fqgitdir/gitweb/access.log", 'a', buffering=1)
627errorlogfile = open("$fqgitdir/gitweb/error.log", 'a', buffering=1)
628
629# and replace our stdout and stderr with log files
630# also do a lowlevel duplicate of the logfile file descriptors so that
631# our CGI child process writes any stderr warning also to the log file
632_orig_stdout_fd = sys.stdout.fileno()
633sys.stdout.close()
634os.dup2(accesslogfile.fileno(), _orig_stdout_fd)
635sys.stdout = accesslogfile
636
637_orig_stderr_fd = sys.stderr.fileno()
638sys.stderr.close()
639os.dup2(errorlogfile.fileno(), _orig_stderr_fd)
640sys.stderr = errorlogfile
641
642from functools import partial
643
644if sys.version_info < (3, 0): # Python 2
645 from CGIHTTPServer import CGIHTTPRequestHandler
646 from BaseHTTPServer import HTTPServer as ServerClass
647else: # Python 3
648 from http.server import CGIHTTPRequestHandler
649 from http.server import HTTPServer as ServerClass
650
651
652# Those environment variables will be passed to the cgi script
653os.environ.update({
654 "GIT_EXEC_PATH": "$GIT_EXEC_PATH",
655 "GIT_DIR": "$GIT_DIR",
656 "GITWEB_CONFIG": "$GITWEB_CONFIG"
657})
658
659
660class GitWebRequestHandler(CGIHTTPRequestHandler):
661
662 def log_message(self, format, *args):
663 # Write access logs to stdout
664 sys.stdout.write("%s - - [%s] %s\n" %
665 (self.address_string(),
666 self.log_date_time_string(),
667 format%args))
668
669 def do_HEAD(self):
670 self.redirect_path()
671 CGIHTTPRequestHandler.do_HEAD(self)
672
673 def do_GET(self):
674 if self.path == "/":
675 self.send_response(303, "See Other")
676 self.send_header("Location", "/cgi-bin/gitweb.cgi")
677 self.end_headers()
678 return
679 self.redirect_path()
680 CGIHTTPRequestHandler.do_GET(self)
681
682 def do_POST(self):
683 self.redirect_path()
684 CGIHTTPRequestHandler.do_POST(self)
685
686 # rewrite path of every request that is not gitweb.cgi to out of cgi-bin
687 def redirect_path(self):
688 if not self.path.startswith("/cgi-bin/gitweb.cgi"):
689 self.path = self.path.replace("/cgi-bin/", "/")
690
691 # gitweb.cgi is the only thing that is ever going to be run here.
692 # Ignore everything else
693 def is_cgi(self):
694 result = False
695 if self.path.startswith('/cgi-bin/gitweb.cgi'):
696 result = CGIHTTPRequestHandler.is_cgi(self)
697 return result
698
699
700bind = "127.0.0.1"
701if "$local" == "true":
702 bind = "0.0.0.0"
703
704# Set our http root directory
705# This is a work around for a missing directory argument in older Python versions
706# as this was added to SimpleHTTPRequestHandler in Python 3.7
707os.chdir("$fqgitdir/gitweb/$httpd_only/")
708
709GitWebRequestHandler.protocol_version = "HTTP/1.0"
710httpd = ServerClass((bind, $port), GitWebRequestHandler)
711
712sa = httpd.socket.getsockname()
713print("Serving HTTP on", sa[0], "port", sa[1], "...")
714httpd.serve_forever()
715EOF
716
717 chmod a+x "$fqgitdir/gitweb/gitweb.py"
718}
719
c0cb4ed3
PKS
720gitweb_conf() {
721 cat > "$fqgitdir/gitweb/gitweb_config.perl" <<EOF
fcb06a8d 722#!@@PERL@@
c0cb4ed3
PKS
723our \$projectroot = "$(dirname "$fqgitdir")";
724our \$git_temp = "$fqgitdir/gitweb/tmp";
725our \$projects_list = \$projectroot;
fc5b8e01
GB
726
727\$feature{'remote_heads'}{'default'} = [1];
c0cb4ed3 728EOF
4af819d4
JN
729}
730
db61f060
JN
731configure_httpd() {
732 case "$httpd" in
733 *lighttpd*)
734 lighttpd_conf
735 ;;
736 *apache2*|*httpd*)
737 apache2_conf
738 ;;
739 webrick)
740 webrick_conf
741 ;;
742 *mongoose*)
743 mongoose_conf
744 ;;
745 *plackup*)
746 plackup_conf
747 ;;
2eb14bb2
AZ
748 *python*)
749 python_conf
750 ;;
db61f060
JN
751 *)
752 echo "Unknown httpd specified: $httpd"
753 exit 1
754 ;;
755 esac
756}
757
c0175f92
JN
758case "$action" in
759stop)
760 stop_httpd
761 exit 0
762 ;;
763start)
764 start_httpd
765 exit 0
766 ;;
767restart)
768 stop_httpd
769 start_httpd
770 exit 0
771 ;;
772esac
773
c0cb4ed3 774gitweb_conf
a51d37c1 775
be5347b3
PKS
776resolve_full_httpd
777mkdir -p "$fqgitdir/gitweb/$httpd_only"
5ad6d387 778conf="$fqgitdir/gitweb/$httpd_only.conf"
be5347b3 779
db61f060 780configure_httpd
a51d37c1
EW
781
782start_httpd
5209eda8 783url=http://127.0.0.1:$port
2e0c2902
CC
784
785if test -n "$browser"; then
d94775e1 786 httpd_is_ready && git web--browse -b "$browser" $url || echo $url
2e0c2902 787else
d94775e1 788 httpd_is_ready && git web--browse -c "instaweb.browser" $url || echo $url
2e0c2902 789fi