diff options
Diffstat (limited to 'git-instaweb.sh')
-rwxr-xr-x | git-instaweb.sh | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/git-instaweb.sh b/git-instaweb.sh new file mode 100755 index 000000000..0843372b5 --- /dev/null +++ b/git-instaweb.sh @@ -0,0 +1,297 @@ +#!/bin/sh +# +# Copyright (c) 2006 Eric Wong +# + +PERL='@@PERL@@' +OPTIONS_KEEPDASHDASH= +OPTIONS_SPEC="\ +git instaweb [options] (--start | --stop | --restart) +-- +l,local only bind on 127.0.0.1 +p,port= the port to bind to +d,httpd= the command to launch +b,browser= the browser to launch +m,module-path= the module path (only needed for apache2) + Action +stop stop the web server +start start the web server +restart restart the web server +" + +. git-sh-setup + +fqgitdir="$GIT_DIR" +local="$(git config --bool --get instaweb.local)" +httpd="$(git config --get instaweb.httpd)" +port=$(git config --get instaweb.port) +module_path="$(git config --get instaweb.modulepath)" + +conf="$GIT_DIR/gitweb/httpd.conf" + +# Defaults: + +# if installed, it doesn't need further configuration (module_path) +test -z "$httpd" && httpd='lighttpd -f' + +# any untaken local port will do... +test -z "$port" && port=1234 + +resolve_full_httpd () { + case "$httpd" in + *apache2*|*lighttpd*) + # ensure that the apache2/lighttpd command ends with "-f" + if ! echo "$httpd" | grep -- '-f *$' >/dev/null 2>&1 + then + httpd="$httpd -f" + fi + ;; + esac + + httpd_only="$(echo $httpd | cut -f1 -d' ')" + if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null;; esac + then + full_httpd=$httpd + else + # many httpds are installed in /usr/sbin or /usr/local/sbin + # these days and those are not in most users $PATHs + # in addition, we may have generated a server script + # in $fqgitdir/gitweb. + for i in /usr/local/sbin /usr/sbin "$fqgitdir/gitweb" + do + if test -x "$i/$httpd_only" + then + full_httpd=$i/$httpd + return + fi + done + + echo >&2 "$httpd_only not found. Install $httpd_only or use" \ + "--httpd to specify another httpd daemon." + exit 1 + fi +} + +start_httpd () { + # here $httpd should have a meaningful value + resolve_full_httpd + + # don't quote $full_httpd, there can be arguments to it (-f) + $full_httpd "$fqgitdir/gitweb/httpd.conf" + if test $? != 0; then + echo "Could not execute http daemon $httpd." + exit 1 + fi +} + +stop_httpd () { + test -f "$fqgitdir/pid" && kill $(cat "$fqgitdir/pid") +} + +while test $# != 0 +do + case "$1" in + --stop|stop) + stop_httpd + exit 0 + ;; + --start|start) + start_httpd + exit 0 + ;; + --restart|restart) + stop_httpd + start_httpd + exit 0 + ;; + -l|--local) + local=true + ;; + -d|--httpd) + shift + httpd="$1" + ;; + -b|--browser) + shift + browser="$1" + ;; + -p|--port) + shift + port="$1" + ;; + -m|--module-path) + shift + module_path="$1" + ;; + --) + ;; + *) + usage + ;; + esac + shift +done + +mkdir -p "$GIT_DIR/gitweb/tmp" +GIT_EXEC_PATH="$(git --exec-path)" +GIT_DIR="$fqgitdir" +export GIT_EXEC_PATH GIT_DIR + + +webrick_conf () { + # generate a standalone server script in $fqgitdir/gitweb. + cat >"$fqgitdir/gitweb/$httpd.rb" <<EOF +require 'webrick' +require 'yaml' +options = YAML::load_file(ARGV[0]) +options[:StartCallback] = proc do + File.open(options[:PidFile],"w") do |f| + f.puts Process.pid + end +end +options[:ServerType] = WEBrick::Daemon +server = WEBrick::HTTPServer.new(options) +['INT', 'TERM'].each do |signal| + trap(signal) {server.shutdown} +end +server.start +EOF + # generate a shell script to invoke the above ruby script, + # which assumes _ruby_ is in the user's $PATH. that's _one_ + # portable way to run ruby, which could be installed anywhere, + # really. + cat >"$fqgitdir/gitweb/$httpd" <<EOF +#!/bin/sh +exec ruby "$fqgitdir/gitweb/$httpd.rb" \$* +EOF + chmod +x "$fqgitdir/gitweb/$httpd" + + cat >"$conf" <<EOF +:Port: $port +:DocumentRoot: "$fqgitdir/gitweb" +:DirectoryIndex: ["gitweb.cgi"] +:PidFile: "$fqgitdir/pid" +EOF + test "$local" = true && echo ':BindAddress: "127.0.0.1"' >> "$conf" +} + +lighttpd_conf () { + cat > "$conf" <<EOF +server.document-root = "$fqgitdir/gitweb" +server.port = $port +server.modules = ( "mod_cgi" ) +server.indexfiles = ( "gitweb.cgi" ) +server.pid-file = "$fqgitdir/pid" +cgi.assign = ( ".cgi" => "" ) +mimetype.assign = ( ".css" => "text/css" ) +EOF + test x"$local" = xtrue && echo 'server.bind = "127.0.0.1"' >> "$conf" +} + +apache2_conf () { + test -z "$module_path" && module_path=/usr/lib/apache2/modules + mkdir -p "$GIT_DIR/gitweb/logs" + bind= + test x"$local" = xtrue && bind='127.0.0.1:' + echo 'text/css css' > $fqgitdir/mime.types + cat > "$conf" <<EOF +ServerName "git-instaweb" +ServerRoot "$fqgitdir/gitweb" +DocumentRoot "$fqgitdir/gitweb" +PidFile "$fqgitdir/pid" +Listen $bind$port +EOF + + for mod in mime dir; do + if test -e $module_path/mod_${mod}.so; then + echo "LoadModule ${mod}_module " \ + "$module_path/mod_${mod}.so" >> "$conf" + fi + done + cat >> "$conf" <<EOF +TypesConfig $fqgitdir/mime.types +DirectoryIndex gitweb.cgi +EOF + + # check to see if Dennis Stosberg's mod_perl compatibility patch + # (<20060621130708.Gcbc6e5c@leonov.stosberg.net>) has been applied + if test -f "$module_path/mod_perl.so" && grep '^our $gitbin' \ + "$GIT_DIR/gitweb/gitweb.cgi" >/dev/null + then + # favor mod_perl if available + cat >> "$conf" <<EOF +LoadModule perl_module $module_path/mod_perl.so +PerlPassEnv GIT_DIR +PerlPassEnv GIT_EXEC_DIR +<Location /gitweb.cgi> + SetHandler perl-script + PerlResponseHandler ModPerl::Registry + PerlOptions +ParseHeaders + Options +ExecCGI +</Location> +EOF + else + # plain-old CGI + resolve_full_httpd + list_mods=$(echo "$full_httpd" | sed "s/-f$/-l/") + $list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \ + echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf" + cat >> "$conf" <<EOF +AddHandler cgi-script .cgi +<Location /gitweb.cgi> + Options +ExecCGI +</Location> +EOF + fi +} + +script=' +s#^(my|our) \$projectroot =.*#$1 \$projectroot = "'$(dirname "$fqgitdir")'";#; +s#(my|our) \$gitbin =.*#$1 \$gitbin = "'$GIT_EXEC_PATH'";#; +s#(my|our) \$projects_list =.*#$1 \$projects_list = \$projectroot;#; +s#(my|our) \$git_temp =.*#$1 \$git_temp = "'$fqgitdir/gitweb/tmp'";#;' + +gitweb_cgi () { + cat > "$1.tmp" <<\EOFGITWEB +@@GITWEB_CGI@@ +EOFGITWEB + # Use the configured full path to perl to match the generated + # scripts' 'hashpling' line + "$PERL" -p -e "$script" "$1.tmp" > "$1" + chmod +x "$1" + rm -f "$1.tmp" +} + +gitweb_css () { + cat > "$1" <<\EOFGITWEB +@@GITWEB_CSS@@ +EOFGITWEB +} + +gitweb_cgi "$GIT_DIR/gitweb/gitweb.cgi" +gitweb_css "$GIT_DIR/gitweb/gitweb.css" + +case "$httpd" in +*lighttpd*) + lighttpd_conf + ;; +*apache2*) + apache2_conf + ;; +webrick) + webrick_conf + ;; +*) + echo "Unknown httpd specified: $httpd" + exit 1 + ;; +esac + +start_httpd +url=http://127.0.0.1:$port + +if test -n "$browser"; then + git web--browse -b "$browser" $url || echo $url +else + git web--browse -c "instaweb.browser" $url || echo $url +fi |