git-instaweb.shon commit git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir (08fc060)
   1#!/bin/sh
   2#
   3# Copyright (c) 2006 Eric Wong
   4#
   5
   6PERL='@@PERL@@'
   7OPTIONS_KEEPDASHDASH=
   8OPTIONS_SPEC="\
   9git instaweb [options] (--start | --stop | --restart)
  10--
  11l,local        only bind on 127.0.0.1
  12p,port=        the port to bind to
  13d,httpd=       the command to launch
  14b,browser=     the browser to launch
  15m,module-path= the module path (only needed for apache2)
  16 Action
  17stop           stop the web server
  18start          start the web server
  19restart        restart the web server
  20"
  21
  22. git-sh-setup
  23
  24fqgitdir="$GIT_DIR"
  25local="$(git config --bool --get instaweb.local)"
  26httpd="$(git config --get instaweb.httpd)"
  27port=$(git config --get instaweb.port)
  28module_path="$(git config --get instaweb.modulepath)"
  29
  30conf="$GIT_DIR/gitweb/httpd.conf"
  31
  32# Defaults:
  33
  34# if installed, it doesn't need further configuration (module_path)
  35test -z "$httpd" && httpd='lighttpd -f'
  36
  37# any untaken local port will do...
  38test -z "$port" && port=1234
  39
  40resolve_full_httpd () {
  41        case "$httpd" in
  42        *apache2*|*lighttpd*)
  43                # ensure that the apache2/lighttpd command ends with "-f"
  44                if ! echo "$httpd" | grep -- '-f *$' >/dev/null 2>&1
  45                then
  46                        httpd="$httpd -f"
  47                fi
  48                ;;
  49        esac
  50
  51        httpd_only="$(echo $httpd | cut -f1 -d' ')"
  52        if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null;; esac
  53        then
  54                full_httpd=$httpd
  55        else
  56                # many httpds are installed in /usr/sbin or /usr/local/sbin
  57                # these days and those are not in most users $PATHs
  58                # in addition, we may have generated a server script
  59                # in $fqgitdir/gitweb.
  60                for i in /usr/local/sbin /usr/sbin "$fqgitdir/gitweb"
  61                do
  62                        if test -x "$i/$httpd_only"
  63                        then
  64                                full_httpd=$i/$httpd
  65                                return
  66                        fi
  67                done
  68
  69                echo >&2 "$httpd_only not found. Install $httpd_only or use" \
  70                     "--httpd to specify another httpd daemon."
  71                exit 1
  72        fi
  73}
  74
  75start_httpd () {
  76        # here $httpd should have a meaningful value
  77        resolve_full_httpd
  78
  79        # don't quote $full_httpd, there can be arguments to it (-f)
  80        $full_httpd "$fqgitdir/gitweb/httpd.conf"
  81        if test $? != 0; then
  82                echo "Could not execute http daemon $httpd."
  83                exit 1
  84        fi
  85}
  86
  87stop_httpd () {
  88        test -f "$fqgitdir/pid" && kill $(cat "$fqgitdir/pid")
  89}
  90
  91while test $# != 0
  92do
  93        case "$1" in
  94        --stop|stop)
  95                stop_httpd
  96                exit 0
  97                ;;
  98        --start|start)
  99                start_httpd
 100                exit 0
 101                ;;
 102        --restart|restart)
 103                stop_httpd
 104                start_httpd
 105                exit 0
 106                ;;
 107        -l|--local)
 108                local=true
 109                ;;
 110        -d|--httpd)
 111                shift
 112                httpd="$1"
 113                ;;
 114        -b|--browser)
 115                shift
 116                browser="$1"
 117                ;;
 118        -p|--port)
 119                shift
 120                port="$1"
 121                ;;
 122        -m|--module-path)
 123                shift
 124                module_path="$1"
 125                ;;
 126        --)
 127                ;;
 128        *)
 129                usage
 130                ;;
 131        esac
 132        shift
 133done
 134
 135mkdir -p "$GIT_DIR/gitweb/tmp"
 136GIT_EXEC_PATH="$(git --exec-path)"
 137GIT_DIR="$fqgitdir"
 138export GIT_EXEC_PATH GIT_DIR
 139
 140
 141webrick_conf () {
 142        # generate a standalone server script in $fqgitdir/gitweb.
 143        cat >"$fqgitdir/gitweb/$httpd.rb" <<EOF
 144require 'webrick'
 145require 'yaml'
 146options = YAML::load_file(ARGV[0])
 147options[:StartCallback] = proc do
 148  File.open(options[:PidFile],"w") do |f|
 149    f.puts Process.pid
 150  end
 151end
 152options[:ServerType] = WEBrick::Daemon
 153server = WEBrick::HTTPServer.new(options)
 154['INT', 'TERM'].each do |signal|
 155  trap(signal) {server.shutdown}
 156end
 157server.start
 158EOF
 159        # generate a shell script to invoke the above ruby script,
 160        # which assumes _ruby_ is in the user's $PATH. that's _one_
 161        # portable way to run ruby, which could be installed anywhere,
 162        # really.
 163        cat >"$fqgitdir/gitweb/$httpd" <<EOF
 164#!/bin/sh
 165exec ruby "$fqgitdir/gitweb/$httpd.rb" \$*
 166EOF
 167        chmod +x "$fqgitdir/gitweb/$httpd"
 168
 169        cat >"$conf" <<EOF
 170:Port: $port
 171:DocumentRoot: "$fqgitdir/gitweb"
 172:DirectoryIndex: ["gitweb.cgi"]
 173:PidFile: "$fqgitdir/pid"
 174EOF
 175        test "$local" = true && echo ':BindAddress: "127.0.0.1"' >> "$conf"
 176}
 177
 178lighttpd_conf () {
 179        cat > "$conf" <<EOF
 180server.document-root = "$fqgitdir/gitweb"
 181server.port = $port
 182server.modules = ( "mod_cgi" )
 183server.indexfiles = ( "gitweb.cgi" )
 184server.pid-file = "$fqgitdir/pid"
 185cgi.assign = ( ".cgi" => "" )
 186mimetype.assign = ( ".css" => "text/css" )
 187EOF
 188        test x"$local" = xtrue && echo 'server.bind = "127.0.0.1"' >> "$conf"
 189}
 190
 191apache2_conf () {
 192        test -z "$module_path" && module_path=/usr/lib/apache2/modules
 193        mkdir -p "$GIT_DIR/gitweb/logs"
 194        bind=
 195        test x"$local" = xtrue && bind='127.0.0.1:'
 196        echo 'text/css css' > $fqgitdir/mime.types
 197        cat > "$conf" <<EOF
 198ServerName "git-instaweb"
 199ServerRoot "$fqgitdir/gitweb"
 200DocumentRoot "$fqgitdir/gitweb"
 201PidFile "$fqgitdir/pid"
 202Listen $bind$port
 203EOF
 204
 205        for mod in mime dir; do
 206                if test -e $module_path/mod_${mod}.so; then
 207                        echo "LoadModule ${mod}_module " \
 208                             "$module_path/mod_${mod}.so" >> "$conf"
 209                fi
 210        done
 211        cat >> "$conf" <<EOF
 212TypesConfig $fqgitdir/mime.types
 213DirectoryIndex gitweb.cgi
 214EOF
 215
 216        # check to see if Dennis Stosberg's mod_perl compatibility patch
 217        # (<20060621130708.Gcbc6e5c@leonov.stosberg.net>) has been applied
 218        if test -f "$module_path/mod_perl.so" && grep '^our $gitbin' \
 219                                "$GIT_DIR/gitweb/gitweb.cgi" >/dev/null
 220        then
 221                # favor mod_perl if available
 222                cat >> "$conf" <<EOF
 223LoadModule perl_module $module_path/mod_perl.so
 224PerlPassEnv GIT_DIR
 225PerlPassEnv GIT_EXEC_DIR
 226<Location /gitweb.cgi>
 227        SetHandler perl-script
 228        PerlResponseHandler ModPerl::Registry
 229        PerlOptions +ParseHeaders
 230        Options +ExecCGI
 231</Location>
 232EOF
 233        else
 234                # plain-old CGI
 235                resolve_full_httpd
 236                list_mods=$(echo "$full_httpd" | sed "s/-f$/-l/")
 237                $list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \
 238                echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
 239                cat >> "$conf" <<EOF
 240AddHandler cgi-script .cgi
 241<Location /gitweb.cgi>
 242        Options +ExecCGI
 243</Location>
 244EOF
 245        fi
 246}
 247
 248script='
 249s#^(my|our) \$projectroot =.*#$1 \$projectroot = "'$(dirname "$fqgitdir")'";#;
 250s#(my|our) \$gitbin =.*#$1 \$gitbin = "'$GIT_EXEC_PATH'";#;
 251s#(my|our) \$projects_list =.*#$1 \$projects_list = \$projectroot;#;
 252s#(my|our) \$git_temp =.*#$1 \$git_temp = "'$fqgitdir/gitweb/tmp'";#;'
 253
 254gitweb_cgi () {
 255        cat > "$1.tmp" <<\EOFGITWEB
 256@@GITWEB_CGI@@
 257EOFGITWEB
 258        # Use the configured full path to perl to match the generated
 259        # scripts' 'hashpling' line
 260        "$PERL" -p -e "$script" "$1.tmp"  > "$1"
 261        chmod +x "$1"
 262        rm -f "$1.tmp"
 263}
 264
 265gitweb_css () {
 266        cat > "$1" <<\EOFGITWEB
 267@@GITWEB_CSS@@
 268EOFGITWEB
 269}
 270
 271gitweb_cgi "$GIT_DIR/gitweb/gitweb.cgi"
 272gitweb_css "$GIT_DIR/gitweb/gitweb.css"
 273
 274case "$httpd" in
 275*lighttpd*)
 276        lighttpd_conf
 277        ;;
 278*apache2*)
 279        apache2_conf
 280        ;;
 281webrick)
 282        webrick_conf
 283        ;;
 284*)
 285        echo "Unknown httpd specified: $httpd"
 286        exit 1
 287        ;;
 288esac
 289
 290start_httpd
 291url=http://127.0.0.1:$port
 292
 293if test -n "$browser"; then
 294        git web--browse -b "$browser" $url || echo $url
 295else
 296        git web--browse -c "instaweb.browser" $url || echo $url
 297fi