install.sh: verify POSIX sh sanity
[girocco.git] / install.sh
blob09abb4cf300a7e8d9ddbef2b3f34dadb78af2903
1 #!/bin/sh
2 # The Girocco installation script
3 # We will OVERWRITE basedir!
5 set -e
7 [ -n "$MAKE" ] || MAKE="$(MAKEFLAGS= make -s gnu_make_command_name | grep '^gnu_make_command_name=' | sed 's/^[^=]*=//')"
8 if [ -z "$MAKE" ]; then
9 echo "ERROR: cannot determine name of the GNU make command" >&2
10 echo "Please set MAKE to the name of the GNU make executable" >&2
11 exit 1
14 # Run perl module checker
15 if [ ! -x toolbox/check-perl-modules.pl ]; then
16 echo "ERROR: missing toolbox/check-perl-modules.pl!" >&2
17 exit 1
20 # What Config should we use?
21 [ -n "$GIROCCO_CONF" ] || GIROCCO_CONF=Girocco::Config
22 echo "*** Initializing using $GIROCCO_CONF..."
24 # First run Girocco::Config consistency checks
25 perl -I. -M$GIROCCO_CONF -e ''
27 . ./shlib.sh
28 umask 0022
29 "$var_perl_bin" toolbox/check-perl-modules.pl
31 # $1 must exist and be a dir
32 # $2 may exist but must be a dir
33 # $3 must not exist
34 # After call $2 will be renamed to $3 (if $2 existed)
35 # And $1 will be renamed to $2
36 quick_move() {
37 [ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] || { echo "fatal: quick_move: bad args: '$1' '$2' '$3'" >&2; exit 1; }
38 ! [ -e "$3" ] || { echo "fatal: quick_move: already exists: $3" >&2; exit 1; }
39 [ -d "$1" ] || { echo "fatal: quick_move: no such dir: $1" >&2; exit 1; }
40 [ ! -e "$2" -o -d "$2" ] || { echo "fatal: quick_move: not a dir: $2" >&2; exit 1; }
41 perl -e 'rename($ARGV[1], $ARGV[2]) or die "rename failed: $!\n" if -d $ARGV[1];
42 rename($ARGV[0], $ARGV[1]) or die "rename failed: $!\n"; exit 0;' "$1" "$2" "$3" || {
43 echo "fatal: quick_move: rename failed" >&2
44 exit 1
46 ! [ -d "$1" ] && [ -d "$2" ] || {
47 echo "fatal: quick_move: rename failed" >&2
48 exit 1
52 check_sh_builtin() (
53 "unset" -f command
54 "command" "$var_sh_bin" -c '{ "unset" -f unalias command "$1" || :; "unalias" "$1" || :; } >/dev/null 2>&1; "command" -v "$1"' "$var_sh_bin" "$1"
55 ) 2>/dev/null
57 owngroup=""
58 [ -z "$cfg_owning_group" ] || owngroup=":$cfg_owning_group"
59 if [ -n "$cfg_httpspushurl" -a -z "$cfg_certsdir" ]; then
60 echo "ERROR: \$httpspushurl is set but \$certsdir is not!" >&2
61 echo "ERROR: perhaps you have an incorrect Config.pm?" >&2
62 exit 1
66 # Check for extra required tools
67 if [ -n "$cfg_xmllint_readme" -a "$cfg_xmllint_readme" != "0" ] && ! command -v xmllint >/dev/null; then
68 echo "ERROR: \$xmllint_readme set but xmllint not in \$PATH!" >&2
69 exit 1
73 echo "*** Checking for compiled utilities..."
74 if [ ! -x src/can_user_push ]; then
75 echo "ERROR: src/can_user_push is not built! Did you _REALLY_ read INSTALL?" >&2
76 echo "ERROR: perhaps you forgot to run make?" >&2
77 exit 1
79 if [ ! -x src/can_user_push_http ]; then
80 echo "ERROR: src/can_user_push_http is not built! Did you _REALLY_ read INSTALL?" >&2
81 echo "ERROR: perhaps you forgot to run make?" >&2
82 exit 1
84 if [ ! -x src/getent ]; then
85 echo "ERROR: src/getent is not built! Did you _REALLY_ read INSTALL?" >&2
86 echo "ERROR: perhaps you forgot to run make?" >&2
87 exit 1
89 if [ ! -x src/get_user_uuid ]; then
90 echo "ERROR: src/get_user_uuid is not built! Did you _REALLY_ read INSTALL?" >&2
91 echo "ERROR: perhaps you forgot to run make?" >&2
92 exit 1
94 if [ ! -x src/list_packs ]; then
95 echo "ERROR: src/list_packs is not built! Did you _REALLY_ read INSTALL?" >&2
96 echo "ERROR: perhaps you forgot to run make?" >&2
97 exit 1
99 if [ ! -x src/peek_packet ]; then
100 echo "ERROR: src/peek_packet is not built! Did you _REALLY_ read INSTALL?" >&2
101 echo "ERROR: perhaps you forgot to run make?" >&2
102 exit 1
104 if [ ! -x src/rangecgi ]; then
105 echo "ERROR: src/rangecgi is not built! Did you _REALLY_ read INSTALL?" >&2
106 echo "ERROR: perhaps you forgot to run make?" >&2
107 exit 1
109 if [ ! -x src/strftime ]; then
110 echo "ERROR: src/strftime is not built! Did you _REALLY_ read INSTALL?" >&2
111 echo "ERROR: perhaps you forgot to run make?" >&2
112 exit 1
114 if [ ! -x src/throttle ]; then
115 echo "ERROR: src/throttle is not built! Did you _REALLY_ read INSTALL?" >&2
116 echo "ERROR: perhaps you forgot to run make?" >&2
117 exit 1
121 echo "*** Checking for ezcert..."
122 if ! [ -f ezcert.git/CACreateCert -a -x ezcert.git/CACreateCert ]; then
123 echo "ERROR: ezcert.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
124 exit 1
128 echo "*** Checking for git..."
129 case "$cfg_git_bin" in /*) :;; *)
130 echo 'ERROR: $Girocco::Config::git_bin must be set to an absolute path' >&2
131 exit 1
132 esac
133 if [ ! -x "$cfg_git_bin" ]; then
134 echo "ERROR: $cfg_git_bin does not exist or is not executable" >&2
135 exit 1
137 if ! git_version="$("$cfg_git_bin" version)"; then
138 echo "ERROR: $cfg_git_bin version failed" >&2
139 exit 1
141 case "$git_version" in
142 [Gg]"it version "*) :;;
144 echo "ERROR: '$cfg_git_bin version' output does not start with 'git version '" >&2
145 exit 1
146 esac
147 echo "Found $cfg_git_bin $git_version"
148 git_vernum="$(echo "$git_version" | sed -ne 's/^[^0-9]*\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$/\1/p')"
149 echo "*** Checking Git $git_vernum for compatibility..."
150 if [ "$(vcmp "$git_vernum" 1.6.6)" -lt 0 ]; then
151 echo 'ERROR: $Girocco::Config::git_bin must be at least Git version 1.6.6'
152 exit 1
154 if [ "$(vcmp "$git_vernum" 1.6.6.3)" -lt 0 ]; then
155 echo 'WARNING: $Girocco::Config::git_bin version < 1.6.6.3, clients will not see useful error messages'
157 if [ "$(vcmp "$git_vernum" 1.7.3)" -lt 0 ]; then
158 cat <<'EOT'
161 *** SEVERE WARNING: $Girocco::Config::git_bin is set to a version of Git before 1.7.3
164 Some Girocco functionality will be gracefully disabled and other things will
165 just not work at all such as race condition protection against simultaneous
166 client pushes and server garbage collections.
170 if [ -n "$cfg_mirror" -a "$(vcmp "$git_vernum" 1.7.5)" -lt 0 ]; then
171 echo 'WARNING: $Girocco::Config::git_bin version < 1.7.5 and mirroring enabled, some sources can cause an infinite fetch loop'
173 if [ "$(vcmp "$git_vernum" 1.7.6.6)" -lt 0 ]; then
174 echo 'WARNING: $Girocco::Config::git_bin version < 1.7.6.6, performance may be degraded'
176 if [ "$(uname -m 2>/dev/null)" = "x86_64" ] && [ "$(vcmp "$git_vernum" 1.7.11)" -ge 0 ]; then
177 echo 'WARNING: $Girocco::Config::git_bin version >= 1.7.11 and x86_64, make sure Git built WITHOUT XDL_FAST_HASH'
178 echo 'WARNING: See http://mid.mail-archive.com/20141222041944.GA441@peff.net for details'
180 if [ "$(vcmp "$git_vernum" 1.8.4.2)" -ge 0 ] && [ -n "$cfg_mirror" -a "$(vcmp "$git_vernum" 2)" -lt 0 ]; then
181 echo 'WARNING: $Girocco::Config::git_bin version >= 1.8.4.2 and < 2.0.0, git-daemon needs write access for shallow clones'
182 echo 'WARNING: $Girocco::Config::git_bin version >= 1.8.4.2 and < 2.0.0, shallow clones will leave repository turds'
184 if [ "$(vcmp "$git_vernum" 1.8.4.3)" -lt 0 ]; then
185 echo 'WARNING: $Girocco::Config::git_bin version < 1.8.4.3, clients will not receive symref=HEAD:refs/heads/...'
187 if [ "$(vcmp "$git_vernum" 2.1)" -lt 0 ]; then
188 echo 'WARNING: $Girocco::Config::git_bin version < 2.1.0, pack bitmaps will not be available'
190 if [ "$(vcmp "$git_vernum" 2.1)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.1.3)" -lt 0 ]; then
191 echo 'WARNING: $Girocco::Config::git_bin version >= 2.1.0 and < 2.1.3, pack bitmaps may not be reliable, please upgrade to at least Git version 2.1.3'
193 if [ "$(vcmp "$git_vernum" 2.2)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.3.2)" -lt 0 ]; then
194 cat <<'EOT'
197 *** ERROR: $Girocco::Config::git_bin is set to an incompatible version of Git
200 Git versions starting with 2.2.0 and continuing up through 2.3.1 are incompatible
201 with Girocco due to various unresolved issues. Please either downgrade to 2.1.4
202 or earlier or, more preferred, upgrade to 2.3.2 (ideally 2.4.11) or later.
204 In order to bypass this check you will have to modify install.sh in which case
205 USE THE SELECTED GIT BINARY AT YOUR OWN RISK!
208 exit 1
210 if [ "$(vcmp "$git_vernum" 2.3.3)" -lt 0 ]; then
211 echo 'WARNING: $Girocco::Config::git_bin version < 2.3.3, performance will be sub-optimal'
213 if [ "$(vcmp "$git_vernum" 2.4.4)" -lt 0 ]; then
214 echo 'WARNING: $Girocco::Config::git_bin version < 2.4.4, many refs smart HTTP fetches can deadlock'
216 secmsg=
217 if [ "$(vcmp "$git_vernum" 2.4.11)" -lt 0 ]; then
218 secmsg='prior to 2.4.11'
220 if [ "$(vcmp "$git_vernum" 2.5)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.5.5)" -lt 0 ]; then
221 secmsg='2.5.x prior to 2.5.5'
223 if [ "$(vcmp "$git_vernum" 2.6)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.6.6)" -lt 0 ]; then
224 secmsg='2.6.x prior to 2.6.6'
226 if [ "$(vcmp "$git_vernum" 2.7)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.7.4)" -lt 0 ]; then
227 secmsg='2.7.x prior to 2.7.4'
229 if [ -n "$secmsg" ]; then
230 cat <<EOT
233 *** SEVERE WARNING: \$Girocco::Config::git_bin is set to a version of Git $secmsg
236 Security issues exist in Git versions prior to 2.4.11, 2.5.x prior to 2.5.5,
237 2.6.x prior to 2.6.6 and 2.7.x prior to 2.7.4.
239 Besides the security fixes included in later versions, versions prior to
240 2.2.0 may accidentally prune unreachable loose objects earlier than
241 intended. Since Git version 2.4.11 is the minimum version to include all
242 security fixes to date, it should be considered the absolute minimum
243 version of Git to use when running Girocco.
245 This is not enforced, but Git is easy to build from the git.git submodule
246 and upgrading to GIT VERSION 2.4.11 OR LATER IS HIGHLY RECOMMENDED.
248 We will now pause for a moment so you can reflect on this warning.
251 sleep 60
253 if [ -n "$cfg_mirror" -a "$cfg_mirror" != 0 ] && grep -q ns_parserr "$cfg_git_bin"; then
254 cat <<'EOT'
257 *** WARNING: $Girocco::Config::git_bin is set to a questionable Git binary
260 You appear to have enabled mirroring and the Git binary you have selected
261 appears to contain an experimental patch that cannot be disabled. This
262 patch can generate invalid network DNS traffic and/or cause long delays
263 when fetching using the "git:" protocol when no port number is specified.
264 It may also end up retrieving repsitory contents from a host other than
265 the one specified in the "git:" URL when the port is omitted.
267 You are advised to either build your own version of Git (the problem patch
268 is not part of the official Git repository) or disable mirroring (via the
269 $Girocco::Config:mirror setting) to avoid these potential problems.
271 USE THE SELECTED GIT BINARY AT YOUR OWN RISK!
274 sleep 5
277 test_nc_U() {
278 [ -n "$1" ] || return 1
279 _cmdnc="$(command -v "$1" 2>/dev/null || :)"
280 [ -n "$_cmdnc" ] && [ -x "$_cmdnc" ] || return 1
281 _tmpdir="$(mktemp -d /tmp/nc-u-XXXXXX)"
282 [ -n "$_tmpdir" ] && [ -d "$_tmpdir" ] || return 1
283 >"$_tmpdir/output"
284 (sleep 3 | "$_cmdnc" -l -U "$_tmpdir/socket" 2>/dev/null >"$_tmpdir/output" || >"$_tmpdir/failed")&
285 _bgpid="$!"
286 sleep 1
287 echo "testing" | "$_cmdnc" -w 1 -U "$_tmpdir/socket" >/dev/null 2>&1 || >"$_tmpdir/failed"
288 sleep 1
289 kill "$_bgpid" >/dev/null 2>&1 || :
290 read -r _result <"$_tmpdir/output" || :
291 _bad=
292 ! [ -e "$_tmpdir/failed" ] || _bad=1
293 rm -rf "$_tmpdir"
294 [ -z "$_bad" ] && [ "$_result" = "testing" ]
295 } >/dev/null 2>&1
297 echo "*** Verifying \$Girocco::Config::nc_openbsd_bin supports -U option..."
298 test_nc_U "$var_nc_openbsd_bin" || {
299 echo "ERROR: invalid Girocco::Config::nc_openbsd_bin setting" >&2
300 echo "ERROR: \"$var_nc_openbsd_bin\" does not grok the -U option" >&2
301 if [ "$(uname -s 2>/dev/null)" = "DragonFly" ]; then
302 echo "ERROR: see the src/dragonfly/README file for a solution" >&2
304 exit 1
307 chown_make() {
308 if [ "$LOGNAME" = root -a -n "$SUDO_USER" -a "$SUDO_USER" != root ]; then
309 find "$@" -user root -print0 2>/dev/null | \
310 xargs -0 chown "$SUDO_USER:$(id -gn "$SUDO_USER")"
311 elif [ "$LOGNAME" = root -a -z "$SUDO_USER" -o "$SUDO_USER" = root ]; then
312 echo "*** WARNING: running make as root w/o sudo may leave root-owned: $*"
316 # Make sure $cfg_cgiroot, $cfg_webroot and $cfg_cgiroot are absolute paths
317 case "$cfg_basedir" in /*) :;; *)
318 echo "ERROR: invalid Girocco::Config::basedir setting" >&2
319 echo "ERROR: \"$cfg_basedir\" must be an absolute path (start with '/')" >&2
320 exit 1
321 esac
322 case "$cfg_webroot" in /*) :;; *)
323 echo "ERROR: invalid Girocco::Config::webroot setting" >&2
324 echo "ERROR: \"$cfg_webroot\" must be an absolute path (start with '/')" >&2
325 exit 1
326 esac
327 case "$cfg_cgiroot" in /*) :;; *)
328 echo "ERROR: invalid Girocco::Config::cgiroot setting" >&2
329 echo "ERROR: \"$cfg_cgiroot\" must be an absolute path (start with '/')" >&2
330 exit 1
331 esac
333 # return the input with trailing slashes stripped but return "/" for all "/"s
334 striptrsl() {
335 [ -n "$1" ] || return 0
336 _s="${1##*[!/]}"
337 [ "$_s" != "$1" ] || _s="${_s#?}"
338 printf "%s\n" "${1%$_s}"
341 # a combination of realpath + dirname where the realpath of the deepest existing
342 # directory is returned with the rest of the non-existing components appended
343 # and trailing slashes and multiple slashes are removed
344 realdir() {
345 _d="$(striptrsl "$1")"
346 if [ "$_d" = "/" ] || [ -z "$_d" ]; then
347 echo "$_d"
348 return 0
350 _c=""
351 while ! [ -d "$_d" ]; do
352 _c="/$(basename "$_d")$_c"
353 _d="$(dirname "$_d")"
354 [ "$_d" != "/" ] || _c="${_c#/}"
355 done
356 printf "%s%s\n" "$(cd "$_d" && pwd -P)" "$_c"
359 # Use basedir, webroot and cgiroot for easier control of filesystem locations
360 # Wherever we are writing/copying/installing files we use these, but where we
361 # are editing, adding config settings or printing advice we always stick to the
362 # cfg_xxx Config variable versions. These are like a set of DESTDIR variables.
363 # Only the file system directories that could be asynchronously accessed (by
364 # the web server, jobd.pl, taskd.pl or incoming pushes) get these special vars.
365 # The chroot is handled specially and does not need one of these.
366 # We must be careful to allow cgiroot and/or webroot to be under basedir in which
367 # case the prior contents of cgiroot and/or webroot are discarded.
368 rbasedir="$(realdir "$cfg_basedir")"
369 rwebroot="$(realdir "$cfg_webroot")"
370 rcgiroot="$(realdir "$cfg_cgiroot")"
371 case "$rbasedir" in "$rwebroot"/?*)
372 echo "ERROR: invalid Girocco::Config::basedir setting; must not be under webroot" >&2
373 exit 1
374 esac
375 case "$rbasedir" in "$rcgiroot"/?*)
376 echo "ERROR: invalid Girocco::Config::basedir setting; must not be under cgiroot" >&2
377 exit 1
378 esac
379 if [ "$rwebroot" = "$rcgiroot" ]; then
380 echo "ERROR: invalid Girocco::Config::webroot and Girocco::Config::cgiroot settings; must not be the same" >&2
381 exit 1
383 case "$rcgiroot" in "$rwebroot"/?*)
384 echo "ERROR: invalid Girocco::Config::cgiroot setting; must not be under webroot" >&2
385 exit 1
386 esac
387 case "$rwebroot" in "$rcgiroot"/?*)
388 echo "ERROR: invalid Girocco::Config::webroot setting; must not be under cgiroot" >&2
389 exit 1
390 esac
391 basedir="$rbasedir-new"
392 case "$rwebroot" in
393 "$rbasedir"/?*)
394 webroot="$basedir${rwebroot#$rbasedir}"
395 webrootsub=1
398 webroot="$rwebroot-new"
399 webrootsub=
401 esac
402 case "$rcgiroot" in
403 "$rbasedir"/?*)
404 cgiroot="$basedir${rcgiroot#$rbasedir}"
405 cgirootsub=1
408 cgiroot="$rcgiroot-new"
409 cgirootsub=
411 esac
413 echo "*** Setting up basedir..."
414 "$MAKE" --no-print-directory --silent apache.conf
415 chown_make apache.conf
416 "$MAKE" --no-print-directory --silent -C src
417 chown_make src
418 rm -fr "$basedir"
419 mkdir -p "$basedir" "$basedir/gitweb" "$basedir/cgi"
420 cp cgi/*.cgi "$basedir/cgi"
421 cp -pR Girocco jobd taskd html jobs toolbox hooks apache.conf shlib.sh bin screen "$basedir"
422 cp -p src/can_user_push src/can_user_push_http src/get_user_uuid src/list_packs src/peek_packet \
423 src/rangecgi src/strftime src/throttle ezcert.git/CACreateCert cgi/authrequired.cgi \
424 cgi/snapshot.cgi "$basedir/bin"
425 cp -p gitweb/*.sh gitweb/*.perl "$basedir/gitweb"
426 [ -n "$cfg_httpspushurl" ] || rm -f "$basedir"/html/rootcert.html "$basedir"/html/httpspush.html
427 [ -n "$cfg_mob" ] || rm -f "$basedir"/html/mob.html
429 # Put the correct Config in place
430 [ "$GIROCCO_CONF" = "Girocco::Config" ] || cp "$(echo "$GIROCCO_CONF" | sed 's#::#/#g; s/$/.pm/')" "$basedir/Girocco/Config.pm"
432 ln -s "$cfg_git_bin" "$basedir/bin/git"
433 echo "*** Verifying selected POSIX sh is sane..."
434 shbin="$var_sh_bin"
435 [ -n "$shbin" ] && [ -x "$shbin" ] && [ "$("$shbin" -c 'echo sh $(( 1 + 1 ))' 2>/dev/null)" = "sh 2" ] || {
436 echo 'ERROR: invalid $Girocco::Config::posix_sh_bin setting' >&2
437 exit 1
439 [ "$(check_sh_builtin command)" = "command" ] || {
440 echo 'ERROR: invalid $Girocco::Config::posix_sh_bin setting (does not understand command -v)' >&2
441 exit 1
443 sh_not_builtin=
444 sh_extra_chroot_installs=
445 badsh=
446 for sbi in cd pwd read umask unset unalias; do
447 if [ "$(check_sh_builtin "$sbi")" != "$sbi" ]; then
448 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (missing built-in $sbi)" >&2
449 badsh=1
451 done
452 [ -z "$badsh" ] || exit 1
453 for sbi in '[' echo printf test; do
454 if ! extra="$(check_sh_builtin "$sbi")"; then
455 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (missing command $sbi)" >&2
456 badsh=1
457 continue
459 if [ "$extra" != "$sbi" ]; then
460 case "$extra" in /*) :;; *)
461 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (bad command -v $sbi result: $extra)" >&2
462 badsh=1
463 continue
464 esac
465 withspc=
466 case "$extra" in *" "*) withspc=1; esac
467 [ -z "$withspc" ] && [ -f "$extra" ] && [ -r "$extra" ] && [ -x "$extra" ] || {
468 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (unusable command -v $sbi result: $extra)" >&2
469 badsh=1
470 continue
472 echo "WARNING: slow \$Girocco::Config::posix_sh_bin setting (not built-in $sbi)" >&2
473 sh_not_builtin="$sh_not_builtin $sbi"
474 sh_extra_chroot_installs="$sh_extra_chroot_installs $extra"
476 done
477 [ -z "$badsh" ] || exit 1
478 [ -z "$sh_extra_chroot_installs" ] || {
479 echo "WARNING: the selected POSIX sh implements these as non-built-in:$sh_not_builtin" >&2
480 echo "WARNING: as a result it will run slower than necessary" >&2
481 echo "WARNING: consider building and switching to dash which can be found at:" >&2
482 echo "WARNING: http://gondor.apana.org.au/~herbert/dash/" >&2
483 echo "WARNING: (download a tarball from the files section or clone the Git repository" >&2
484 echo "WARNING: and checkout the latest tag, run autogen.sh, configure and build)" >&2
485 echo "WARNING: dash is licensed under the 3-clause BSD license" >&2
487 ln -s "$shbin" "$basedir/bin/sh"
488 echo "*** Verifying selected perl is sane..."
489 perlbin="$var_perl_bin"
490 [ -n "$perlbin" ] && [ -x "$perlbin" ] && [ "$("$perlbin" -wle 'print STDOUT "perl ", + ( 1 + 1 )' 2>/dev/null)" = "perl 2" ] || {
491 echo 'ERROR: invalid $Girocco::Config::perl_bin setting' >&2
492 exit 1
494 ln -s "$perlbin" "$basedir/bin/perl"
495 echo "*** Verifying selected gzip is sane..."
496 gzipbin="$var_gzip_bin"
497 [ -n "$gzipbin" ] && [ -x "$gzipbin" ] && "$gzipbin" -V 2>&1 | grep -q gzip && \
498 [ "$(echo Girocco | "$gzipbin" -c -n -9 | "$gzipbin" -c -d)" = "Girocco" ] || {
499 echo 'ERROR: invalid $Girocco::Config::gzip_bin setting' >&2
500 exit 1
502 ln -s "$gzipbin" "$basedir/bin/gzip"
504 echo "*** Preprocessing scripts..."
505 SHBIN="$shbin" && export SHBIN
506 PERLBIN="$perlbin" && export PERLBIN
507 perl -I. -M$GIROCCO_CONF -i -p \
508 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
509 -e 's/^#!.*sh/#!$ENV{SHBIN}/ if $. == 1;' \
510 -e 's/(?<!")\@basedir\@/"$Girocco::Config::basedir"/g;' \
511 -e 's/(?<=")\@basedir\@/$Girocco::Config::basedir/g;' \
512 -e 's/\@reporoot\@/"$Girocco::Config::reporoot"/g;' \
513 -e 's/\@shbin\@/"$ENV{SHBIN}"/g;' \
514 -e 's/\@perlbin\@/"$ENV{PERLBIN}"/g;' \
515 -e 's/\@jailreporoot\@/"$Girocco::Config::jailreporoot"/g;' \
516 -e 's/\@chroot\@/"$Girocco::Config::chroot"/g;' \
517 -e 's/\@webadmurl\@/"$Girocco::Config::webadmurl"/g;' \
518 -e 's/\@screen_acl_file\@/"$Girocco::Config::screen_acl_file"/g;' \
519 -e 's/\@mob\@/"$Girocco::Config::mob"/g;' \
520 -e 's/\@git_server_ua\@/"$Girocco::Config::git_server_ua"/g;' \
521 -e 's/\@defined_git_server_ua\@/defined($Girocco::Config::git_server_ua)/ge;' \
522 -e 's/\@git_no_mmap\@/"$Girocco::Config::git_no_mmap"/g;' \
523 -e 's/\@var_xargs_r\@/"'"$var_xargs_r"'"/g;' \
524 -e 's/\@big_file_threshold\@/"'"$var_big_file_threshold"'"/g;' \
525 -e 's/\@upload_pack_window\@/"'"$var_upload_window"'"/g;' \
526 -e 'close ARGV if eof;' \
527 "$basedir"/jobs/*.sh "$basedir"/jobd/*.sh \
528 "$basedir"/taskd/*.sh "$basedir"/gitweb/*.sh \
529 "$basedir"/shlib.sh "$basedir"/hooks/* \
530 "$basedir"/toolbox/*.sh "$basedir"/toolbox/*.pl \
531 "$basedir"/toolbox/reports/*.sh \
532 "$basedir"/bin/git-* "$basedir"/bin/*.sh \
533 "$basedir"/bin/create-* "$basedir"/bin/update-* \
534 "$basedir"/bin/*.cgi "$basedir"/screen/*
535 perl -i -p \
536 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
537 -e 'close ARGV if eof;' \
538 "$basedir"/jobd/jobd.pl "$basedir"/taskd/taskd.pl \
539 "$basedir"/bin/sendmail.pl "$basedir"/bin/CACreateCert
540 perl -i -p \
541 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
542 -e 's/^#!.*sh/#!$ENV{SHBIN}/ if $. == 1;' \
543 -e 'close ARGV if eof;' \
544 "$basedir"/bin/format-readme "$basedir/cgi"/*.cgi
545 unset PERLBIN
546 unset SHBIN
548 # Dump all the cfg_ and defined_ variables to shlib_vars.sh
549 get_girocco_config_var_list > "$basedir"/shlib_vars.sh
551 echo "*** Setting up darcs-fast-export from bzr-fastimport.git..."
552 if [ ! -d bzr-fastimport.git/exporters/darcs/ ]; then
553 echo "ERROR: bzr-fastimport.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
554 exit 1
556 mkdir -p "$basedir"/bin
557 cp bzr-fastimport.git/exporters/darcs/darcs-fast-export "$basedir"/bin
559 echo "*** Setting up hg-fast-export from fast-export.git..."
560 if [ ! -f fast-export.git/hg-fast-export.py -o ! -f fast-export.git/hg2git.py ]; then
561 echo "ERROR: fast-export.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
562 exit 1
564 mkdir -p "$basedir"/bin
565 cp fast-export.git/hg-fast-export.py fast-export.git/hg2git.py "$basedir"/bin
567 echo "*** Setting up markdown from markdown.git..."
568 if [ ! -f markdown.git/Markdown.pl ]; then
569 echo "ERROR: markdown.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
570 exit 1
572 mkdir -p "$basedir"/bin
573 (PERLBIN="$perlbin" && export PERLBIN && \
574 perl -p -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
575 markdown.git/Markdown.pl > "$basedir"/bin/Markdown.pl.$$ && \
576 chmod a+x "$basedir"/bin/Markdown.pl.$$ && \
577 mv -f "$basedir"/bin/Markdown.pl.$$ "$basedir"/bin/Markdown.pl)
578 test $? -eq 0
580 # Some permission sanity on basedir/bin just in case
581 find "$basedir"/bin -type f -print0 | xargs -0 chmod go-w
582 chown -R -h "$cfg_mirror_user""$owngroup" "$basedir"/bin
584 if [ -n "$cfg_mirror" ]; then
585 echo "--- Remember to start $cfg_basedir/taskd/taskd.pl"
587 echo "--- Also remember to either start $cfg_basedir/jobd/jobd.sh, or add this"
588 echo "--- to the crontab of $cfg_mirror_user (adjust frequency on number of repos):"
589 echo "*/30 * * * * /usr/bin/nice -n 18 $cfg_basedir/jobd/jobd.sh -q --all-once"
592 echo "*** Setting up repository root..."
593 mkdir -p "$cfg_reporoot" "$cfg_reporoot/_recyclebin"
594 if [ "$cfg_owning_group" ]; then
595 chgrp "$cfg_owning_group" "$cfg_reporoot" || echo "WARNING: Cannot chgrp $cfg_owning_group $cfg_reporoot"
596 chgrp "$cfg_owning_group" "$cfg_reporoot/_recyclebin" || echo "WARNING: Cannot chgrp $cfg_owning_group $cfg_reporoot/_recyclebin"
598 chmod 02775 "$cfg_reporoot" || echo "WARNING: Cannot chmod $cfg_reporoot properly"
599 chmod 02775 "$cfg_reporoot/_recyclebin" || echo "WARNING: Cannot chmod $cfg_reporoot/_recyclebin properly"
602 if [ -n "$cfg_chrooted" ]; then
603 echo "*** Setting up chroot jail for pushing..."
604 if [ "$(id -u)" -eq 0 ]; then
605 # jailsetup may install things from $cfg_basedir/bin into the
606 # chroot so we do a mini-update of just that portion now
607 mkdir -p "$cfg_basedir"
608 rm -rf "$cfg_basedir/bin-new"
609 cp -pR "$basedir/bin" "$cfg_basedir/bin-new" >/dev/null 2>&1
610 rm -rf "$cfg_basedir/bin-old"
611 quick_move "$cfg_basedir/bin-new" "$cfg_basedir/bin" "$cfg_basedir/bin-old"
612 rm -rf "$cfg_basedir/bin-old"
613 if [ -n "$sh_extra_chroot_installs" ]; then
614 GIROCCO_CHROOT_EXTRA_INSTALLS="$sh_extra_chroot_installs"
615 export GIROCCO_CHROOT_EXTRA_INSTALLS
617 ./jailsetup.sh
618 unset GIROCCO_CHROOT_EXTRA_INSTALLS
619 else
620 echo "WARNING: Skipping jail setup, not root"
625 echo "*** Setting up jail configuration (project database)..."
626 [ "$(id -u)" -eq 0 ] || ./jailsetup.sh dbonly
627 mkdir -p "$cfg_chroot" "$cfg_chroot/etc"
628 touch "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group"
629 chown "$cfg_mirror_user""$owngroup" "$cfg_chroot/etc" ||
630 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_chroot/etc"
631 chown "$cfg_cgi_user""$owngroup" "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
632 echo "WARNING: Cannot chown $cfg_cgi_user$owngroup the etc/passwd and/or etc/group files"
633 chmod g+w "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
634 echo "WARNING: Cannot chmod g+w the etc/passwd and/or etc/group files"
635 chmod 02775 "$cfg_chroot/etc" || echo "WARNING: Cannot chmod 02775 $cfg_chroot/etc"
638 echo "*** Setting up gitweb from git.git..."
639 if [ ! -f git.git/Makefile ]; then
640 echo "ERROR: git.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
641 exit 1
644 # We do not wholesale replace either webroot or cgiroot unless they are under
645 # basedir so if they exist and are not we make a copy to start working on them.
646 # We make a copy using -p which can result in some warnings so we suppress
647 # error output as it's of no consequence in this case.
648 rm -rf "$webroot" "$cgiroot"
649 [ -n "$webrootsub" ] || ! [ -d "$rwebroot" ] || cp -pR "$rwebroot" "$webroot" >/dev/null 2>&1 || :
650 [ -n "$cgirootsub" ] || ! [ -d "$rcgiroot" ] || cp -pR "$rcgiroot" "$cgiroot" >/dev/null 2>&1 || :
651 mkdir -p "$webroot" "$cgiroot"
653 (cd git.git && "$MAKE" --no-print-directory --silent NO_SUBDIR=: bindir="$(dirname "$cfg_git_bin")" \
654 GITWEB_CONFIG="$cfg_basedir/gitweb/gitweb_config.perl" SHELL_PATH="$shbin" gitweb && \
655 chown_make gitweb && \
656 PERLBIN="$perlbin" && export PERLBIN && \
657 perl -p -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
658 -e 's/^(\s*use\s+warnings\s*;.*)$/#$1/;' gitweb/gitweb.cgi > "$cgiroot"/gitweb.cgi.$$ && \
659 chmod a+x "$cgiroot"/gitweb.cgi.$$ && \
660 chown_make "$cgiroot"/gitweb.cgi.$$ && \
661 mv -f "$cgiroot"/gitweb.cgi.$$ "$cgiroot"/gitweb.cgi && \
662 cp gitweb/static/*.png gitweb/static/*.css gitweb/static/*.js "$webroot")
663 test $? -eq 0
666 echo "*** Setting up git-browser from git-browser.git..."
667 if [ ! -f git-browser.git/git-browser.cgi ]; then
668 echo "ERROR: git-browser.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
669 exit 1
671 mkdir -p "$webroot"/git-browser "$cgiroot"
672 (cd git-browser.git && \
673 CFG="$cfg_basedir/gitweb/git-browser.conf" && export CFG && \
674 PERLBIN="$perlbin" && export PERLBIN && perl -p \
675 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
676 -e 's/"git-browser\.conf"/"$ENV{"CFG"}"/' git-browser.cgi > "$cgiroot"/git-browser.cgi.$$ && \
677 chmod a+x "$cgiroot"/git-browser.cgi.$$ && \
678 chown_make "$cgiroot"/git-browser.cgi.$$ && \
679 mv -f "$cgiroot"/git-browser.cgi.$$ "$cgiroot"/git-browser.cgi && \
680 cp -r *.html *.js *.css js.lib "$webroot"/git-browser && \
681 cp -r JSON "$cgiroot")
682 test $? -eq 0
683 rm -f "$webroot"/git-browser/index.html
684 cat >"$basedir/gitweb"/git-browser.conf.$$ <<EOT
685 gitbin: $cfg_git_bin
686 warehouse: $cfg_reporoot
687 doconfig: $cfg_basedir/gitweb/gitbrowser_config.perl
689 chown_make "$basedir/gitweb"/git-browser.conf.$$
690 mv -f "$basedir/gitweb"/git-browser.conf.$$ "$basedir/gitweb"/git-browser.conf
691 cat >"$webroot"/git-browser/GitConfig.js.$$ <<EOT
692 cfg_gitweb_url="$cfg_gitweburl/"
693 cfg_browsercgi_url="$cfg_webadmurl/git-browser.cgi"
695 chown_make "$webroot"/git-browser/GitConfig.js.$$
696 mv -f "$webroot"/git-browser/GitConfig.js.$$ "$webroot"/git-browser/GitConfig.js
699 echo "*** Setting up our part of the website..."
700 mkdir -p "$webroot" "$cgiroot"
701 cp "$basedir"/bin/snapshot.cgi "$basedir/cgi"
702 cp "$basedir"/bin/authrequired.cgi "$basedir/cgi"
703 [ -n "$cfg_httpspushurl" ] || rm -f "$basedir/cgi"/usercert.cgi "$cgiroot"/usercert.cgi
704 cp "$basedir/cgi"/*.cgi "$cgiroot"
705 rm -rf "$basedir/cgi"
706 ln -fs "$cfg_basedir"/Girocco "$cgiroot"
707 [ -z "$cfg_webreporoot" ] || { rm -f "$cfg_webreporoot" && ln -s "$cfg_reporoot" "$cfg_webreporoot"; }
708 if [ -z "$cfg_httpspushurl" ]; then
709 grep -v 'rootcert[.]html' gitweb/indextext.html > "$basedir/gitweb/indextext.html"
710 else
711 cp gitweb/indextext.html "$basedir/gitweb"
713 mv "$basedir"/html/*.css "$basedir"/html/*.js "$webroot"
714 cp mootools.js "$webroot"
715 cp htaccess "$webroot/.htaccess"
716 cp cgi/htaccess "$cgiroot/.htaccess"
717 cp git-favicon.ico "$webroot/favicon.ico"
718 cp robots.txt "$webroot"
719 cat gitweb/gitweb.css >>"$webroot"/gitweb.css
722 if [ -n "$cfg_httpspushurl" ]; then
723 echo "*** Setting up SSL certificates..."
724 bits=2048
725 if [ "$cfg_rsakeylength" -gt "$bits" ] 2>/dev/null; then
726 bits="$cfg_rsakeylength"
728 mkdir -p "$cfg_certsdir"
729 [ -d "$cfg_certsdir" ]
730 wwwcertcn=
731 if [ -e "$cfg_certsdir/girocco_www_crt.pem" ]; then
732 wwwcertcn="$( \
733 openssl x509 -in "$cfg_certsdir/girocco_www_crt.pem" -noout -subject | \
734 sed -e 's,[^/]*,,' \
737 wwwcertdns=
738 if [ -n "$cfg_wwwcertaltnames" ]; then
739 for dnsopt in $cfg_wwwcertaltnames; do
740 wwwcertdns="${wwwcertdns:+$wwwcertdns }--dns $dnsopt"
741 done
743 wwwcertdnsfile=
744 if [ -r "$cfg_certsdir/girocco_www_crt.dns" ]; then
745 wwwcertdnsfile="$(cat "$cfg_certsdir/girocco_www_crt.dns")"
747 needroot=
748 [ -e "$cfg_certsdir/girocco_client_crt.pem" -a \
749 -e "$cfg_certsdir/girocco_client_key.pem" -a \
750 -e "$cfg_certsdir/girocco_www_key.pem" -a \
751 -e "$cfg_certsdir/girocco_www_crt.pem" -a "$wwwcertcn" = "/CN=$cfg_httpsdnsname" -a \
752 -e "$cfg_certsdir/girocco_root_crt.pem" ] || needroot=1
753 if [ -n "$needroot" -a ! -e "$cfg_certsdir/girocco_root_key.pem" ]; then
754 rm -f "$cfg_certsdir/girocco_root_crt.pem" "$cfg_certsdir/girocco_root_key.pem"
755 umask 0077
756 openssl genrsa -f4 -out "$cfg_certsdir/girocco_root_key.pem" $bits
757 chmod 0600 "$cfg_certsdir/girocco_root_key.pem"
758 rm -f "$cfg_certsdir/girocco_root_crt.pem"
759 umask 0022
760 echo "Created new root key"
762 if [ ! -e "$cfg_certsdir/girocco_root_crt.pem" ]; then
763 "$basedir/bin/CACreateCert" --root --key "$cfg_certsdir/girocco_root_key.pem" \
764 --out "$cfg_certsdir/girocco_root_crt.pem" "girocco $cfg_nickname root certificate"
765 rm -f "$cfg_certsdir/girocco_www_crt.pem" "$cfg_certsdir/girocco_www_chain.pem"
766 rm -f "$cfg_certsdir/girocco_client_crt.pem" "$cfg_certsdir/girocco_client_suffix.pem"
767 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
768 rm -f "$cfg_chroot/etc/sshcerts"/*.pem
769 echo "Created new root certificate"
771 if [ ! -e "$cfg_certsdir/girocco_www_key.pem" ]; then
772 umask 0077
773 openssl genrsa -f4 -out "$cfg_certsdir/girocco_www_key.pem" $bits
774 chmod 0600 "$cfg_certsdir/girocco_www_key.pem"
775 rm -f "$cfg_certsdir/girocco_www_crt.pem"
776 umask 0022
777 echo "Created new www key"
779 if [ ! -e "$cfg_certsdir/girocco_www_crt.pem" ] || \
780 [ "$wwwcertcn" != "/CN=$cfg_httpsdnsname" ] || [ "$wwwcertdns" != "$wwwcertdnsfile" ]; then
781 openssl rsa -in "$cfg_certsdir/girocco_www_key.pem" -pubout |
782 "$basedir/bin/CACreateCert" --server --key "$cfg_certsdir/girocco_root_key.pem" \
783 --cert "$cfg_certsdir/girocco_root_crt.pem" $wwwcertdns \
784 --out "$cfg_certsdir/girocco_www_crt.pem" "$cfg_httpsdnsname"
785 printf '%s\n' "$wwwcertdns" > "$cfg_certsdir/girocco_www_crt.dns"
786 echo "Created www certificate"
788 if [ ! -e "$cfg_certsdir/girocco_www_chain.pem" ]; then
789 cat "$cfg_certsdir/girocco_root_crt.pem" > "$cfg_certsdir/girocco_www_chain.pem"
790 echo "Created www certificate chain file"
792 if [ ! -e "$cfg_certsdir/girocco_client_key.pem" ]; then
793 umask 0037
794 openssl genrsa -f4 -out "$cfg_certsdir/girocco_client_key.pem" $bits
795 chmod 0640 "$cfg_certsdir/girocco_client_key.pem"
796 rm -f "$cfg_certsdir/girocco_client_crt.pem"
797 umask 0022
798 echo "Created new client key"
800 if [ ! -e "$cfg_certsdir/girocco_client_crt.pem" ]; then
801 openssl rsa -in "$cfg_certsdir/girocco_client_key.pem" -pubout |
802 "$basedir/bin/CACreateCert" --subca --key "$cfg_certsdir/girocco_root_key.pem" \
803 --cert "$cfg_certsdir/girocco_root_crt.pem" \
804 --out "$cfg_certsdir/girocco_client_crt.pem" "girocco $cfg_nickname client authority"
805 rm -f "$cfg_certsdir/girocco_client_suffix.pem"
806 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
807 rm -f "$cfg_chroot/etc/sshcerts"/*.pem
808 echo "Created client certificate"
810 if [ ! -e "$cfg_certsdir/girocco_client_suffix.pem" ]; then
811 cat "$cfg_certsdir/girocco_client_crt.pem" > "$cfg_certsdir/girocco_client_suffix.pem"
812 echo "Created client certificate suffix file"
814 cat "$cfg_rootcert" > "$webroot/${cfg_nickname}_root_cert.pem"
815 if [ -n "$cfg_mob" ]; then
816 if [ ! -e "$cfg_certsdir/girocco_mob_user_key.pem" ]; then
817 openssl genrsa -f4 -out "$cfg_certsdir/girocco_mob_user_key.pem" $bits
818 chmod 0644 "$cfg_certsdir/girocco_mob_user_key.pem"
819 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
820 echo "Created new mob user key"
822 if [ ! -e "$cfg_certsdir/girocco_mob_user_crt.pem" ]; then
823 openssl rsa -in "$cfg_mobuserkey" -pubout |
824 "$basedir/bin/CACreateCert" --client --key "$cfg_clientkey" \
825 --cert "$cfg_clientcert" \
826 --out "$cfg_certsdir/girocco_mob_user_crt.pem" 'mob'
827 echo "Created mob user client certificate"
829 cat "$cfg_mobuserkey" > "$webroot/${cfg_nickname}_mob_key.pem"
830 cat "$cfg_mobusercert" "$cfg_clientcertsuffix" > "$webroot/${cfg_nickname}_mob_user.pem"
831 else
832 rm -f "$webroot/${cfg_nickname}_mob_key.pem" "$webroot/${cfg_nickname}_mob_user.pem"
834 else
835 rm -f "$webroot/${cfg_nickname}_root_cert.pem"
836 rm -f "$webroot/${cfg_nickname}_mob_key.pem" "$webroot/${cfg_nickname}_mob_user.pem"
840 echo "*** Finalizing permissions and moving into place..."
841 chown -R -h "$cfg_mirror_user""$owngroup" "$basedir" "$webroot" "$cgiroot"
842 [ -z "$cfg_httpspushurl" ] || chown -R -h "$cfg_mirror_user""$owngroup" "$cfg_certsdir"
844 # This should always be the very last thing install.sh does
845 rm -rf "$rbasedir-old" "$rwebroot-old" "$rcgiroot-old"
846 quick_move "$basedir" "$rbasedir" "$rbasedir-old"
847 [ -n "$webrootsub" ] || quick_move "$webroot" "$rwebroot" "$rwebroot-old"
848 [ -n "$cgirootsub" ] || quick_move "$cgiroot" "$rcgiroot" "$rcgiroot-old"
849 rm -rf "$rbasedir-old" "$rwebroot-old" "$rcgiroot-old"
850 ! [ -S "$cfg_chroot/etc/taskd.socket" ] || {
851 echo "*** Requesting graceful restart of running taskd (and, if running, jobd)..."
852 touch "$cfg_chroot/etc/taskd.restart"
853 echo "nop" | nc_openbsd -w 5 -U "$cfg_chroot/etc/taskd.socket" || :