67
httpd_only="${httpd%% *}" # cut on first space
68
return
69
;;
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
+ ;;
77
esac
78
79
httpd_only="$(echo $httpd | cut -f1 -d' ')"
117
118
# don't quote $full_httpd, there can be arguments to it (-f)
119
case "$httpd" in
113
- *mongoose*|*plackup*)
120
+ *mongoose*|*plackup*|*python*)
121
#These servers don't have a daemon mode so we'll have to fork it
122
$full_httpd "$conf" &
123
#Save the pid before doing anything else (we'll print it later)
602
rm -f "$conf"
603
}
604
605
+python_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
622
+import os
623
+import sys
624
+
625
+# Open log file in line buffering mode
626
+accesslogfile = open("$fqgitdir/gitweb/access.log", 'a', buffering=1)
627
+errorlogfile = 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()
633
+sys.stdout.close()
634
+os.dup2(accesslogfile.fileno(), _orig_stdout_fd)
635
+sys.stdout = accesslogfile
636
+
637
+_orig_stderr_fd = sys.stderr.fileno()
638
+sys.stderr.close()
639
+os.dup2(errorlogfile.fileno(), _orig_stderr_fd)
640
+sys.stderr = errorlogfile
641
+
642
+from functools import partial
643
+
644
+if sys.version_info < (3, 0): # Python 2
645
+ from CGIHTTPServer import CGIHTTPRequestHandler
646
+ from BaseHTTPServer import HTTPServer as ServerClass
647
+else: # 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
653
+os.environ.update({
654
+ "GIT_EXEC_PATH": "$GIT_EXEC_PATH",
655
+ "GIT_DIR": "$GIT_DIR",
656
+ "GITWEB_CONFIG": "$GITWEB_CONFIG"
657
+})
658
+
659
+
660
+class 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
+
700
+bind = "127.0.0.1"
701
+if "$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
707
+os.chdir("$fqgitdir/gitweb/$httpd_only/")
708
+
709
+GitWebRequestHandler.protocol_version = "HTTP/1.0"
710
+httpd = ServerClass((bind, $port), GitWebRequestHandler)
711
+
712
+sa = httpd.socket.getsockname()
713
+print("Serving HTTP on", sa[0], "port", sa[1], "...")
714
+httpd.serve_forever()
715
+EOF
716
+
717
+ chmod a+x "$fqgitdir/gitweb/gitweb.py"
718
+}
719
+
720
gitweb_conf() {
721
cat > "$fqgitdir/gitweb/gitweb_config.perl" <<EOF
722
#!@@PERL@@
745
*plackup*)
746
plackup_conf
747
;;
748
+ *python*)
749
+ python_conf
750
+ ;;
751
*)
752
echo "Unknown httpd specified: $httpd"
753
exit 1