install.sh: cache root check
[girocco.git] / install.sh
blobbd7ccde3a3ef317d22102a93ee79567a7a9d522d
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 ! [ -f toolbox/check-perl-modules.pl ] || ! [ -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"$PWD" -M$GIROCCO_CONF -e ''
27 . ./shlib.sh
28 umask 0022
29 "$var_perl_bin" toolbox/check-perl-modules.pl
31 # Config.pm already checked $cfg_reporoot to require an absolute path, but
32 # we also require it does not contain a : or ; that would cause problems when
33 # used in GIT_ALTERNATE_OBJECT_DIRECTORIES
34 probch=':;'
35 case "$cfg_reporoot" in *[$probch]*)
36 echo "fatal: \$Girocco::Config::reporoot may not contain ':' or ';' characters" >&2
37 exit 1
38 esac
40 warn() { printf >&2 '%s\n' "$*"; }
41 die() { warn "$@"; exit 1; }
43 # Either we must run as root (but preferably not if disable_jailsetup is true)
44 # or the mirror_user (preferred choice for disable_jailsetup).
45 isroot=
46 [ "$(id -u)" -ne 0 ] || isroot=1
47 if [ -n "$isroot" ]; then
48 if [ "${cfg_disable_jailsetup:-0}" != "0" ]; then
49 cat <<'EOT'
51 ***
52 *** WARNING: $Girocco::Config::disable_jailsetup has been enabled
53 *** WARNING: but installation is being performed as the superuser
54 ***
56 You appear to have disabled jailsetup which is perfectly fine for installations
57 that will not be using an ssh jail. However, in that case, running the install
58 process as the superuser is highly discouraged.
60 Instead, running it as the configured $Girocco::Config::mirror_user is much
61 preferred.
63 The install process will now pause for 10 seconds to give you a chance to abort
64 it before continuing to install a disable_jailsetup config as the superuser.
66 EOT
67 sleep 10 || die "install aborted"
69 else
70 [ -n "$cfg_mirror_user" ] || die 'Girocco::Config.pm $mirror_user must be set'
71 curuname="$(id -un)"
72 [ -n "$curuname" ] || die "Cannot determine name of current user"
73 if [ "$cfg_mirror_user" != "$curuname" ]; then
74 warn "ERROR: install must run as superuser or Config.pm's \$mirror_user ($cfg_mirror_user)"
75 die "ERROR: install is currently running as $curuname"
79 # $1 must exist and be a dir
80 # $2 may exist but must be a dir
81 # $3 must not exist
82 # After call $2 will be renamed to $3 (if $2 existed)
83 # And $1 will be renamed to $2
84 quick_move() {
85 [ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] || { echo "fatal: quick_move: bad args: '$1' '$2' '$3'" >&2; exit 1; }
86 ! [ -e "$3" ] || { echo "fatal: quick_move: already exists: $3" >&2; exit 1; }
87 [ -d "$1" ] || { echo "fatal: quick_move: no such dir: $1" >&2; exit 1; }
88 ! [ -e "$2" ] || [ -d "$2" ] || { echo "fatal: quick_move: not a dir: $2" >&2; exit 1; }
89 perl -e 'rename($ARGV[1], $ARGV[2]) or die "rename failed: $!\n" if -d $ARGV[1];
90 rename($ARGV[0], $ARGV[1]) or die "rename failed: $!\n"; exit 0;' "$1" "$2" "$3" || {
91 echo "fatal: quick_move: rename failed" >&2
92 exit 1
94 ! [ -d "$1" ] && [ -d "$2" ] || {
95 echo "fatal: quick_move: rename failed" >&2
96 exit 1
100 check_sh_builtin() (
101 "unset" -f command
102 "command" "$var_sh_bin" -c '{ "unset" -f unalias command "$1" || :; "unalias" "$1" || :; } >/dev/null 2>&1; "command" -v "$1"' "$var_sh_bin" "$1"
103 ) 2>/dev/null
105 owngroup=
106 [ -z "$cfg_owning_group" ] || owngroup=":$cfg_owning_group"
107 if [ -n "$cfg_httpspushurl" ] && [ -z "$cfg_certsdir" ]; then
108 echo "ERROR: \$httpspushurl is set but \$certsdir is not!" >&2
109 echo "ERROR: perhaps you have an incorrect Config.pm?" >&2
110 exit 1
114 # Check for extra required tools
115 if [ "${cfg_xmllint_readme:-0}" != "0" ] && ! command -v xmllint >/dev/null; then
116 echo "ERROR: \$xmllint_readme set but xmllint not in \$PATH!" >&2
117 exit 1
121 echo "*** Checking for compiled utilities..."
122 if ! [ -f src/can_user_push ] || ! [ -x src/can_user_push ]; then
123 echo "ERROR: src/can_user_push is not built! Did you _REALLY_ read INSTALL?" >&2
124 echo "ERROR: perhaps you forgot to run make?" >&2
125 exit 1
127 if ! [ -f src/can_user_push_http ] || ! [ -x src/can_user_push_http ]; then
128 echo "ERROR: src/can_user_push_http is not built! Did you _REALLY_ read INSTALL?" >&2
129 echo "ERROR: perhaps you forgot to run make?" >&2
130 exit 1
132 if ! [ -f src/getent ] || ! [ -x src/getent ]; then
133 echo "ERROR: src/getent is not built! Did you _REALLY_ read INSTALL?" >&2
134 echo "ERROR: perhaps you forgot to run make?" >&2
135 exit 1
137 if ! [ -f src/get_user_uuid ] || ! [ -x src/get_user_uuid ]; then
138 echo "ERROR: src/get_user_uuid is not built! Did you _REALLY_ read INSTALL?" >&2
139 echo "ERROR: perhaps you forgot to run make?" >&2
140 exit 1
142 if ! [ -f src/list_packs ] || ! [ -x src/list_packs ]; then
143 echo "ERROR: src/list_packs is not built! Did you _REALLY_ read INSTALL?" >&2
144 echo "ERROR: perhaps you forgot to run make?" >&2
145 exit 1
147 if ! [ -f src/peek_packet ] || ! [ -x src/peek_packet ]; then
148 echo "ERROR: src/peek_packet is not built! Did you _REALLY_ read INSTALL?" >&2
149 echo "ERROR: perhaps you forgot to run make?" >&2
150 exit 1
152 if ! [ -f src/rangecgi ] || ! [ -x src/rangecgi ]; then
153 echo "ERROR: src/rangecgi is not built! Did you _REALLY_ read INSTALL?" >&2
154 echo "ERROR: perhaps you forgot to run make?" >&2
155 exit 1
157 if ! [ -f src/readlink ] || ! [ -x src/readlink ]; then
158 echo "ERROR: src/readlink is not built! Did you _REALLY_ read INSTALL?" >&2
159 echo "ERROR: perhaps you forgot to run make?" >&2
160 exit 1
162 if ! [ -f src/strftime ] || ! [ -x src/strftime ]; then
163 echo "ERROR: src/strftime is not built! Did you _REALLY_ read INSTALL?" >&2
164 echo "ERROR: perhaps you forgot to run make?" >&2
165 exit 1
167 if ! [ -f src/throttle ] || ! [ -x src/throttle ]; then
168 echo "ERROR: src/throttle is not built! Did you _REALLY_ read INSTALL?" >&2
169 echo "ERROR: perhaps you forgot to run make?" >&2
170 exit 1
172 if ! [ -f src/ulimit512 ] || ! [ -x src/ulimit512 ]; then
173 echo "ERROR: src/ulimit512 is not built! Did you _REALLY_ read INSTALL?" >&2
174 echo "ERROR: perhaps you forgot to run make?" >&2
175 exit 1
177 ebin="/bin/echo"
178 if [ ! -x "$ebin" ] && [ -x "/usr/bin/echo" ]; then
179 ebin="/usr/bin/echo"
181 if [ ! -x "$ebin" ]; then
182 echo "ERROR: neither /bin/echo nor /usr/bin/echo found" >&2
183 echo "ERROR: at least one must be present for testing during install" >&2
184 exit 1
186 ec=999
187 tmpfile="$(mktemp "/tmp/ul512-$$-XXXXXX")"
188 { src/ulimit512 -f 0 "$ebin" test >"$tmpfile" || ec=$?; } >/dev/null 2>&1
189 rm -f "$tmpfile"
190 if [ "$ec" = "999" ] || [ "$ec" = "0" ]; then
191 echo "ERROR: src/ulimit512 is built, but broken!" >&2
192 echo "ERROR: exceeding file size limit did not fail!" >&2
193 exit 1
195 if ! [ -f src/ltsha256 ] || ! [ -x src/ltsha256 ]; then
196 echo "ERROR: src/ltsha256 is not built! Did you _REALLY_ read INSTALL?" >&2
197 echo "ERROR: perhaps you forgot to run make?" >&2
198 exit 1
200 sha256check="15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225"
201 sha256result="$(printf '%s' '123456789' | src/ltsha256)"
202 if [ "$sha256check" != "$sha256result" ]; then
203 echo "ERROR: src/ltsha256 is built, but broken!" >&2
204 echo "ERROR: verifying sha256 hash of '123456789' failed!" >&2
205 exit 1
209 echo "*** Checking for ezcert..."
210 if ! [ -f ezcert.git/CACreateCert ] || ! [ -x ezcert.git/CACreateCert ]; then
211 echo "ERROR: ezcert.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
212 exit 1
216 echo "*** Checking for git..."
217 case "$cfg_git_bin" in /*) :;; *)
218 echo 'ERROR: $Girocco::Config::git_bin must be set to an absolute path' >&2
219 exit 1
220 esac
221 if ! [ -f "$cfg_git_bin" ] || ! [ -x "$cfg_git_bin" ]; then
222 echo "ERROR: $cfg_git_bin does not exist or is not executable" >&2
223 exit 1
225 if ! git_version="$("$cfg_git_bin" version)" || [ -z "$git_version" ]; then
226 echo "ERROR: $cfg_git_bin version failed" >&2
227 exit 1
229 case "$git_version" in
230 [Gg]"it version "*) :;;
232 echo "ERROR: '$cfg_git_bin version' output does not start with 'git version '" >&2
233 exit 1
234 esac
235 echo "Found $cfg_git_bin $git_version"
236 git_vernum="$(echo "$git_version" | sed -ne 's/^[^0-9]*\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$/\1/p')"
237 echo "*** Checking Git $git_vernum for compatibility..."
238 if [ "$(vcmp "$git_vernum" 1.6.6)" -lt 0 ]; then
239 echo 'ERROR: $Girocco::Config::git_bin must be at least Git version 1.6.6'
240 exit 1
242 if [ "$(vcmp "$git_vernum" 1.6.6.3)" -lt 0 ]; then
243 echo 'WARNING: $Girocco::Config::git_bin version < 1.6.6.3, clients will not see useful error messages'
245 if [ "$(vcmp "$git_vernum" 1.7.3)" -lt 0 ]; then
246 cat <<'EOT'
249 *** SEVERE WARNING: $Girocco::Config::git_bin is set to a version of Git before 1.7.3
252 Some Girocco functionality will be gracefully disabled and other things will
253 just not work at all such as race condition protection against simultaneous
254 client pushes and server garbage collections.
258 if [ -n "$cfg_mirror" ] && [ "$(vcmp "$git_vernum" 1.7.5)" -lt 0 ]; then
259 echo 'WARNING: $Girocco::Config::git_bin version < 1.7.5 and mirroring enabled, some sources can cause an infinite fetch loop'
261 if [ "$(vcmp "$git_vernum" 1.7.6.6)" -lt 0 ]; then
262 echo 'WARNING: $Girocco::Config::git_bin version < 1.7.6.6, performance may be degraded'
264 if [ "$(uname -m 2>/dev/null)" = "x86_64" ] && [ "$(vcmp "$git_vernum" 1.7.11)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.12.0)" -lt 0 ]; then
265 echo 'WARNING: $Girocco::Config::git_bin version >= 1.7.11 and < 2.12.0 and x86_64, make sure Git built WITHOUT XDL_FAST_HASH'
266 echo 'WARNING: See https://lore.kernel.org/git/20141222041944.GA441@peff.net/ for details'
268 if [ "$(vcmp "$git_vernum" 1.8.4.2)" -ge 0 ] && [ -n "$cfg_mirror" ] && [ "$(vcmp "$git_vernum" 2)" -lt 0 ]; then
269 echo 'WARNING: $Girocco::Config::git_bin version >= 1.8.4.2 and < 2.0.0, git-daemon needs write access for shallow clones'
270 echo 'WARNING: $Girocco::Config::git_bin version >= 1.8.4.2 and < 2.0.0, shallow clones will leave repository turds'
272 if [ "$(vcmp "$git_vernum" 1.8.4.3)" -lt 0 ]; then
273 echo 'WARNING: $Girocco::Config::git_bin version < 1.8.4.3, clients will not receive symref=HEAD:refs/heads/...'
275 if [ "$(vcmp "$git_vernum" 2.1)" -lt 0 ]; then
276 echo 'WARNING: $Girocco::Config::git_bin version < 2.1.0, pack bitmaps will not be available'
278 if [ "$(vcmp "$git_vernum" 2.1)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.1.3)" -lt 0 ]; then
279 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'
281 if [ "$(vcmp "$git_vernum" 2.2)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.3.2)" -lt 0 ]; then
282 cat <<'EOT'
285 *** ERROR: $Girocco::Config::git_bin is set to an incompatible version of Git
288 Git versions starting with 2.2.0 and continuing up through 2.3.1 are incompatible
289 with Girocco due to various unresolved issues. Please either downgrade to 2.1.4
290 or earlier or, more preferred, upgrade to 2.3.2 (ideally 2.4.11) or later.
292 In order to bypass this check you will have to modify install.sh in which case
293 USE THE SELECTED GIT BINARY AT YOUR OWN RISK!
296 exit 1
298 if [ "$(vcmp "$git_vernum" 2.3.3)" -lt 0 ]; then
299 echo 'WARNING: $Girocco::Config::git_bin version < 2.3.3, performance will be sub-optimal'
301 if [ "$(vcmp "$git_vernum" 2.4.4)" -lt 0 ]; then
302 echo 'WARNING: $Girocco::Config::git_bin version < 2.4.4, many refs smart HTTP fetches can deadlock'
304 if [ "$(vcmp "$git_vernum" 2.10.1)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.12.3)" -lt 0 ]; then
305 echo 'WARNING: $Girocco::Config::git_bin version >= 2.10.1 and < 2.12.3, --pickaxe-regex can segfault'
306 echo 'WARNING: If gitweb pickaxe regular expression searches are enabled, --pickaxe-regex will be used'
307 echo 'WARNING: See the fix at http://repo.or.cz/git.git/f53c5de29cec68e3 for details'
308 echo 'WARNING: The fix is trivial and easily cherry-picked into a custom 2.10.1 - 2.12.2 build'
309 echo 'WARNING: Leaving the gitweb/gitweb_config.perl "regexp" feature off as recommended avoids the issue'
311 secmsg=
312 if [ "$(vcmp "$git_vernum" 2.4.11)" -lt 0 ]; then
313 secmsg='prior to 2.4.11'
315 if [ "$(vcmp "$git_vernum" 2.5)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.5.5)" -lt 0 ]; then
316 secmsg='2.5.x prior to 2.5.5'
318 if [ "$(vcmp "$git_vernum" 2.6)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.6.6)" -lt 0 ]; then
319 secmsg='2.6.x prior to 2.6.6'
321 if [ "$(vcmp "$git_vernum" 2.7)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.7.4)" -lt 0 ]; then
322 secmsg='2.7.x prior to 2.7.4'
324 if [ -n "$secmsg" ]; then
325 cat <<EOT
328 *** SEVERE WARNING: \$Girocco::Config::git_bin is set to a version of Git $secmsg
331 Security issues exist in Git versions prior to 2.4.11, 2.5.x prior to 2.5.5,
332 2.6.x prior to 2.6.6 and 2.7.x prior to 2.7.4.
334 Besides the security fixes included in later versions, versions prior to
335 2.2.0 may accidentally prune unreachable loose objects earlier than
336 intended. Since Git version 2.4.11 is the minimum version to include all
337 security fixes to date, it should be considered the absolute minimum
338 version of Git to use when running Girocco.
340 This is not enforced, but Git is easy to build from the git.git submodule
341 and upgrading to GIT VERSION 2.4.11 OR LATER IS HIGHLY RECOMMENDED.
343 We will now pause for a moment so you can reflect on this warning.
346 sleep 60
348 if [ -n "$cfg_mirror" ] && [ "$cfg_mirror" != 0 ] && grep -q ns_parserr "$cfg_git_bin"; then
349 cat <<'EOT'
352 *** WARNING: $Girocco::Config::git_bin is set to a questionable Git binary
355 You appear to have enabled mirroring and the Git binary you have selected
356 appears to contain an experimental patch that cannot be disabled. This
357 patch can generate invalid network DNS traffic and/or cause long delays
358 when fetching using the "git:" protocol when no port number is specified.
359 It may also end up retrieving repsitory contents from a host other than
360 the one specified in the "git:" URL when the port is omitted.
362 You are advised to either build your own version of Git (the problem patch
363 is not part of the official Git repository) or disable mirroring (via the
364 $Girocco::Config:mirror setting) to avoid these potential problems.
366 USE THE SELECTED GIT BINARY AT YOUR OWN RISK!
369 sleep 5
372 test_nc_U() {
373 [ -n "$1" ] || return 1
374 _cmdnc="$(command -v "$1" 2>/dev/null)" || :
375 [ -n "$_cmdnc" ] && [ -f "$_cmdnc" ] && [ -x "$_cmdnc" ] || return 1
376 _tmpdir="$(mktemp -d /tmp/nc-u-XXXXXX)"
377 [ -n "$_tmpdir" ] && [ -d "$_tmpdir" ] || return 1
378 >"$_tmpdir/output"
379 (sleep 3 | "$_cmdnc" -l -U "$_tmpdir/socket" 2>/dev/null >"$_tmpdir/output" || >"$_tmpdir/failed")&
380 _bgpid="$!"
381 sleep 1
382 echo "testing" | "$_cmdnc" -w 1 -U "$_tmpdir/socket" >/dev/null 2>&1 || >"$_tmpdir/failed"
383 sleep 1
384 kill "$_bgpid" >/dev/null 2>&1 || :
385 read -r _result <"$_tmpdir/output" || :
386 _bad=
387 ! [ -e "$_tmpdir/failed" ] || _bad=1
388 rm -rf "$_tmpdir"
389 [ -z "$_bad" ] && [ "$_result" = "testing" ]
390 } >/dev/null 2>&1
392 echo "*** Verifying \$Girocco::Config::nc_openbsd_bin supports -U option..."
393 test_nc_U "$var_nc_openbsd_bin" || {
394 echo "ERROR: invalid Girocco::Config::nc_openbsd_bin setting" >&2
395 echo "ERROR: \"$var_nc_openbsd_bin\" does not grok the -U option" >&2
396 uname_s="$(uname -s 2>/dev/null | tr A-Z a-z 2>/dev/null)" || :
397 case "$uname_s" in
398 *dragonfly*)
399 echo "ERROR: see the src/dragonfly/README file for a solution" >&2;;
400 *kfreebsd*|*linux*)
401 echo "ERROR: try installing the package named 'netcat-openbsd'" >&2;;
402 esac
403 exit 1
406 echo "*** Verifying selected POSIX sh is sane..."
407 shbin="$var_sh_bin"
408 [ -n "$shbin" ] && [ -f "$shbin" ] && [ -x "$shbin" ] && [ "$("$shbin" -c 'echo sh $(( 1 + 1 ))' 2>/dev/null)" = "sh 2" ] || {
409 echo 'ERROR: invalid $Girocco::Config::posix_sh_bin setting' >&2
410 exit 1
412 [ "$(check_sh_builtin command)" = "command" ] || {
413 echo 'ERROR: invalid $Girocco::Config::posix_sh_bin setting (does not understand command -v)' >&2
414 exit 1
416 sh_not_builtin=
417 sh_extra_chroot_installs=
418 badsh=
419 for sbi in cd pwd read umask unset unalias; do
420 if [ "$(check_sh_builtin "$sbi")" != "$sbi" ]; then
421 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (missing built-in $sbi)" >&2
422 badsh=1
424 done
425 [ -z "$badsh" ] || exit 1
426 for sbi in '[' echo printf test; do
427 if ! extra="$(check_sh_builtin "$sbi")"; then
428 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (missing command $sbi)" >&2
429 badsh=1
430 continue
432 if [ "$extra" != "$sbi" ]; then
433 case "$extra" in /*) :;; *)
434 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (bad command -v $sbi result: $extra)" >&2
435 badsh=1
436 continue
437 esac
438 withspc=
439 case "$extra" in *" "*) withspc=1; esac
440 [ -z "$withspc" ] && [ -f "$extra" ] && [ -r "$extra" ] && [ -x "$extra" ] || {
441 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (unusable command -v $sbi result: $extra)" >&2
442 badsh=1
443 continue
445 echo "WARNING: slow \$Girocco::Config::posix_sh_bin setting (not built-in $sbi)" >&2
446 sh_not_builtin="$sh_not_builtin $sbi"
447 sh_extra_chroot_installs="$sh_extra_chroot_installs $extra"
449 done
450 [ -z "$badsh" ] || exit 1
451 [ -z "$sh_extra_chroot_installs" ] || {
452 echo "WARNING: the selected POSIX sh implements these as non-built-in:$sh_not_builtin" >&2
453 echo "WARNING: as a result it will run slower than necessary" >&2
454 echo "WARNING: consider building and switching to dash which can be found at:" >&2
455 echo "WARNING: http://gondor.apana.org.au/~herbert/dash/" >&2
456 echo "WARNING: (download a tarball from the files section or clone the Git repository" >&2
457 echo "WARNING: and checkout the latest tag, run autogen.sh, configure and build)" >&2
458 echo "WARNING: dash is licensed under the 3-clause BSD license" >&2
461 echo "*** Verifying xargs is sane..."
462 _xargsr="$(</dev/null command xargs printf %s -r)" || :
463 xtest1="$(</dev/null command xargs $_xargsr printf 'test %s ' 2>/dev/null)" || :
464 xtest2="$(printf '%s\n' one two | command xargs $_xargsr printf 'test %s ' 2>/dev/null)" || :
465 [ -z "$xtest1" ] && [ "$xtest2" = "test one test two " ] || {
466 echo 'ERROR: xargs is unusable' >&2
467 echo 'ERROR: either `test -z "$(</dev/null xargs echo test 2>/dev/null)"`' >&2
468 echo 'ERROR: or `test -z "$(</dev/null xargs -r echo test 2>/dev/null)"`' >&2
469 echo 'ERROR: must be true, but neither is' >&2
470 exit 1
473 echo "*** Verifying selected perl is sane..."
474 perlbin="$var_perl_bin"
475 [ -n "$perlbin" ] && [ -f "$perlbin" ] && [ -x "$perlbin" ] && [ "$("$perlbin" -wle 'print STDOUT "perl ", + ( 1 + 1 )' 2>/dev/null)" = "perl 2" ] || {
476 echo 'ERROR: invalid $Girocco::Config::perl_bin setting' >&2
477 exit 1
480 echo "*** Verifying selected gzip is sane..."
481 gzipbin="$var_gzip_bin"
482 [ -n "$gzipbin" ] && [ -f "$gzipbin" ] && [ -x "$gzipbin" ] && "$gzipbin" -V 2>&1 | grep -q gzip &&
483 [ "$(echo Girocco | "$gzipbin" -c -n -9 | "$gzipbin" -c -d)" = "Girocco" ] || {
484 echo 'ERROR: invalid $Girocco::Config::gzip_bin setting' >&2
485 exit 1
488 echo "*** Verifying basedir, webroot, webreporoot and cgiroot paths..."
489 # Make sure $cfg_basedir, $cfg_webroot and $cfg_cgiroot are absolute paths
490 case "$cfg_basedir" in /*) :;; *)
491 echo "ERROR: invalid Girocco::Config::basedir setting" >&2
492 echo "ERROR: \"$cfg_basedir\" must be an absolute path (start with '/')" >&2
493 exit 1
494 esac
495 case "$cfg_webroot" in /*) :;; *)
496 echo "ERROR: invalid Girocco::Config::webroot setting" >&2
497 echo "ERROR: \"$cfg_webroot\" must be an absolute path (start with '/')" >&2
498 exit 1
499 esac
500 if [ -n "$cfg_webreporoot" ]; then
501 case "$cfg_webreporoot" in /*) :;; *)
502 echo "ERROR: invalid Girocco::Config::webreporoot setting" >&2
503 echo "ERROR: \"$cfg_webreporoot\" must be an absolute path (start with '/') or undef" >&2
504 exit 1
505 esac
507 case "$cfg_cgiroot" in /*) :;; *)
508 echo "ERROR: invalid Girocco::Config::cgiroot setting" >&2
509 echo "ERROR: \"$cfg_cgiroot\" must be an absolute path (start with '/')" >&2
510 exit 1
511 esac
513 # return the input with trailing slashes stripped but return "/" for all "/"s
514 striptrsl() {
515 [ -n "$1" ] || return 0
516 _s="${1##*[!/]}"
517 [ "$_s" != "$1" ] || _s="${_s#?}"
518 printf "%s\n" "${1%$_s}"
521 # a combination of realpath + dirname where the realpath of the deepest existing
522 # directory is returned with the rest of the non-existing components appended
523 # and trailing slashes and multiple slashes are removed
524 realdir() {
525 _d="$(striptrsl "$1")"
526 if [ "$_d" = "/" ] || [ -z "$_d" ]; then
527 echo "$_d"
528 return 0
530 _c=""
531 while ! [ -d "$_d" ]; do
532 _c="/$(basename "$_d")$_c"
533 _d="$(dirname "$_d")"
534 [ "$_d" != "/" ] || _c="${_c#/}"
535 done
536 printf "%s%s\n" "$(cd "$_d" && pwd -P)" "$_c"
539 # Use basedir, webroot and cgiroot for easier control of filesystem locations
540 # Wherever we are writing/copying/installing files we use these, but where we
541 # are editing, adding config settings or printing advice we always stick to the
542 # cfg_xxx Config variable versions. These are like a set of DESTDIR variables.
543 # Only the file system directories that could be asynchronously accessed (by
544 # the web server, jobd.pl, taskd.pl or incoming pushes) get these special vars.
545 # The chroot is handled specially and does not need one of these.
546 # We must be careful to allow cgiroot and/or webroot to be under basedir in which
547 # case the prior contents of cgiroot and/or webroot are discarded.
548 rbasedir="$(realdir "$cfg_basedir")"
549 rwebroot="$(realdir "$cfg_webroot")"
550 rwebreporoot=
551 [ -z "$cfg_webreporoot" ] || {
552 # avoid resolving a pre-existing symlink from a previous install
553 rwebreporoot="$(realdir "${cfg_webreporoot%/}_NOSUCHDIR")"
554 rwebreporoot="${rwebreporoot%_NOSUCHDIR}"
556 rcgiroot="$(realdir "$cfg_cgiroot")"
557 case "$rbasedir" in "$rwebroot"/?*)
558 echo "ERROR: invalid Girocco::Config::basedir setting; must not be under webroot" >&2
559 exit 1
560 esac
561 case "$rbasedir" in "$rcgiroot"/?*)
562 echo "ERROR: invalid Girocco::Config::basedir setting; must not be under cgiroot" >&2
563 exit 1
564 esac
565 if [ "$rwebroot" = "$rcgiroot" ]; then
566 echo "ERROR: invalid Girocco::Config::webroot and Girocco::Config::cgiroot settings; must not be the same" >&2
567 exit 1
569 case "$rcgiroot" in "$rwebroot"/?*)
570 echo "ERROR: invalid Girocco::Config::cgiroot setting; must not be under webroot" >&2
571 exit 1
572 esac
573 case "$rwebroot" in "$rcgiroot"/?*)
574 echo "ERROR: invalid Girocco::Config::webroot setting; must not be under cgiroot" >&2
575 exit 1
576 esac
577 if [ -n "$rwebreporoot" ]; then
578 if [ "$rwebreporoot" = "$rwebroot" ]; then
579 echo "ERROR: invalid Girocco::Config::webroot and Girocco::Config::webreporoot settings; must not be the same" >&2
580 exit 1
582 case "$rwebreporoot" in "$rwebroot"/?*);;*)
583 echo "ERROR: invalid Girocco::Config::webreporoot setting; must be under webroot or undef" >&2
584 exit 1
585 esac
587 basedir="$rbasedir-new"
588 case "$rwebroot" in
589 "$rbasedir"/?*)
590 webroot="$basedir${rwebroot#$rbasedir}"
591 webrootsub=1
594 webroot="$rwebroot-new"
595 webrootsub=
597 esac
598 webreporoot=
599 [ -z "$rwebreporoot" ] || webreporoot="$webroot${rwebreporoot#$rwebroot}"
600 case "$rcgiroot" in
601 "$rbasedir"/?*)
602 cgiroot="$basedir${rcgiroot#$rbasedir}"
603 cgirootsub=1
606 cgiroot="$rcgiroot-new"
607 cgirootsub=
609 esac
611 echo "*** Setting up basedir..."
613 chown_make() {
614 if [ "$LOGNAME" = root ] && [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != root ]; then
615 find -H "$@" -user root -exec chown "$SUDO_USER:$(id -gn "$SUDO_USER")" '{}' + 2>/dev/null || :
616 elif [ "$LOGNAME" = root ] && { [ -z "$SUDO_USER" ] || [ "$SUDO_USER" = root ]; }; then
617 echo "*** WARNING: running make as root w/o sudo may leave root-owned: $*"
621 "$MAKE" --no-print-directory --silent apache.conf
622 chown_make apache.conf
623 "$MAKE" --no-print-directory --silent -C src
624 chown_make src
625 rm -fr "$basedir"
626 mkdir -p "$basedir" "$basedir/gitweb" "$basedir/cgi"
627 # make the mtlinesfile with 1000 empty lines
628 yes '' | dd bs=1000 count=1 2>/dev/null >"$basedir/mtlinesfile"
629 chmod a+r "$basedir/mtlinesfile"
630 cp cgi/*.cgi "$basedir/cgi"
631 cp -pR Girocco jobd taskd html jobs toolbox hooks apache.conf shlib.sh bin screen "$basedir"
632 rm -f "$basedir/Girocco/Dumper.pm" # Dumper.pm is only for the install.sh process
633 find -H "$basedir" -type l -exec rm -f '{}' +
634 cp -p src/can_user_push src/can_user_push_http src/get_user_uuid src/list_packs src/peek_packet \
635 src/rangecgi src/readlink src/strftime src/throttle src/ulimit512 src/ltsha256 \
636 ezcert.git/CACreateCert cgi/authrequired.cgi cgi/snapshot.cgi \
637 "$basedir/bin"
638 cp -p gitweb/*.sh gitweb/*.perl "$basedir/gitweb"
639 if [ -n "$cfg_httpspushurl" ]; then
640 [ -z "$cfg_pretrustedroot" ] || rm -f "$basedir"/html/rootcert.html
641 else
642 rm -f "$basedir"/html/rootcert.html "$basedir"/html/httpspush.html
644 [ -n "$cfg_mob" ] || rm -f "$basedir"/html/mob.html
646 # Put the frozen Config in place
647 VARLIST="$(get_girocco_config_var_list varonly)" && export VARLIST
648 perl -I"$PWD" -MGirocco::Dumper=FreezeConfig -MScalar::Util=looks_like_number -e '
649 my $usemod = $ARGV[0];
650 my $f = sub { return () unless $_[0] =~ /^(var_[^=\s]+)=(.*)$/;
651 my ($k,$v) = ($1,$2);
652 $v =~ s/([\@\%])/\\$1/gos;
653 $v = "\"".$v."\"" unless substr($v,0,1) eq "\"" || looks_like_number($v);
654 my $e = eval $v;
655 [$k, $e] };
656 my @vars = map({&$f($_)} split(/\n+/, $ENV{VARLIST}));
657 my $s = sub { my $conf = shift;
658 foreach (@vars) {
659 my ($k,$v) = @{$_};
660 eval "\$${conf}::$k=\$v";
663 print FreezeConfig($usemod, undef, $s);
664 ' -- "$GIROCCO_CONF" >"$basedir/Girocco/Config.pm"
665 unset VARLIST
667 # Create symbolic links to selected binaries
668 ln -s "$cfg_git_bin" "$basedir/bin/git"
669 ln -s "$shbin" "$basedir/bin/sh"
670 ln -s "$perlbin" "$basedir/bin/perl"
671 ln -s "$gzipbin" "$basedir/bin/gzip"
672 [ -z "$var_openssl_bin" ] || ln -s "$var_openssl_bin" "$basedir/bin/openssl"
674 echo "*** Preprocessing scripts..."
675 SHBIN="$shbin" && export SHBIN
676 PERLBIN="$perlbin" && export PERLBIN
677 perl -I"$PWD" -M$GIROCCO_CONF -i -p \
678 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
679 -e 's/^#!.*sh/#!$ENV{SHBIN}/ if $. == 1;' \
680 -e 's/(?<!")\@basedir\@/"$Girocco::Config::basedir"/g;' \
681 -e 's/(?<=")\@basedir\@/$Girocco::Config::basedir/g;' \
682 -e 's/__BASE''DIR__/$Girocco::Config::basedir/g;' \
683 -e 's/\@reporoot\@/"$Girocco::Config::reporoot"/g;' \
684 -e 's/\@shbin\@/"$ENV{SHBIN}"/g;' \
685 -e 's/\@perlbin\@/"$ENV{PERLBIN}"/g;' \
686 -e 's/\@jailreporoot\@/"$Girocco::Config::jailreporoot"/g;' \
687 -e 's/\@chroot\@/"$Girocco::Config::chroot"/g;' \
688 -e 's/\@webadmurl\@/"$Girocco::Config::webadmurl"/g;' \
689 -e 's/\@screen_acl_file\@/"$Girocco::Config::screen_acl_file"/g;' \
690 -e 's/\@mob\@/"$Girocco::Config::mob"/g;' \
691 -e 's/\@autogchack\@/"$Girocco::Config::autogchack"/g;' \
692 -e 's/\@git_server_ua\@/"$Girocco::Config::git_server_ua"/g;' \
693 -e 's/\@defined_git_server_ua\@/defined($Girocco::Config::git_server_ua)/ge;' \
694 -e 's/\@git_no_mmap\@/"$Girocco::Config::git_no_mmap"/g;' \
695 -e 's/\@big_file_threshold\@/"'"$var_big_file_threshold"'"/g;' \
696 -e 's/\@upload_pack_window\@/"'"$var_upload_window"'"/g;' \
697 -e 's/\@fetch_stash_refs\@/"$Girocco::Config::fetch_stash_refs"/g;' \
698 -e 's/\@suppress_git_ssh_logging\@/"$Girocco::Config::suppress_git_ssh_logging"/g;' \
699 -e 's/\@max_file_size512\@/"$Girocco::Config::max_file_size512"/g;' \
700 -e 'close ARGV if eof;' \
701 "$basedir"/jobs/*.sh "$basedir"/jobd/*.sh \
702 "$basedir"/taskd/*.sh "$basedir"/gitweb/*.sh \
703 "$basedir"/shlib.sh "$basedir"/hooks/* \
704 "$basedir"/toolbox/*.sh "$basedir"/toolbox/*.pl \
705 "$basedir"/toolbox/reports/*.sh \
706 "$basedir"/bin/git-* "$basedir"/bin/*.sh \
707 "$basedir"/bin/create-* "$basedir"/bin/update-* \
708 "$basedir"/bin/*.cgi "$basedir"/screen/*
709 perl -I"$PWD" -M$GIROCCO_CONF -i -p \
710 -e 's/__BASE''DIR__/$Girocco::Config::basedir/g;' \
711 "$basedir"/cgi/*.cgi "$basedir"/gitweb/*.perl \
712 "$basedir"/jobd/*.pl "$basedir"/taskd/*.pl
713 perl -i -p \
714 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
715 -e 'close ARGV if eof;' \
716 "$basedir"/jobd/jobd.pl "$basedir"/taskd/taskd.pl \
717 "$basedir"/bin/sendmail.pl "$basedir"/bin/CACreateCert
718 perl -i -p \
719 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
720 -e 's/^#!.*sh/#!$ENV{SHBIN}/ if $. == 1;' \
721 -e 'close ARGV if eof;' \
722 "$basedir"/bin/format-readme "$basedir/cgi"/*.cgi
723 unset PERLBIN
724 unset SHBIN
726 # Dump all the cfg_ and defined_ variables to shlib_vars.sh
727 get_girocco_config_var_list >"$basedir"/shlib_vars.sh
729 if [ "${cfg_mirror_darcs:-0}" != "0" ]; then
730 echo "*** Setting up darcs-fast-export from girocco-darcs-fast-export.git..."
731 if ! [ -f girocco-darcs-fast-export.git/darcs-fast-export ] ||
732 ! [ -x girocco-darcs-fast-export.git/darcs-fast-export ]; then
733 echo "ERROR: girocco-darcs-fast-export.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
734 exit 1
736 mkdir -p "$basedir"/bin
737 cp girocco-darcs-fast-export.git/darcs-fast-export "$basedir"/bin
740 if [ "${cfg_mirror_hg:-0}" != "0" ]; then
741 echo "*** Setting up hg-fast-export from girocco-hg-fast-export.git..."
742 if ! [ -f girocco-hg-fast-export.git/hg-fast-export.py ] || ! [ -f girocco-hg-fast-export.git/hg2git.py ]; then
743 echo "ERROR: girocco-hg-fast-export.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
744 exit 1
746 mkdir -p "$basedir"/bin
747 cp girocco-hg-fast-export.git/hg-fast-export.py girocco-hg-fast-export.git/hg2git.py "$basedir"/bin
750 echo "*** Setting up markdown from markdown.git..."
751 if ! [ -f markdown.git/Markdown.pl ]; then
752 echo "ERROR: markdown.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
753 exit 1
755 mkdir -p "$basedir"/bin
756 (PERLBIN="$perlbin" && export PERLBIN &&
757 perl -p -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
758 markdown.git/Markdown.pl >"$basedir"/bin/Markdown.pl.$$ &&
759 chmod a+x "$basedir"/bin/Markdown.pl.$$ &&
760 mv -f "$basedir"/bin/Markdown.pl.$$ "$basedir"/bin/Markdown.pl)
761 test $? -eq 0
763 # Some permission sanity on basedir/bin just in case
764 find -H "$basedir"/bin -type f -exec chmod go-w '{}' +
765 chown -R -h "$cfg_mirror_user""$owngroup" "$basedir"/bin
767 if [ -n "$cfg_mirror" ]; then
768 echo "--- Remember to start $cfg_basedir/taskd/taskd.pl"
770 echo "--- Also remember to either start $cfg_basedir/jobd/jobd.pl, or add this"
771 echo "--- to the crontab of $cfg_mirror_user (adjust frequency on number of repos):"
772 echo "*/30 * * * * /usr/bin/nice -n 18 $cfg_basedir/jobd/jobd.pl -q --all-once"
775 echo "*** Setting up repository root..."
776 [ -d "$cfg_reporoot" ] || {
777 mkdir -p "$cfg_reporoot"
778 chown "$cfg_mirror_user""$owngroup" "$cfg_reporoot" ||
779 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_reporoot"
781 [ -z "$cfg_owning_group" ] ||
782 chgrp "$cfg_owning_group" "$cfg_reporoot" || echo "WARNING: Cannot chgrp $cfg_owning_group $cfg_reporoot"
783 chmod 02775 "$cfg_reporoot" || echo "WARNING: Cannot chmod $cfg_reporoot properly"
784 mkdir -p "$cfg_reporoot/_recyclebin" "$cfg_reporoot/_global/hooks" "$cfg_reporoot/_global/empty"
785 chown "$cfg_mirror_user""$owngroup" "$cfg_reporoot/_recyclebin" "$cfg_reporoot/_global" "$cfg_reporoot/_global/hooks" "$cfg_reporoot/_global/empty" ||
786 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_reporoot/{_recyclebin,_global} properly"
787 if [ "$cfg_owning_group" ]; then
788 chgrp "$cfg_owning_group" "$cfg_reporoot/_recyclebin" || echo "WARNING: Cannot chgrp $cfg_owning_group $cfg_reporoot/_recyclebin"
789 chgrp -R "$cfg_owning_group" "$cfg_reporoot/_global" || echo "WARNING: Cannot chgrp -R $cfg_owning_group $cfg_reporoot/_global"
791 chmod 02775 "$cfg_reporoot/_recyclebin" || echo "WARNING: Cannot chmod $cfg_reporoot/_recyclebin properly"
792 chmod 00755 "$cfg_reporoot/_global" "$cfg_reporoot/_global/hooks" "$cfg_reporoot/_global/empty" || echo "WARNING: Cannot chmod $cfg_reporoot/_global properly"
795 if [ "${cfg_disable_jailsetup:-0}" = "0" ] && [ -n "$cfg_chrooted" ]; then
796 echo "*** Setting up chroot jail for pushing..."
797 if [ -n "$isroot" ]; then
798 # jailsetup may install things from $cfg_basedir/bin into the
799 # chroot so we do a mini-update of just that portion now
800 mkdir -p "$cfg_basedir"
801 rm -rf "$cfg_basedir/bin-new"
802 cp -pR "$basedir/bin" "$cfg_basedir/bin-new" >/dev/null 2>&1
803 rm -rf "$cfg_basedir/bin-old"
804 quick_move "$cfg_basedir/bin-new" "$cfg_basedir/bin" "$cfg_basedir/bin-old"
805 rm -rf "$cfg_basedir/bin-old"
806 if [ -n "$sh_extra_chroot_installs" ]; then
807 GIROCCO_CHROOT_EXTRA_INSTALLS="$sh_extra_chroot_installs"
808 export GIROCCO_CHROOT_EXTRA_INSTALLS
810 ./jailsetup.sh
811 unset GIROCCO_CHROOT_EXTRA_INSTALLS
812 else
813 echo "WARNING: Skipping jail setup, not root"
818 echo "*** Setting up jail configuration (project database)..."
819 [ -n "$isroot" ] || ./jailsetup.sh dbonly
820 mkdir -p "$cfg_chroot" "$cfg_chroot/etc"
821 touch "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group"
822 chown "$cfg_mirror_user""$owngroup" "$cfg_chroot/etc" ||
823 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_chroot/etc"
824 chown "$cfg_cgi_user""$owngroup" "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
825 echo "WARNING: Cannot chown $cfg_cgi_user$owngroup the etc/passwd and/or etc/group files"
826 chmod g+w "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
827 echo "WARNING: Cannot chmod g+w the etc/passwd and/or etc/group files"
828 chmod 02775 "$cfg_chroot/etc" || echo "WARNING: Cannot chmod 02775 $cfg_chroot/etc"
831 echo "*** Setting up global hook scripts..."
832 # It is absolutely CRUCIAL that hook script replacements are done atomically!
833 # Otherwise an incoming push might slip in and fail to run the hook script!
834 # The underlying rename(2) function call provides this and mv will use it.
835 # First add hook scripts
836 hooks="pre-auto-gc pre-receive post-commit post-receive update"
837 for hook in $hooks; do
838 cat "$basedir/hooks/$hook" >"$cfg_reporoot/_global/hooks/$hook.$$"
839 chown "$cfg_mirror_user""$owngroup" "$cfg_reporoot/_global/hooks/$hook.$$" ||
840 echo "WARNING: Cannot chown $cfg_reporoot/_global/hooks/$hook"
841 chmod 0755 "$cfg_reporoot/_global/hooks/$hook.$$"
842 mv -f "$cfg_reporoot/_global/hooks/$hook.$$" "$cfg_reporoot/_global/hooks/$hook"
843 done
844 # Then remove any hook scripts that do not belong
845 for hook in "$cfg_reporoot/_global/hooks"/*; do
846 hook="${hook##*/}"
847 [ -f "$cfg_reporoot/_global/hooks/$hook" ] || continue
848 case " $hooks " in *" $hook "*);;*)
849 rm -f "$cfg_reporoot/_global/hooks/$hook" ||
850 echo "WARNING: Cannot remove extraneous $cfg_reporoot/_global/hooks/$hook"
851 esac
852 done
855 echo "*** Setting up gitweb from git.git..."
856 if ! [ -f git.git/Makefile ]; then
857 echo "ERROR: git.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
858 exit 1
861 # We do not wholesale replace either webroot or cgiroot unless they are under
862 # basedir so if they exist and are not we make a copy to start working on them.
863 # We make a copy using -p which can result in some warnings so we suppress
864 # error output as it's of no consequence in this case.
865 rm -rf "$webroot" "$cgiroot"
866 [ -n "$webrootsub" ] || ! [ -d "$rwebroot" ] || cp -pR "$rwebroot" "$webroot" >/dev/null 2>&1 || :
867 [ -n "$cgirootsub" ] || ! [ -d "$rcgiroot" ] || cp -pR "$rcgiroot" "$cgiroot" >/dev/null 2>&1 || :
868 mkdir -p "$webroot" "$cgiroot"
871 cd git.git &&
872 "$MAKE" --no-print-directory --silent NO_SUBDIR=: bindir="$(dirname "$cfg_git_bin")" \
873 GITWEB_CONFIG_COMMON="" GITWEB_CONFIG_SYSTEM="" \
874 GITWEB_CONFIG="$cfg_basedir/gitweb/gitweb_config.perl" SHELL_PATH="$shbin" gitweb &&
875 chown_make gitweb &&
876 PERLBIN="$perlbin" && export PERLBIN &&
877 perl -p -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
878 -e 's/^(\s*use\s+warnings\s*;.*)$/#$1/;' gitweb/gitweb.cgi >"$cgiroot"/gitweb.cgi.$$ &&
879 chmod a+x "$cgiroot"/gitweb.cgi.$$ &&
880 chown_make "$cgiroot"/gitweb.cgi.$$ &&
881 mv -f "$cgiroot"/gitweb.cgi.$$ "$cgiroot"/gitweb.cgi &&
882 cp gitweb/static/*.png gitweb/static/*.css gitweb/static/*.js "$webroot"
884 test $? -eq 0
887 echo "*** Setting up git-browser from git-browser.git..."
888 if ! [ -f git-browser.git/git-browser.cgi ]; then
889 echo "ERROR: git-browser.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
890 exit 1
892 mkdir -p "$webroot"/git-browser "$cgiroot"
894 cd git-browser.git &&
895 CFG="$cfg_basedir/gitweb/git-browser.conf" && export CFG &&
896 PERLBIN="$perlbin" && export PERLBIN && perl -p \
897 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
898 -e 's/"git-browser\.conf"/"$ENV{"CFG"}"/' git-browser.cgi >"$cgiroot"/git-browser.cgi.$$ &&
899 chmod a+x "$cgiroot"/git-browser.cgi.$$ &&
900 chown_make "$cgiroot"/git-browser.cgi.$$ &&
901 perl -p \
902 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
903 -e 's/"git-browser\.conf"/"$ENV{"CFG"}"/' git-diff.cgi >"$cgiroot"/git-diff.cgi.$$ &&
904 chmod a+x "$cgiroot"/git-diff.cgi.$$ &&
905 chown_make "$cgiroot"/git-diff.cgi.$$ &&
906 mv -f "$cgiroot"/git-browser.cgi.$$ "$cgiroot"/git-browser.cgi &&
907 mv -f "$cgiroot"/git-diff.cgi.$$ "$cgiroot"/git-diff.cgi &&
908 for h in *.html; do
909 [ "$h" != "index.html" ] || continue
910 if [ "$h" = "by-commit.html" ] || [ "$h" = "by-date.html" ]; then
911 FAVLINE='<link rel="shortcut icon" href="/git-favicon.png" type="image/png" />' &&
912 export FAVLINE && perl -p -e 'print "$ENV{FAVLINE}\n" if m{</head>};' "$h" \
913 >"$webroot/git-browser/$h.$$" &&
914 chmod a+r "$webroot/git-browser/$h.$$" &&
915 mv -f "$webroot/git-browser/$h.$$" "$webroot/git-browser/$h"
916 else
917 cp -p "$h" "$webroot/git-browser/"
919 done
920 cp -pR *.js *.css js.lib "$webroot/git-browser/" &&
921 cp -pR JSON "$cgiroot/"
923 test $? -eq 0
924 gitwebabs="$cfg_gitweburl"
925 case "$gitwebabs" in "http://"[!/]*|"https://"[!/]*)
926 gitwebabs="${gitwebabs#*://}"
927 case "$gitwebabs" in
928 *"/"*) gitwebabs="/${gitwebabs#*/}";;
929 *) gitwebabs="";;
930 esac
931 esac
932 case "$gitwebabs" in */);;*) gitwebabs="$gitwebabs/"; esac
933 cat >"$basedir/gitweb"/git-browser.conf.$$ <<-EOT
934 gitbin: $cfg_git_bin
935 gitweb: $gitwebabs
936 warehouse: $cfg_reporoot
937 doconfig: $cfg_basedir/gitweb/gitbrowser_config.perl
939 chown_make "$basedir/gitweb"/git-browser.conf.$$
940 mv -f "$basedir/gitweb"/git-browser.conf.$$ "$basedir/gitweb"/git-browser.conf
941 esctitle="$(printf '%s\n' "$cfg_title" | LC_ALL=C sed 's/\\/\\\\/g;s/"/\\"/g;')" || :
942 cat >"$webroot"/git-browser/GitConfig.js.$$ <<-EOT
943 cfg_gitweb_url="$cfg_gitweburl/"
944 cfg_browsercgi_url="$cfg_webadmurl/git-browser.cgi"
945 cfg_home_url="$cfg_gitweburl/%n"
946 cfg_home_text="summary"
947 cfg_bycommit_title="$esctitle - %n/graphiclog1"
948 cfg_bydate_title="$esctitle - %n/graphiclog2"
950 chown_make "$webroot"/git-browser/GitConfig.js.$$
951 mv -f "$webroot"/git-browser/GitConfig.js.$$ "$webroot"/git-browser/GitConfig.js
954 echo "*** Setting up our part of the website..."
955 mkdir -p "$webroot" "$cgiroot"
956 cp "$basedir"/bin/snapshot.cgi "$basedir/cgi"
957 cp "$basedir"/bin/authrequired.cgi "$basedir/cgi"
958 [ -n "$cfg_httpspushurl" ] || rm -f "$basedir/cgi"/usercert.cgi "$cgiroot"/usercert.cgi
959 cp "$basedir/cgi"/*.cgi "$cgiroot"
960 rm -rf "$basedir/cgi"
961 [ -z "$webreporoot" ] || { rm -f "$webreporoot" && ln -s "$cfg_reporoot" "$webreporoot"; }
962 if [ -z "$cfg_httpspushurl" ] || [ -n "$cfg_pretrustedroot" ]; then
963 grep -v 'rootcert[.]html' gitweb/indextext.html >"$basedir/gitweb/indextext.html"
964 else
965 cp gitweb/indextext.html "$basedir/gitweb"
967 mv "$basedir"/html/*.css "$basedir"/html/*.js "$webroot"
968 cp mootools.js "$webroot"
969 cp htaccess "$webroot/.htaccess"
970 cp cgi/htaccess "$cgiroot/.htaccess"
971 cp git-favicon.ico "$webroot/favicon.ico"
972 cp robots.txt "$webroot"
973 cat gitweb/gitweb.css >>"$webroot"/gitweb.css
976 if [ -n "$cfg_httpspushurl" ]; then
977 echo "*** Setting up SSL certificates..."
978 openssl="${var_openssl_bin:-openssl}"
979 createcert() { PATH="$basedir/bin:$PATH" "$basedir/bin/CACreateCert" "$@"; }
980 bits=2048
981 if [ "$cfg_rsakeylength" -gt "$bits" ] 2>/dev/null; then
982 bits="$cfg_rsakeylength"
984 mkdir -p "$cfg_certsdir"
985 [ -d "$cfg_certsdir" ]
986 wwwcertcn=
987 if [ -e "$cfg_certsdir/girocco_www_crt.pem" ]; then
988 wwwcertcn="$(
989 "$openssl" x509 -in "$cfg_certsdir/girocco_www_crt.pem" -noout -subject |
990 sed -e 's,[^/]*,,'
993 wwwcertdns=
994 if [ -n "$cfg_wwwcertaltnames" ]; then
995 for dnsopt in $cfg_wwwcertaltnames; do
996 wwwcertdns="${wwwcertdns:+$wwwcertdns }--dns $dnsopt"
997 done
999 wwwcertdnsfile=
1000 if [ -r "$cfg_certsdir/girocco_www_crt.dns" ]; then
1001 wwwcertdnsfile="$(cat "$cfg_certsdir/girocco_www_crt.dns")"
1003 needroot=
1004 [ -e "$cfg_certsdir/girocco_client_crt.pem" ] &&
1005 [ -e "$cfg_certsdir/girocco_client_key.pem" ] &&
1006 [ -e "$cfg_certsdir/girocco_www_key.pem" ] &&
1007 [ -e "$cfg_certsdir/girocco_www_crt.pem" ] && [ "$wwwcertcn" = "/CN=$cfg_httpsdnsname" ] &&
1008 [ -e "$cfg_certsdir/girocco_root_crt.pem" ] || needroot=1
1009 if [ -n "$needroot" ] && ! [ -e "$cfg_certsdir/girocco_root_key.pem" ]; then
1010 rm -f "$cfg_certsdir/girocco_root_crt.pem" "$cfg_certsdir/girocco_root_key.pem"
1011 umask 0077
1012 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_root_key.pem" $bits
1013 chmod 0600 "$cfg_certsdir/girocco_root_key.pem"
1014 rm -f "$cfg_certsdir/girocco_root_crt.pem"
1015 umask 0022
1016 echo "Created new root key"
1018 if ! [ -e "$cfg_certsdir/girocco_root_crt.pem" ]; then
1019 createcert --root --key "$cfg_certsdir/girocco_root_key.pem" \
1020 --out "$cfg_certsdir/girocco_root_crt.pem" "girocco $cfg_nickname root certificate"
1021 rm -f "$cfg_certsdir/girocco_www_crt.pem" "$cfg_certsdir/girocco_www_chain.pem"
1022 rm -f "$cfg_certsdir/girocco_client_crt.pem" "$cfg_certsdir/girocco_client_suffix.pem"
1023 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
1024 rm -f "$cfg_chroot/etc/sshcerts"/*.pem
1025 echo "Created new root certificate"
1027 if ! [ -e "$cfg_certsdir/girocco_www_key.pem" ]; then
1028 umask 0077
1029 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_www_key.pem" $bits
1030 chmod 0600 "$cfg_certsdir/girocco_www_key.pem"
1031 rm -f "$cfg_certsdir/girocco_www_crt.pem"
1032 umask 0022
1033 echo "Created new www key"
1035 if ! [ -e "$cfg_certsdir/girocco_www_crt.pem" ] ||
1036 [ "$wwwcertcn" != "/CN=$cfg_httpsdnsname" ] || [ "$wwwcertdns" != "$wwwcertdnsfile" ]; then
1037 "$openssl" rsa -in "$cfg_certsdir/girocco_www_key.pem" -pubout |
1038 createcert --server --key "$cfg_certsdir/girocco_root_key.pem" \
1039 --cert "$cfg_certsdir/girocco_root_crt.pem" $wwwcertdns \
1040 --out "$cfg_certsdir/girocco_www_crt.pem" "$cfg_httpsdnsname"
1041 printf '%s\n' "$wwwcertdns" >"$cfg_certsdir/girocco_www_crt.dns"
1042 echo "Created www certificate"
1044 if ! [ -e "$cfg_certsdir/girocco_www_chain.pem" ]; then
1045 cat "$cfg_certsdir/girocco_root_crt.pem" >"$cfg_certsdir/girocco_www_chain.pem"
1046 echo "Created www certificate chain file"
1048 if ! [ -e "$cfg_certsdir/girocco_client_key.pem" ]; then
1049 umask 0037
1050 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_client_key.pem" $bits
1051 chmod 0640 "$cfg_certsdir/girocco_client_key.pem"
1052 rm -f "$cfg_certsdir/girocco_client_crt.pem"
1053 umask 0022
1054 echo "Created new client key"
1056 if ! [ -e "$cfg_certsdir/girocco_client_crt.pem" ]; then
1057 "$openssl" rsa -in "$cfg_certsdir/girocco_client_key.pem" -pubout |
1058 createcert --subca --key "$cfg_certsdir/girocco_root_key.pem" \
1059 --cert "$cfg_certsdir/girocco_root_crt.pem" \
1060 --out "$cfg_certsdir/girocco_client_crt.pem" "girocco $cfg_nickname client authority"
1061 rm -f "$cfg_certsdir/girocco_client_suffix.pem"
1062 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
1063 rm -f "$cfg_chroot/etc/sshcerts"/*.pem
1064 echo "Created client certificate"
1066 if ! [ -e "$cfg_certsdir/girocco_client_suffix.pem" ]; then
1067 cat "$cfg_certsdir/girocco_client_crt.pem" >"$cfg_certsdir/girocco_client_suffix.pem"
1068 echo "Created client certificate suffix file"
1070 if [ -z "$cfg_pretrustedroot" ]; then
1071 cat "$cfg_rootcert" >"$webroot/${cfg_nickname}_root_cert.pem"
1072 else
1073 rm -f "$webroot/${cfg_nickname}_root_cert.pem"
1075 if [ -n "$cfg_mob" ]; then
1076 if ! [ -e "$cfg_certsdir/girocco_mob_user_key.pem" ]; then
1077 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_mob_user_key.pem" $bits
1078 chmod 0644 "$cfg_certsdir/girocco_mob_user_key.pem"
1079 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
1080 echo "Created new mob user key"
1082 if ! [ -e "$cfg_certsdir/girocco_mob_user_crt.pem" ]; then
1083 "$openssl" rsa -in "$cfg_mobuserkey" -pubout |
1084 createcert --client --key "$cfg_clientkey" \
1085 --cert "$cfg_clientcert" \
1086 --out "$cfg_certsdir/girocco_mob_user_crt.pem" 'mob'
1087 echo "Created mob user client certificate"
1089 cat "$cfg_mobuserkey" >"$webroot/${cfg_nickname}_mob_key.pem"
1090 cat "$cfg_mobusercert" "$cfg_clientcertsuffix" >"$webroot/${cfg_nickname}_mob_user.pem"
1091 else
1092 rm -f "$webroot/${cfg_nickname}_mob_key.pem" "$webroot/${cfg_nickname}_mob_user.pem"
1094 else
1095 rm -f "$webroot/${cfg_nickname}_root_cert.pem"
1096 rm -f "$webroot/${cfg_nickname}_mob_key.pem" "$webroot/${cfg_nickname}_mob_user.pem"
1100 echo "*** Processing website html templates..."
1101 rm -f "$cgiroot/html.cgi"
1102 rm -rf "$cgiroot/html"
1103 mkdir -p "$cgiroot/html"
1104 for tf in "$basedir/html"/*.html; do
1105 tfb="${tf##*/}"
1106 "$perlbin" -I"$basedir" cgi/html.cgi "$webroot" "$tfb" "$basedir" >"$cgiroot/html/$tfb"
1107 rm -f "$tf"
1108 done
1110 echo "*** Formatting markdown documentation..."
1111 mkdir -p "$cgiroot/html/gfm"
1112 for d in basics.md syntax.md; do
1114 cat <<-HEADER
1115 <!DOCTYPE html>
1116 <html xmlns="http://www.w3.org/1999/xhtml">
1117 <head>
1118 <meta charset="utf-8" />
1119 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
1120 <title>$d</title>
1121 </head>
1122 <body><pre>
1123 HEADER
1124 <"markdown.git/$d" LC_ALL=C sed -e '/\[[Ll]icense\]/d' \
1125 -e 's, \([a-z][a-z]*\)\.md, \1.md.html,' \
1126 -e 's/ by adding `.md` to the URL//' \
1127 -e 's/&/\&amp;/g' -e 's/</\&lt;/g' <"markdown.git/$d"
1128 cat <<-FOOTER
1129 </pre></body>
1130 </html>
1131 FOOTER
1132 } >"$cgiroot/html/gfm/$d.html"
1134 title="Markdown: $(echo "${d%.md}" | "$perlbin" -pe '$_=ucfirst')"
1135 gwfpath="$cfg_gitwebfiles"
1136 case "$gwfpath" in *"//"*)
1137 case "$gwfpath" in *"/");;*) gwfpath="$gwfpath/"; esac
1138 gwfpath="${gwfpath#*//}"; gwfpath="${gwfpath#*/}"
1139 esac
1140 case "$gwfpath" in "/"*);;*) gwfpath="/$gwfpath"; esac
1141 gwfpath="${gwfpath%/}"
1142 cat <<-HEADER
1143 <!DOCTYPE html>
1144 <html xmlns="http://www.w3.org/1999/xhtml">
1145 <head>
1146 <meta charset="utf-8" />
1147 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
1148 <title>$title</title>
1149 <link rel="stylesheet" type="text/css" href="$gwfpath/gitweb.css" />
1150 <link rel="stylesheet" type="text/css" href="$gwfpath/girocco.css" />
1151 <link rel="shortcut icon" href="$gwfpath/git-favicon.png" type="image/png" />
1152 </head>
1153 <body style="text-align:center">
1154 <div class="readme" style="overflow:inherit;display:inline-block;text-align:left;max-width:42pc">
1155 HEADER
1156 <"markdown.git/$d" LC_ALL=C sed -e '/\[[Ll]icense\]/d' \
1157 -e 's, \([a-z][a-z]*\)\.md, \1.md.html,' \
1158 -e 's/ by adding `.md` to the URL//' |
1159 "$perlbin" "markdown.git/Markdown.pl"
1160 cat <<-FOOTER
1161 </div>
1162 </body>
1163 </html>
1164 FOOTER
1165 } >"$cgiroot/html/gfm/${d%.md}.html"
1166 done
1169 echo "*** Finalizing permissions and moving into place..."
1170 chown -R -h "$cfg_mirror_user""$owngroup" "$basedir" "$webroot" "$cgiroot"
1171 [ -z "$cfg_httpspushurl" ] || chown -R -h "$cfg_mirror_user""$owngroup" "$cfg_certsdir"
1173 # This should always be the very last thing install.sh does
1174 rm -rf "$rbasedir-old" "$rwebroot-old" "$rcgiroot-old"
1175 quick_move "$basedir" "$rbasedir" "$rbasedir-old"
1176 [ -n "$webrootsub" ] || quick_move "$webroot" "$rwebroot" "$rwebroot-old"
1177 [ -n "$cgirootsub" ] || quick_move "$cgiroot" "$rcgiroot" "$rcgiroot-old"
1178 rm -rf "$rbasedir-old" "$rwebroot-old" "$rcgiroot-old"
1179 echo "--- Update hooks and config with $cfg_basedir/toolbox/update-all-projects.sh"
1180 ! [ -S "$cfg_chroot/etc/taskd.socket" ] || {
1181 echo "*** Requesting graceful restart of running taskd (and, if running, jobd)..."
1182 touch "$cfg_chroot/etc/taskd.restart"
1183 chown_make "$cfg_chroot/etc/taskd.restart"
1184 trap ':' PIPE
1185 echo "nop" | nc_openbsd -w 5 -U "$cfg_chroot/etc/taskd.socket" || :
1186 trap - PIPE