git-instaweb.shon commit Introduce "skip-worktree" bit in index, teach Git to get/set this bit (44a3691)
   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 2>&1;; 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_setenv", "mod_cgi" )
 183server.indexfiles = ( "gitweb.cgi" )
 184server.pid-file = "$fqgitdir/pid"
 185server.errorlog = "$fqgitdir/gitweb/error.log"
 186
 187# to enable, add "mod_access", "mod_accesslog" to server.modules
 188# variable above and uncomment this
 189#accesslog.filename = "$fqgitdir/gitweb/access.log"
 190
 191setenv.add-environment = ( "PATH" => "/usr/local/bin:/usr/bin:/bin" )
 192
 193cgi.assign = ( ".cgi" => "" )
 194
 195# mimetype mapping
 196mimetype.assign             = (
 197  ".pdf"          =>      "application/pdf",
 198  ".sig"          =>      "application/pgp-signature",
 199  ".spl"          =>      "application/futuresplash",
 200  ".class"        =>      "application/octet-stream",
 201  ".ps"           =>      "application/postscript",
 202  ".torrent"      =>      "application/x-bittorrent",
 203  ".dvi"          =>      "application/x-dvi",
 204  ".gz"           =>      "application/x-gzip",
 205  ".pac"          =>      "application/x-ns-proxy-autoconfig",
 206  ".swf"          =>      "application/x-shockwave-flash",
 207  ".tar.gz"       =>      "application/x-tgz",
 208  ".tgz"          =>      "application/x-tgz",
 209  ".tar"          =>      "application/x-tar",
 210  ".zip"          =>      "application/zip",
 211  ".mp3"          =>      "audio/mpeg",
 212  ".m3u"          =>      "audio/x-mpegurl",
 213  ".wma"          =>      "audio/x-ms-wma",
 214  ".wax"          =>      "audio/x-ms-wax",
 215  ".ogg"          =>      "application/ogg",
 216  ".wav"          =>      "audio/x-wav",
 217  ".gif"          =>      "image/gif",
 218  ".jpg"          =>      "image/jpeg",
 219  ".jpeg"         =>      "image/jpeg",
 220  ".png"          =>      "image/png",
 221  ".xbm"          =>      "image/x-xbitmap",
 222  ".xpm"          =>      "image/x-xpixmap",
 223  ".xwd"          =>      "image/x-xwindowdump",
 224  ".css"          =>      "text/css",
 225  ".html"         =>      "text/html",
 226  ".htm"          =>      "text/html",
 227  ".js"           =>      "text/javascript",
 228  ".asc"          =>      "text/plain",
 229  ".c"            =>      "text/plain",
 230  ".cpp"          =>      "text/plain",
 231  ".log"          =>      "text/plain",
 232  ".conf"         =>      "text/plain",
 233  ".text"         =>      "text/plain",
 234  ".txt"          =>      "text/plain",
 235  ".dtd"          =>      "text/xml",
 236  ".xml"          =>      "text/xml",
 237  ".mpeg"         =>      "video/mpeg",
 238  ".mpg"          =>      "video/mpeg",
 239  ".mov"          =>      "video/quicktime",
 240  ".qt"           =>      "video/quicktime",
 241  ".avi"          =>      "video/x-msvideo",
 242  ".asf"          =>      "video/x-ms-asf",
 243  ".asx"          =>      "video/x-ms-asf",
 244  ".wmv"          =>      "video/x-ms-wmv",
 245  ".bz2"          =>      "application/x-bzip",
 246  ".tbz"          =>      "application/x-bzip-compressed-tar",
 247  ".tar.bz2"      =>      "application/x-bzip-compressed-tar",
 248  ""              =>      "text/plain"
 249 )
 250EOF
 251        test x"$local" = xtrue && echo 'server.bind = "127.0.0.1"' >> "$conf"
 252}
 253
 254apache2_conf () {
 255        test -z "$module_path" && module_path=/usr/lib/apache2/modules
 256        mkdir -p "$GIT_DIR/gitweb/logs"
 257        bind=
 258        test x"$local" = xtrue && bind='127.0.0.1:'
 259        echo 'text/css css' > "$fqgitdir/mime.types"
 260        cat > "$conf" <<EOF
 261ServerName "git-instaweb"
 262ServerRoot "$fqgitdir/gitweb"
 263DocumentRoot "$fqgitdir/gitweb"
 264PidFile "$fqgitdir/pid"
 265Listen $bind$port
 266EOF
 267
 268        for mod in mime dir; do
 269                if test -e $module_path/mod_${mod}.so; then
 270                        echo "LoadModule ${mod}_module " \
 271                             "$module_path/mod_${mod}.so" >> "$conf"
 272                fi
 273        done
 274        cat >> "$conf" <<EOF
 275TypesConfig "$fqgitdir/mime.types"
 276DirectoryIndex gitweb.cgi
 277EOF
 278
 279        # check to see if Dennis Stosberg's mod_perl compatibility patch
 280        # (<20060621130708.Gcbc6e5c@leonov.stosberg.net>) has been applied
 281        if test -f "$module_path/mod_perl.so" && grep 'MOD_PERL' \
 282                                "$GIT_DIR/gitweb/gitweb.cgi" >/dev/null
 283        then
 284                # favor mod_perl if available
 285                cat >> "$conf" <<EOF
 286LoadModule perl_module $module_path/mod_perl.so
 287PerlPassEnv GIT_DIR
 288PerlPassEnv GIT_EXEC_DIR
 289<Location /gitweb.cgi>
 290        SetHandler perl-script
 291        PerlResponseHandler ModPerl::Registry
 292        PerlOptions +ParseHeaders
 293        Options +ExecCGI
 294</Location>
 295EOF
 296        else
 297                # plain-old CGI
 298                resolve_full_httpd
 299                list_mods=$(echo "$full_httpd" | sed "s/-f$/-l/")
 300                $list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \
 301                echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
 302                cat >> "$conf" <<EOF
 303AddHandler cgi-script .cgi
 304<Location /gitweb.cgi>
 305        Options +ExecCGI
 306</Location>
 307EOF
 308        fi
 309}
 310
 311script='
 312s#^(my|our) \$projectroot =.*#$1 \$projectroot = "'$(dirname "$fqgitdir")'";#;
 313s#(my|our) \$gitbin =.*#$1 \$gitbin = "'$GIT_EXEC_PATH'";#;
 314s#(my|our) \$projects_list =.*#$1 \$projects_list = \$projectroot;#;
 315s#(my|our) \$git_temp =.*#$1 \$git_temp = "'$fqgitdir/gitweb/tmp'";#;'
 316
 317gitweb_cgi () {
 318        cat > "$1.tmp" <<\EOFGITWEB
 319@@GITWEB_CGI@@
 320EOFGITWEB
 321        # Use the configured full path to perl to match the generated
 322        # scripts' 'hashpling' line
 323        "$PERL" -p -e "$script" "$1.tmp"  > "$1"
 324        chmod +x "$1"
 325        rm -f "$1.tmp"
 326}
 327
 328gitweb_css () {
 329        cat > "$1" <<\EOFGITWEB
 330@@GITWEB_CSS@@
 331EOFGITWEB
 332}
 333
 334gitweb_cgi "$GIT_DIR/gitweb/gitweb.cgi"
 335gitweb_css "$GIT_DIR/gitweb/gitweb.css"
 336
 337case "$httpd" in
 338*lighttpd*)
 339        lighttpd_conf
 340        ;;
 341*apache2*)
 342        apache2_conf
 343        ;;
 344webrick)
 345        webrick_conf
 346        ;;
 347*)
 348        echo "Unknown httpd specified: $httpd"
 349        exit 1
 350        ;;
 351esac
 352
 353start_httpd
 354url=http://127.0.0.1:$port
 355
 356if test -n "$browser"; then
 357        git web--browse -b "$browser" $url || echo $url
 358else
 359        git web--browse -c "instaweb.browser" $url || echo $url
 360fi