hooks--update: fix test for properly set up project description file
[git] / git-instaweb.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Eric Wong
4 #
5 USAGE='[--start] [--stop] [--restart]
6   [--local] [--httpd=<httpd>] [--port=<port>] [--browser=<browser>]
7   [--module-path=<path> (for Apache2 only)]'
8
9 . git-sh-setup
10
11 fqgitdir="$GIT_DIR"
12 local="`git config --bool --get instaweb.local`"
13 httpd="`git config --get instaweb.httpd`"
14 browser="`git config --get instaweb.browser`"
15 port=`git config --get instaweb.port`
16 module_path="`git config --get instaweb.modulepath`"
17
18 conf=$GIT_DIR/gitweb/httpd.conf
19
20 # Defaults:
21
22 # if installed, it doesn't need further configuration (module_path)
23 test -z "$httpd" && httpd='lighttpd -f'
24
25 # probably the most popular browser among gitweb users
26 test -z "$browser" && browser='firefox'
27
28 # any untaken local port will do...
29 test -z "$port" && port=1234
30
31 start_httpd () {
32         httpd_only="`echo $httpd | cut -f1 -d' '`"
33         if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null;; esac
34         then
35                 $httpd $fqgitdir/gitweb/httpd.conf
36         else
37                 # many httpds are installed in /usr/sbin or /usr/local/sbin
38                 # these days and those are not in most users $PATHs
39                 # in addition, we may have generated a server script
40                 # in $fqgitdir/gitweb.
41                 for i in /usr/local/sbin /usr/sbin "$fqgitdir/gitweb"
42                 do
43                         if test -x "$i/$httpd_only"
44                         then
45                                 # don't quote $httpd, there can be
46                                 # arguments to it (-f)
47                                 $i/$httpd "$fqgitdir/gitweb/httpd.conf"
48                                 return
49                         fi
50                 done
51                 echo "$httpd_only not found. Install $httpd_only or use" \
52                      "--httpd to specify another http daemon."
53                 exit 1
54         fi
55         if test $? != 0; then
56                 echo "Could not execute http daemon $httpd."
57                 exit 1
58         fi
59 }
60
61 stop_httpd () {
62         test -f "$fqgitdir/pid" && kill `cat "$fqgitdir/pid"`
63 }
64
65 while test $# != 0
66 do
67         case "$1" in
68         --stop|stop)
69                 stop_httpd
70                 exit 0
71                 ;;
72         --start|start)
73                 start_httpd
74                 exit 0
75                 ;;
76         --restart|restart)
77                 stop_httpd
78                 start_httpd
79                 exit 0
80                 ;;
81         --local|-l)
82                 local=true
83                 ;;
84         -d|--httpd|--httpd=*)
85                 case "$#,$1" in
86                 *,*=*)
87                         httpd=`expr "$1" : '-[^=]*=\(.*\)'` ;;
88                 1,*)
89                         usage ;;
90                 *)
91                         httpd="$2"
92                         shift ;;
93                 esac
94                 ;;
95         -b|--browser|--browser=*)
96                 case "$#,$1" in
97                 *,*=*)
98                         browser=`expr "$1" : '-[^=]*=\(.*\)'` ;;
99                 1,*)
100                         usage ;;
101                 *)
102                         browser="$2"
103                         shift ;;
104                 esac
105                 ;;
106         -p|--port|--port=*)
107                 case "$#,$1" in
108                 *,*=*)
109                         port=`expr "$1" : '-[^=]*=\(.*\)'` ;;
110                 1,*)
111                         usage ;;
112                 *)
113                         port="$2"
114                         shift ;;
115                 esac
116                 ;;
117         -m|--module-path=*|--module-path)
118                 case "$#,$1" in
119                 *,*=*)
120                         module_path=`expr "$1" : '-[^=]*=\(.*\)'` ;;
121                 1,*)
122                         usage ;;
123                 *)
124                         module_path="$2"
125                         shift ;;
126                 esac
127                 ;;
128         *)
129                 usage
130                 ;;
131         esac
132         shift
133 done
134
135 mkdir -p "$GIT_DIR/gitweb/tmp"
136 GIT_EXEC_PATH="`git --exec-path`"
137 GIT_DIR="$fqgitdir"
138 export GIT_EXEC_PATH GIT_DIR
139
140
141 webrick_conf () {
142         # generate a standalone server script in $fqgitdir/gitweb.
143         cat >"$fqgitdir/gitweb/$httpd.rb" <<EOF
144 require 'webrick'
145 require 'yaml'
146 options = YAML::load_file(ARGV[0])
147 options[:StartCallback] = proc do
148   File.open(options[:PidFile],"w") do |f|
149     f.puts Process.pid
150   end
151 end
152 options[:ServerType] = WEBrick::Daemon
153 server = WEBrick::HTTPServer.new(options)
154 ['INT', 'TERM'].each do |signal|
155   trap(signal) {server.shutdown}
156 end
157 server.start
158 EOF
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
165 exec ruby "$fqgitdir/gitweb/$httpd.rb" \$*
166 EOF
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"
174 EOF
175         test "$local" = true && echo ':BindAddress: "127.0.0.1"' >> "$conf"
176 }
177
178 lighttpd_conf () {
179         cat > "$conf" <<EOF
180 server.document-root = "$fqgitdir/gitweb"
181 server.port = $port
182 server.modules = ( "mod_cgi" )
183 server.indexfiles = ( "gitweb.cgi" )
184 server.pid-file = "$fqgitdir/pid"
185 cgi.assign = ( ".cgi" => "" )
186 mimetype.assign = ( ".css" => "text/css" )
187 EOF
188         test "$local" = true && echo 'server.bind = "127.0.0.1"' >> "$conf"
189 }
190
191 apache2_conf () {
192         test -z "$module_path" && module_path=/usr/lib/apache2/modules
193         mkdir -p "$GIT_DIR/gitweb/logs"
194         bind=
195         test "$local" = true && bind='127.0.0.1:'
196         echo 'text/css css' > $fqgitdir/mime.types
197         cat > "$conf" <<EOF
198 ServerName "git-instaweb"
199 ServerRoot "$fqgitdir/gitweb"
200 DocumentRoot "$fqgitdir/gitweb"
201 PidFile "$fqgitdir/pid"
202 Listen $bind$port
203 EOF
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
212 TypesConfig $fqgitdir/mime.types
213 DirectoryIndex gitweb.cgi
214 EOF
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
223 LoadModule perl_module $module_path/mod_perl.so
224 PerlPassEnv GIT_DIR
225 PerlPassEnv GIT_EXEC_DIR
226 <Location /gitweb.cgi>
227         SetHandler perl-script
228         PerlResponseHandler ModPerl::Registry
229         PerlOptions +ParseHeaders
230         Options +ExecCGI
231 </Location>
232 EOF
233         else
234                 # plain-old CGI
235                 list_mods=`echo "$httpd" | sed "s/-f$/-l/"`
236                 $list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \
237                 echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
238                 cat >> "$conf" <<EOF
239 AddHandler cgi-script .cgi
240 <Location /gitweb.cgi>
241         Options +ExecCGI
242 </Location>
243 EOF
244         fi
245 }
246
247 script='
248 s#^\(my\|our\) $projectroot =.*#\1 $projectroot = "'`dirname $fqgitdir`'";#
249 s#\(my\|our\) $gitbin =.*#\1 $gitbin = "'$GIT_EXEC_PATH'";#
250 s#\(my\|our\) $projects_list =.*#\1 $projects_list = $projectroot;#
251 s#\(my\|our\) $git_temp =.*#\1 $git_temp = "'$fqgitdir/gitweb/tmp'";#'
252
253 gitweb_cgi () {
254         cat > "$1.tmp" <<\EOFGITWEB
255 @@GITWEB_CGI@@
256 EOFGITWEB
257         sed "$script" "$1.tmp"  > "$1"
258         chmod +x "$1"
259         rm -f "$1.tmp"
260 }
261
262 gitweb_css () {
263         cat > "$1" <<\EOFGITWEB
264 @@GITWEB_CSS@@
265 EOFGITWEB
266 }
267
268 gitweb_cgi $GIT_DIR/gitweb/gitweb.cgi
269 gitweb_css $GIT_DIR/gitweb/gitweb.css
270
271 case "$httpd" in
272 *lighttpd*)
273         lighttpd_conf
274         ;;
275 *apache2*)
276         apache2_conf
277         ;;
278 webrick)
279         webrick_conf
280         ;;
281 *)
282         echo "Unknown httpd specified: $httpd"
283         exit 1
284         ;;
285 esac
286
287 start_httpd
288 test -z "$browser" && browser=echo
289 url=http://127.0.0.1:$port
290 $browser $url || echo $url