config: always explicitly set PATH to something
[girocco.git] / install.sh
blobcffd6b77f2b0815dd03a995f9d4e2c6b8470318d
1 #!/bin/sh
2 # The Girocco installation script
3 # We will OVERWRITE basedir!
5 set -e
7 echol() { printf '%s\n' "$*"; }
9 # Include custom configuration, if any
10 [ ! -e config.sh ] || [ ! -f config.sh ] || [ ! -r config.sh ] || . ./config.sh
12 [ -n "$MAKE" ] || MAKE="$(MAKEFLAGS= make -s gnu_make_command_name | grep '^gnu_make_command_name=' | sed 's/^[^=]*=//')"
13 if [ -z "$MAKE" ]; then
14 echo "ERROR: cannot determine name of the GNU make command" >&2
15 echo "Please set MAKE to the name of the GNU make executable" >&2
16 exit 1
19 # Run perl module checker
20 if ! [ -f toolbox/check-perl-modules.pl ] || ! [ -x toolbox/check-perl-modules.pl ]; then
21 echo "ERROR: missing toolbox/check-perl-modules.pl!" >&2
22 exit 1
25 # What Config should we use?
26 [ -n "$GIROCCO_CONF" ] || GIROCCO_CONF=Girocco::Config
27 export GIROCCO_CONF
28 echo "*** Initializing using $GIROCCO_CONF..."
30 # First run Girocco::Config consistency checks
31 perl -I"$PWD" -M$GIROCCO_CONF -MGirocco::Validator -e ''
33 . ./shlib.sh
34 umask 0022
35 "$var_perl_bin" toolbox/check-perl-modules.pl
37 # Config.pm already checked $cfg_reporoot to require an absolute path, but
38 # we also require it does not contain a : or ; that would cause problems when
39 # used in GIT_ALTERNATE_OBJECT_DIRECTORIES
40 probch=':;'
41 case "$cfg_reporoot" in *[$probch]*)
42 echo "fatal: \$Girocco::Config::reporoot may not contain ':' or ';' characters" >&2
43 exit 1
44 esac
46 warn() { printf >&2 '%s\n' "$*"; }
47 die() { warn "$@"; exit 1; }
49 # Either we must run as root (but preferably not if disable_jailsetup is true)
50 # or the mirror_user (preferred choice for disable_jailsetup).
51 isroot=
52 [ "$(id -u)" -ne 0 ] || isroot=1
53 if [ -n "$isroot" ]; then
54 if [ "${cfg_disable_jailsetup:-0}" != "0" ]; then
55 cat <<'EOT'
57 ***
58 *** WARNING: $Girocco::Config::disable_jailsetup has been enabled
59 *** WARNING: but installation is being performed as the superuser
60 ***
62 You appear to have disabled jailsetup which is perfectly fine for installations
63 that will not be using an ssh jail. However, in that case, running the install
64 process as the superuser is highly discouraged.
66 Instead, running it as the configured $Girocco::Config::mirror_user is much
67 preferred.
69 The install process will now pause for 10 seconds to give you a chance to abort
70 it before continuing to install a disable_jailsetup config as the superuser.
72 EOT
73 sleep 10 || die "install aborted"
75 else
76 [ -n "$cfg_mirror_user" ] || die 'Girocco::Config.pm $mirror_user must be set'
77 curuname="$(id -un)"
78 [ -n "$curuname" ] || die "Cannot determine name of current user"
79 if [ "$cfg_mirror_user" != "$curuname" ]; then
80 warn "ERROR: install must run as superuser or Config.pm's \$mirror_user ($cfg_mirror_user)"
81 die "ERROR: install is currently running as $curuname"
85 # $1 must exist and be a dir
86 # $2 may exist but must be a dir
87 # $3 must not exist
88 # After call $2 will be renamed to $3 (if $2 existed)
89 # And $1 will be renamed to $2
90 quick_move() {
91 [ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] || { echo "fatal: quick_move: bad args: '$1' '$2' '$3'" >&2; exit 1; }
92 ! [ -e "$3" ] || { echo "fatal: quick_move: already exists: $3" >&2; exit 1; }
93 [ -d "$1" ] || { echo "fatal: quick_move: no such dir: $1" >&2; exit 1; }
94 ! [ -e "$2" ] || [ -d "$2" ] || { echo "fatal: quick_move: not a dir: $2" >&2; exit 1; }
95 perl -e 'rename($ARGV[1], $ARGV[2]) or die "rename failed: $!\n" if -d $ARGV[1];
96 rename($ARGV[0], $ARGV[1]) or die "rename failed: $!\n"; exit 0;' "$1" "$2" "$3" || {
97 echo "fatal: quick_move: rename failed" >&2
98 exit 1
100 ! [ -d "$1" ] && [ -d "$2" ] || {
101 echo "fatal: quick_move: rename failed" >&2
102 exit 1
106 check_sh_builtin() (
107 "unset" -f command
108 "command" "$var_sh_bin" -c '{ "unset" -f unalias command "$1" || :; "unalias" "$1" || :; } >/dev/null 2>&1; "command" -v "$1"' "$var_sh_bin" "$1"
109 ) 2>/dev/null
111 owngroup=
112 [ -z "$cfg_owning_group" ] || owngroup=":$cfg_owning_group"
113 if [ -n "$cfg_httpspushurl" ] && [ -z "$cfg_certsdir" ]; then
114 echo "ERROR: \$httpspushurl is set but \$certsdir is not!" >&2
115 echo "ERROR: perhaps you have an incorrect Config.pm?" >&2
116 exit 1
120 # Check for extra required tools
121 if [ "${cfg_xmllint_readme:-0}" != "0" ] && ! command -v xmllint >/dev/null; then
122 echo "ERROR: \$xmllint_readme set but xmllint not in \$PATH!" >&2
123 exit 1
127 echo "*** Checking for compiled utilities..."
128 if ! [ -f src/can_user_push ] || ! [ -x src/can_user_push ]; then
129 echo "ERROR: src/can_user_push is not built! Did you _REALLY_ read INSTALL?" >&2
130 echo "ERROR: perhaps you forgot to run make?" >&2
131 exit 1
133 if ! [ -f src/can_user_push_http ] || ! [ -x src/can_user_push_http ]; then
134 echo "ERROR: src/can_user_push_http is not built! Did you _REALLY_ read INSTALL?" >&2
135 echo "ERROR: perhaps you forgot to run make?" >&2
136 exit 1
138 if ! [ -f src/getent ] || ! [ -x src/getent ]; then
139 echo "ERROR: src/getent is not built! Did you _REALLY_ read INSTALL?" >&2
140 echo "ERROR: perhaps you forgot to run make?" >&2
141 exit 1
143 if ! [ -f src/get_sun_path_len ] || ! [ -x src/get_sun_path_len ]; then
144 echo "ERROR: src/get_sun_path_len is not built! Did you _REALLY_ read INSTALL?" >&2
145 echo "ERROR: perhaps you forgot to run make?" >&2
146 exit 1
148 if ! [ -f src/get_user_uuid ] || ! [ -x src/get_user_uuid ]; then
149 echo "ERROR: src/get_user_uuid is not built! Did you _REALLY_ read INSTALL?" >&2
150 echo "ERROR: perhaps you forgot to run make?" >&2
151 exit 1
153 if ! [ -f src/list_packs ] || ! [ -x src/list_packs ]; then
154 echo "ERROR: src/list_packs is not built! Did you _REALLY_ read INSTALL?" >&2
155 echo "ERROR: perhaps you forgot to run make?" >&2
156 exit 1
158 if ! [ -f src/peek_packet ] || ! [ -x src/peek_packet ]; then
159 echo "ERROR: src/peek_packet is not built! Did you _REALLY_ read INSTALL?" >&2
160 echo "ERROR: perhaps you forgot to run make?" >&2
161 exit 1
163 if ! [ -f src/rangecgi ] || ! [ -x src/rangecgi ]; then
164 echo "ERROR: src/rangecgi is not built! Did you _REALLY_ read INSTALL?" >&2
165 echo "ERROR: perhaps you forgot to run make?" >&2
166 exit 1
168 if ! [ -f src/readlink ] || ! [ -x src/readlink ]; then
169 echo "ERROR: src/readlink is not built! Did you _REALLY_ read INSTALL?" >&2
170 echo "ERROR: perhaps you forgot to run make?" >&2
171 exit 1
173 if ! [ -f src/strftime ] || ! [ -x src/strftime ]; then
174 echo "ERROR: src/strftime is not built! Did you _REALLY_ read INSTALL?" >&2
175 echo "ERROR: perhaps you forgot to run make?" >&2
176 exit 1
178 if ! [ -f src/throttle ] || ! [ -x src/throttle ]; then
179 echo "ERROR: src/throttle is not built! Did you _REALLY_ read INSTALL?" >&2
180 echo "ERROR: perhaps you forgot to run make?" >&2
181 exit 1
183 if ! [ -f src/ulimit512 ] || ! [ -x src/ulimit512 ]; then
184 echo "ERROR: src/ulimit512 is not built! Did you _REALLY_ read INSTALL?" >&2
185 echo "ERROR: perhaps you forgot to run make?" >&2
186 exit 1
188 ebin="/bin/echo"
189 if [ ! -x "$ebin" ] && [ -x "/usr/bin/echo" ]; then
190 ebin="/usr/bin/echo"
192 if [ ! -x "$ebin" ]; then
193 echo "ERROR: neither /bin/echo nor /usr/bin/echo found" >&2
194 echo "ERROR: at least one must be present for testing during install" >&2
195 exit 1
197 ec=999
198 tmpfile="$(mktemp "/tmp/ul512-$$-XXXXXX")"
199 { src/ulimit512 -f 0 "$ebin" test >"$tmpfile" || ec=$?; } >/dev/null 2>&1
200 rm -f "$tmpfile"
201 if [ "$ec" = "999" ] || [ "$ec" = "0" ]; then
202 echo "ERROR: src/ulimit512 is built, but broken!" >&2
203 echo "ERROR: exceeding file size limit did not fail!" >&2
204 exit 1
206 if ! [ -f src/ltsha256 ] || ! [ -x src/ltsha256 ]; then
207 echo "ERROR: src/ltsha256 is not built! Did you _REALLY_ read INSTALL?" >&2
208 echo "ERROR: perhaps you forgot to run make?" >&2
209 exit 1
211 sha256check="15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225"
212 sha256result="$(printf '%s' '123456789' | src/ltsha256)"
213 if [ "$sha256check" != "$sha256result" ]; then
214 echo "ERROR: src/ltsha256 is built, but broken!" >&2
215 echo "ERROR: verifying sha256 hash of '123456789' failed!" >&2
216 exit 1
218 if ! [ -f src/ltsha1 ] || ! [ -x src/ltsha1 ]; then
219 echo "ERROR: src/ltsha1 is not built! Did you _REALLY_ read INSTALL?" >&2
220 echo "ERROR: perhaps you forgot to run make?" >&2
221 exit 1
223 sha1check="f7c3bc1d808e04732adf679965ccc34ca7ae3441"
224 sha1result="$(printf '%s' '123456789' | src/ltsha1)"
225 if [ "$sha1check" != "$sha1result" ]; then
226 echo "ERROR: src/ltsha1 is built, but broken!" >&2
227 echo "ERROR: verifying sha1 hash of '123456789' failed!" >&2
228 exit 1
230 var_sun_path_len="$(src/get_sun_path_len 2>/dev/null)" || :
232 [ -z "$var_sun_path_len" ] ||
233 [ "${var_sun_path_len#*[!0-9]}" != "$var_sun_path_len" ] ||
234 [ "$var_sun_path_len" -lt 80 ] || [ "$var_sun_path_len" -gt 4096 ]
235 then
236 echol "ERROR: src/get_sun_path_len is built, but bogus!" >&2
237 echol "ERROR: reports sizeof(struct sockaddr_un.sun_path) is '$var_sun_path_len'" >&2
238 exit 1
240 taskdsockpath="$cfg_chroot/etc/taskd.socket@" # "@" stands in for the NUL byte
241 if [ "${#taskdsockpath}" -gt "$var_sun_path_len" ]; then
242 echol "ERROR: maximum length of sockaddr_un.sun_path is $var_sun_path_len" >&2
243 echol "ERROR: the configured taskd.socket path has length ${#taskdsockpath}" >&2
244 echol "ERROR: reduce the length of \$Girocco::Config::chroot to shorten" >&2
245 echol "ERROR: '${taskdsockpath%?}'" >&2
246 echol "ERROR: to fit (including the final '\\0' byte)" >&2
247 exit 1
251 echo "*** Checking for ezcert..."
252 if ! [ -f ezcert.git/CACreateCert ] || ! [ -x ezcert.git/CACreateCert ]; then
253 echo "ERROR: ezcert.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
254 exit 1
258 echo "*** Checking for git..."
259 case "$cfg_git_bin" in /*) :;; *)
260 echo 'ERROR: $Girocco::Config::git_bin must be set to an absolute path' >&2
261 exit 1
262 esac
263 if ! [ -f "$cfg_git_bin" ] || ! [ -x "$cfg_git_bin" ]; then
264 echo "ERROR: $cfg_git_bin does not exist or is not executable" >&2
265 exit 1
267 if ! git_version="$("$cfg_git_bin" version)" || [ -z "$git_version" ]; then
268 echo "ERROR: $cfg_git_bin version failed" >&2
269 exit 1
271 case "$git_version" in
272 [Gg]"it version "*) :;;
274 echo "ERROR: '$cfg_git_bin version' output does not start with 'git version '" >&2
275 exit 1
276 esac
277 echo "Found $cfg_git_bin $git_version"
278 git_vernum="$(echo "$git_version" | sed -ne 's/^[^0-9]*\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$/\1/p')"
279 echo "*** Checking Git $git_vernum for compatibility..."
280 if [ "$(vcmp "$git_vernum" 1.6.6)" -lt 0 ]; then
281 echo 'ERROR: $Girocco::Config::git_bin must be at least Git version 1.6.6'
282 exit 1
284 if [ "$(vcmp "$git_vernum" 1.6.6.3)" -lt 0 ]; then
285 echo 'WARNING: $Girocco::Config::git_bin version < 1.6.6.3, clients will not see useful error messages'
287 if [ "$(vcmp "$git_vernum" 1.7.3)" -lt 0 ]; then
288 cat <<'EOT'
291 *** SEVERE WARNING: $Girocco::Config::git_bin is set to a version of Git before 1.7.3
294 Some Girocco functionality will be gracefully disabled and other things will
295 just not work at all such as race condition protection against simultaneous
296 client pushes and server garbage collections.
300 if [ -n "$cfg_mirror" ] && [ "$(vcmp "$git_vernum" 1.7.5)" -lt 0 ]; then
301 echo 'WARNING: $Girocco::Config::git_bin version < 1.7.5 and mirroring enabled, some sources can cause an infinite fetch loop'
303 if [ "$(vcmp "$git_vernum" 1.7.6.6)" -lt 0 ]; then
304 echo 'WARNING: $Girocco::Config::git_bin version < 1.7.6.6, performance may be degraded'
306 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
307 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'
308 echo 'WARNING: See https://lore.kernel.org/git/20141222041944.GA441@peff.net/ for details'
310 if [ "$(vcmp "$git_vernum" 1.8.4.2)" -ge 0 ] && [ -n "$cfg_mirror" ] && [ "$(vcmp "$git_vernum" 2)" -lt 0 ]; then
311 echo 'WARNING: $Girocco::Config::git_bin version >= 1.8.4.2 and < 2.0.0, git-daemon needs write access for shallow clones'
312 echo 'WARNING: $Girocco::Config::git_bin version >= 1.8.4.2 and < 2.0.0, shallow clones will leave repository turds'
314 if [ "$(vcmp "$git_vernum" 1.8.4.3)" -lt 0 ]; then
315 echo 'WARNING: $Girocco::Config::git_bin version < 1.8.4.3, clients will not receive symref=HEAD:refs/heads/...'
317 if [ "$(vcmp "$git_vernum" 2.1)" -lt 0 ]; then
318 echo 'WARNING: $Girocco::Config::git_bin version < 2.1.0, pack bitmaps will not be available'
320 if [ "$(vcmp "$git_vernum" 2.1)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.1.3)" -lt 0 ]; then
321 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'
323 if [ "$(vcmp "$git_vernum" 2.2)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.3.2)" -lt 0 ]; then
324 cat <<'EOT'
327 *** ERROR: $Girocco::Config::git_bin is set to an incompatible version of Git
330 Git versions starting with 2.2.0 and continuing up through 2.3.1 are incompatible
331 with Girocco due to various unresolved issues. Please either downgrade to 2.1.4
332 or earlier or, more preferred, upgrade to 2.3.2 (ideally 2.4.11) or later.
334 In order to bypass this check you will have to modify install.sh in which case
335 USE THE SELECTED GIT BINARY AT YOUR OWN RISK!
338 exit 1
340 if [ "$(vcmp "$git_vernum" 2.3.3)" -lt 0 ]; then
341 echo 'WARNING: $Girocco::Config::git_bin version < 2.3.3, performance will be sub-optimal'
343 if [ "$(vcmp "$git_vernum" 2.4.4)" -lt 0 ]; then
344 echo 'WARNING: $Girocco::Config::git_bin version < 2.4.4, many refs smart HTTP fetches can deadlock'
346 if [ "$(vcmp "$git_vernum" 2.10.1)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.12.3)" -lt 0 ]; then
347 echo 'WARNING: $Girocco::Config::git_bin version >= 2.10.1 and < 2.12.3, --pickaxe-regex can segfault'
348 echo 'WARNING: If gitweb pickaxe regular expression searches are enabled, --pickaxe-regex will be used'
349 echo 'WARNING: See the fix at http://repo.or.cz/git.git/f53c5de29cec68e3 for details'
350 echo 'WARNING: The fix is trivial and easily cherry-picked into a custom 2.10.1 - 2.12.2 build'
351 echo 'WARNING: Leaving the gitweb/gitweb_config.perl "regexp" feature off as recommended avoids the issue'
353 secmsg=
354 if [ "$(vcmp "$git_vernum" 2.4.11)" -lt 0 ]; then
355 secmsg='prior to 2.4.11'
357 if [ "$(vcmp "$git_vernum" 2.5)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.5.5)" -lt 0 ]; then
358 secmsg='2.5.x prior to 2.5.5'
360 if [ "$(vcmp "$git_vernum" 2.6)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.6.6)" -lt 0 ]; then
361 secmsg='2.6.x prior to 2.6.6'
363 if [ "$(vcmp "$git_vernum" 2.7)" -ge 0 ] && [ "$(vcmp "$git_vernum" 2.7.4)" -lt 0 ]; then
364 secmsg='2.7.x prior to 2.7.4'
366 if [ -n "$secmsg" ]; then
367 cat <<EOT
370 *** SEVERE WARNING: \$Girocco::Config::git_bin is set to a version of Git $secmsg
373 Security issues exist in Git versions prior to 2.4.11, 2.5.x prior to 2.5.5,
374 2.6.x prior to 2.6.6 and 2.7.x prior to 2.7.4.
376 Besides the security fixes included in later versions, versions prior to
377 2.2.0 may accidentally prune unreachable loose objects earlier than
378 intended. Since Git version 2.4.11 is the minimum version to include all
379 security fixes to date, it should be considered the absolute minimum
380 version of Git to use when running Girocco.
382 This is not enforced, but Git is easy to build from the git.git submodule
383 and upgrading to GIT VERSION 2.4.11 OR LATER IS HIGHLY RECOMMENDED.
385 We will now pause for a moment so you can reflect on this warning.
388 sleep 60
390 if [ -n "$cfg_mirror" ] && [ "$cfg_mirror" != 0 ] && LC_ALL=C grep -a -q ns_parserr "$cfg_git_bin"; then
391 cat <<'EOT'
394 *** WARNING: $Girocco::Config::git_bin is set to a questionable Git binary
397 You appear to have enabled mirroring and the Git binary you have selected
398 appears to contain an experimental patch that cannot be disabled. This
399 patch can generate invalid network DNS traffic and/or cause long delays
400 when fetching using the "git:" protocol when no port number is specified.
401 It may also end up retrieving repsitory contents from a host other than
402 the one specified in the "git:" URL when the port is omitted.
404 You are advised to either build your own version of Git (the problem patch
405 is not part of the official Git repository) or disable mirroring (via the
406 $Girocco::Config:mirror setting) to avoid these potential problems.
408 USE THE SELECTED GIT BINARY AT YOUR OWN RISK!
411 sleep 5
414 test_nc_U() {
415 [ -n "$1" ] || return 1
416 _cmdnc="$(command -v "$1" 2>/dev/null)" || :
417 [ -n "$_cmdnc" ] && [ -f "$_cmdnc" ] && [ -x "$_cmdnc" ] || return 1
418 _tmpdir="$(mktemp -d /tmp/nc-u-XXXXXX)"
419 [ -n "$_tmpdir" ] && [ -d "$_tmpdir" ] || return 1
420 >"$_tmpdir/output"
421 (sleep 3 | "$_cmdnc" -l -U "$_tmpdir/socket" 2>/dev/null >"$_tmpdir/output" || >"$_tmpdir/failed")&
422 _bgpid="$!"
423 sleep 1
424 echo "testing" | "$_cmdnc" -w 1 -U "$_tmpdir/socket" >/dev/null 2>&1 || >"$_tmpdir/failed"
425 sleep 1
426 kill "$_bgpid" >/dev/null 2>&1 || :
427 read -r _result <"$_tmpdir/output" || :
428 _bad=
429 ! [ -e "$_tmpdir/failed" ] || _bad=1
430 rm -rf "$_tmpdir"
431 [ -z "$_bad" ] && [ "$_result" = "testing" ]
432 } >/dev/null 2>&1
434 echo "*** Verifying \$Girocco::Config::nc_openbsd_bin supports -U option..."
435 test_nc_U "$var_nc_openbsd_bin" || {
436 echo "ERROR: invalid Girocco::Config::nc_openbsd_bin setting" >&2
437 echo "ERROR: \"$var_nc_openbsd_bin\" does not grok the -U option" >&2
438 uname_s="$(uname -s 2>/dev/null | tr A-Z a-z 2>/dev/null)" || :
439 case "$uname_s" in
440 *dragonfly*)
441 echo "ERROR: see the src/dragonfly/README file for a solution" >&2;;
442 *kfreebsd*|*linux*)
443 echo "ERROR: try installing the package named 'netcat-openbsd'" >&2;;
444 esac
445 exit 1
448 echo "*** Verifying selected POSIX sh is sane..."
449 shbin="$var_sh_bin"
450 [ -n "$shbin" ] && [ -f "$shbin" ] && [ -x "$shbin" ] && [ "$("$shbin" -c 'echo sh $(( 1 + 1 ))' 2>/dev/null)" = "sh 2" ] || {
451 echo 'ERROR: invalid $Girocco::Config::posix_sh_bin setting' >&2
452 exit 1
454 [ "$(check_sh_builtin command)" = "command" ] || {
455 echo 'ERROR: invalid $Girocco::Config::posix_sh_bin setting (does not understand command -v)' >&2
456 exit 1
458 sh_not_builtin=
459 sh_extra_chroot_installs=
460 badsh=
461 for sbi in cd pwd read umask unset unalias; do
462 if [ "$(check_sh_builtin "$sbi")" != "$sbi" ]; then
463 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (missing built-in $sbi)" >&2
464 badsh=1
466 done
467 [ -z "$badsh" ] || exit 1
468 for sbi in '[' echo printf test; do
469 if ! extra="$(check_sh_builtin "$sbi")"; then
470 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (missing command $sbi)" >&2
471 badsh=1
472 continue
474 if [ "$extra" != "$sbi" ]; then
475 case "$extra" in /*) :;; *)
476 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (bad command -v $sbi result: $extra)" >&2
477 badsh=1
478 continue
479 esac
480 withspc=
481 case "$extra" in *" "*) withspc=1; esac
482 [ -z "$withspc" ] && [ -f "$extra" ] && [ -r "$extra" ] && [ -x "$extra" ] || {
483 echo "ERROR: invalid \$Girocco::Config::posix_sh_bin setting (unusable command -v $sbi result: $extra)" >&2
484 badsh=1
485 continue
487 echo "WARNING: slow \$Girocco::Config::posix_sh_bin setting (not built-in $sbi)" >&2
488 sh_not_builtin="$sh_not_builtin $sbi"
489 sh_extra_chroot_installs="$sh_extra_chroot_installs $extra"
491 done
492 [ -z "$badsh" ] || exit 1
493 [ -z "$sh_extra_chroot_installs" ] || {
494 echo "WARNING: the selected POSIX sh implements these as non-built-in:$sh_not_builtin" >&2
495 echo "WARNING: as a result it will run slower than necessary" >&2
496 echo "WARNING: consider building and switching to dash which can be found at:" >&2
497 echo "WARNING: http://gondor.apana.org.au/~herbert/dash/" >&2
498 echo "WARNING: (download a tarball from the files section or clone the Git repository" >&2
499 echo "WARNING: and checkout the latest tag, run autogen.sh, configure and build)" >&2
500 echo "WARNING: dash is licensed under the 3-clause BSD license" >&2
503 echo "*** Verifying xargs is sane..."
504 _xargsr="$(</dev/null command xargs printf %s -r)" || :
505 xtest1="$(</dev/null command xargs $_xargsr printf 'test %s ' 2>/dev/null)" || :
506 xtest2="$(printf '%s\n' one two | command xargs $_xargsr printf 'test %s ' 2>/dev/null)" || :
507 [ -z "$xtest1" ] && [ "$xtest2" = "test one test two " ] || {
508 echo 'ERROR: xargs is unusable' >&2
509 echo 'ERROR: either `test -z "$(</dev/null xargs echo test 2>/dev/null)"`' >&2
510 echo 'ERROR: or `test -z "$(</dev/null xargs -r echo test 2>/dev/null)"`' >&2
511 echo 'ERROR: must be true, but neither is' >&2
512 exit 1
515 echo "*** Verifying selected perl is sane..."
516 perlbin="$var_perl_bin"
517 [ -n "$perlbin" ] && [ -f "$perlbin" ] && [ -x "$perlbin" ] && [ "$("$perlbin" -wle 'print STDOUT "perl ", + ( 1 + 1 )' 2>/dev/null)" = "perl 2" ] || {
518 echo 'ERROR: invalid $Girocco::Config::perl_bin setting' >&2
519 exit 1
522 echo "*** Verifying selected gzip is sane..."
523 gzipbin="$var_gzip_bin"
524 [ -n "$gzipbin" ] && [ -f "$gzipbin" ] && [ -x "$gzipbin" ] && "$gzipbin" -V 2>&1 | grep -q gzip &&
525 [ "$(echo Girocco | "$gzipbin" -c -n -9 | "$gzipbin" -c -d)" = "Girocco" ] || {
526 echo 'ERROR: invalid $Girocco::Config::gzip_bin setting' >&2
527 exit 1
530 echo "*** Verifying basedir, webroot, webreporoot and cgiroot paths..."
531 # Make sure $cfg_basedir, $cfg_webroot and $cfg_cgiroot are absolute paths
532 case "$cfg_basedir" in /*) :;; *)
533 echo "ERROR: invalid Girocco::Config::basedir setting" >&2
534 echo "ERROR: \"$cfg_basedir\" must be an absolute path (start with '/')" >&2
535 exit 1
536 esac
537 case "$cfg_webroot" in /*) :;; *)
538 echo "ERROR: invalid Girocco::Config::webroot setting" >&2
539 echo "ERROR: \"$cfg_webroot\" must be an absolute path (start with '/')" >&2
540 exit 1
541 esac
542 if [ -n "$cfg_webreporoot" ]; then
543 case "$cfg_webreporoot" in /*) :;; *)
544 echo "ERROR: invalid Girocco::Config::webreporoot setting" >&2
545 echo "ERROR: \"$cfg_webreporoot\" must be an absolute path (start with '/') or undef" >&2
546 exit 1
547 esac
549 case "$cfg_cgiroot" in /*) :;; *)
550 echo "ERROR: invalid Girocco::Config::cgiroot setting" >&2
551 echo "ERROR: \"$cfg_cgiroot\" must be an absolute path (start with '/')" >&2
552 exit 1
553 esac
555 # return the input with trailing slashes stripped but return "/" for all "/"s
556 striptrsl() {
557 [ -n "$1" ] || return 0
558 _s="${1##*[!/]}"
559 [ "$_s" != "$1" ] || _s="${_s#?}"
560 printf "%s\n" "${1%$_s}"
563 # a combination of realpath + dirname where the realpath of the deepest existing
564 # directory is returned with the rest of the non-existing components appended
565 # and trailing slashes and multiple slashes are removed
566 realdir() {
567 _d="$(striptrsl "$1")"
568 if [ "$_d" = "/" ] || [ -z "$_d" ]; then
569 echo "$_d"
570 return 0
572 _c=""
573 while ! [ -d "$_d" ]; do
574 _c="/$(basename "$_d")$_c"
575 _d="$(dirname "$_d")"
576 [ "$_d" != "/" ] || _c="${_c#/}"
577 done
578 printf "%s%s\n" "$(cd "$_d" && pwd -P)" "$_c"
581 # Use basedir, webroot and cgiroot for easier control of filesystem locations
582 # Wherever we are writing/copying/installing files we use these, but where we
583 # are editing, adding config settings or printing advice we always stick to the
584 # cfg_xxx Config variable versions. These are like a set of DESTDIR variables.
585 # Only the file system directories that could be asynchronously accessed (by
586 # the web server, jobd.pl, taskd.pl or incoming pushes) get these special vars.
587 # The chroot is handled specially and does not need one of these.
588 # We must be careful to allow cgiroot and/or webroot to be under basedir in which
589 # case the prior contents of cgiroot and/or webroot are discarded.
590 rbasedir="$(realdir "$cfg_basedir")"
591 rwebroot="$(realdir "$cfg_webroot")"
592 rwebreporoot=
593 [ -z "$cfg_webreporoot" ] || {
594 # avoid resolving a pre-existing symlink from a previous install
595 rwebreporoot="$(realdir "${cfg_webreporoot%/}_NOSUCHDIR")"
596 rwebreporoot="${rwebreporoot%_NOSUCHDIR}"
598 rcgiroot="$(realdir "$cfg_cgiroot")"
599 case "$rbasedir" in "$rwebroot"/?*)
600 echo "ERROR: invalid Girocco::Config::basedir setting; must not be under webroot" >&2
601 exit 1
602 esac
603 case "$rbasedir" in "$rcgiroot"/?*)
604 echo "ERROR: invalid Girocco::Config::basedir setting; must not be under cgiroot" >&2
605 exit 1
606 esac
607 if [ "$rwebroot" = "$rcgiroot" ]; then
608 echo "ERROR: invalid Girocco::Config::webroot and Girocco::Config::cgiroot settings; must not be the same" >&2
609 exit 1
611 case "$rcgiroot" in "$rwebroot"/?*)
612 echo "ERROR: invalid Girocco::Config::cgiroot setting; must not be under webroot" >&2
613 exit 1
614 esac
615 case "$rwebroot" in "$rcgiroot"/?*)
616 echo "ERROR: invalid Girocco::Config::webroot setting; must not be under cgiroot" >&2
617 exit 1
618 esac
619 if [ -n "$rwebreporoot" ]; then
620 if [ "$rwebreporoot" = "$rwebroot" ]; then
621 echo "ERROR: invalid Girocco::Config::webroot and Girocco::Config::webreporoot settings; must not be the same" >&2
622 exit 1
624 case "$rwebreporoot" in "$rwebroot"/?*);;*)
625 echo "ERROR: invalid Girocco::Config::webreporoot setting; must be under webroot or undef" >&2
626 exit 1
627 esac
629 basedir="$rbasedir-new"
630 case "$rwebroot" in
631 "$rbasedir"/?*)
632 webroot="$basedir${rwebroot#$rbasedir}"
633 webrootsub=1
636 webroot="$rwebroot-new"
637 webrootsub=
639 esac
640 webreporoot=
641 [ -z "$rwebreporoot" ] || webreporoot="$webroot${rwebreporoot#$rwebroot}"
642 case "$rcgiroot" in
643 "$rbasedir"/?*)
644 cgiroot="$basedir${rcgiroot#$rbasedir}"
645 cgirootsub=1
648 cgiroot="$rcgiroot-new"
649 cgirootsub=
651 esac
653 echo "*** Setting up basedir..."
655 chown_make() {
656 if [ "$LOGNAME" = root ] && [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != root ]; then
657 find -H "$@" -user root -exec chown "$SUDO_USER:$(id -gn "$SUDO_USER")" '{}' + 2>/dev/null || :
658 elif [ "$LOGNAME" = root ] && { [ -z "$SUDO_USER" ] || [ "$SUDO_USER" = root ]; }; then
659 echo "*** WARNING: running make as root w/o sudo may leave root-owned: $*"
663 "$MAKE" --no-print-directory --silent apache.conf
664 chown_make apache.conf
665 "$MAKE" --no-print-directory --silent -C src
666 chown_make src
667 rm -fr "$basedir"
668 mkdir -p "$basedir" "$basedir/gitweb" "$basedir/cgi"
669 # make the mtlinesfile with 1000 empty lines
670 yes '' | dd bs=1000 count=1 2>/dev/null >"$basedir/mtlinesfile"
671 chmod a+r "$basedir/mtlinesfile"
672 cp cgi/*.cgi "$basedir/cgi"
673 cp -pR Girocco jobd taskd html jobs toolbox hooks apache.conf shlib.sh bin screen "$basedir"
674 rm -f "$basedir/Girocco/Dumper.pm" # Dumper.pm is only for the install.sh process
675 rm -f "$basedir/Girocco/Validator.pm" # Validator.pm is only for the install.sh process
676 find -H "$basedir" -type l -exec rm -f '{}' +
677 cp -p src/can_user_push src/can_user_push_http src/get_user_uuid src/list_packs src/peek_packet \
678 src/rangecgi src/readlink src/strftime src/throttle src/ulimit512 src/ltsha256 \
679 ezcert.git/CACreateCert cgi/authrequired.cgi cgi/snapshot.cgi \
680 "$basedir/bin"
681 cp -p gitweb/*.sh gitweb/*.perl "$basedir/gitweb"
682 if [ -n "$cfg_httpspushurl" ]; then
683 [ -z "$cfg_pretrustedroot" ] || rm -f "$basedir"/html/rootcert.html
684 else
685 rm -f "$basedir"/html/rootcert.html "$basedir"/html/httpspush.html
687 [ -n "$cfg_mob" ] || rm -f "$basedir"/html/mob.html
689 # Put the frozen Config in place
690 VARLIST="$(get_girocco_config_var_list varonly)" && export VARLIST
691 perl -I"$PWD" -MGirocco::Dumper=FreezeConfig -MScalar::Util=looks_like_number -e '
692 my $usemod = $ARGV[0];
693 my $f = sub { return () unless $_[0] =~ /^(var_[^=\s]+)=(.*)$/;
694 my ($k,$v) = ($1,$2);
695 $v =~ s/([\@\%])/\\$1/gos;
696 $v = "\"".$v."\"" unless substr($v,0,1) eq "\"" || looks_like_number($v);
697 my $e = eval $v;
698 [$k, $e] };
699 my @vars = map({&$f($_)} split(/\n+/, $ENV{VARLIST}));
700 my $s = sub { my $conf = shift;
701 foreach (@vars) {
702 my ($k,$v) = @{$_};
703 eval "\$${conf}::$k=\$v";
706 print FreezeConfig([$usemod,"Girocco::Validator"], undef, $s);
707 ' -- "$GIROCCO_CONF" >"$basedir/Girocco/Config.pm"
708 unset VARLIST
710 # Create symbolic links to selected binaries
711 ln -s "$cfg_git_bin" "$basedir/bin/git"
712 ln -s "$shbin" "$basedir/bin/sh"
713 ln -s "$perlbin" "$basedir/bin/perl"
714 ln -s "$gzipbin" "$basedir/bin/gzip"
715 [ -z "$var_openssl_bin" ] || ln -s "$var_openssl_bin" "$basedir/bin/openssl"
717 echo "*** Preprocessing scripts..."
718 SHBIN="$shbin" && export SHBIN
719 PERLBIN="$perlbin" && export PERLBIN
720 perl -I"$PWD" -M$GIROCCO_CONF -MGirocco::Validator -i -p \
721 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
722 -e 's/^#!.*sh/#!$ENV{SHBIN}/ if $. == 1;' \
723 -e 's/(?<!")\@basedir\@/"$Girocco::Config::basedir"/g;' \
724 -e 's/(?<=")\@basedir\@/$Girocco::Config::basedir/g;' \
725 -e 's/__BASE''DIR__/$Girocco::Config::basedir/g;' \
726 -e 's/\@reporoot\@/"$Girocco::Config::reporoot"/g;' \
727 -e 's/\@cgiroot\@/"$Girocco::Config::cgiroot"/g;' \
728 -e 's/\@shbin\@/"$ENV{SHBIN}"/g;' \
729 -e 's/\@perlbin\@/"$ENV{PERLBIN}"/g;' \
730 -e 's/\@jailreporoot\@/"$Girocco::Config::jailreporoot"/g;' \
731 -e 's/\@chroot\@/"$Girocco::Config::chroot"/g;' \
732 -e 's/\@webadmurl\@/"$Girocco::Config::webadmurl"/g;' \
733 -e 's/\@screen_acl_file\@/"$Girocco::Config::screen_acl_file"/g;' \
734 -e 's/\@mob\@/"$Girocco::Config::mob"/g;' \
735 -e 's/\@autogchack\@/"$Girocco::Config::autogchack"/g;' \
736 -e 's/\@git_server_ua\@/"$Girocco::Config::git_server_ua"/g;' \
737 -e 's/\@defined_git_server_ua\@/defined($Girocco::Config::git_server_ua)/ge;' \
738 -e 's/\@git_no_mmap\@/"$Girocco::Config::git_no_mmap"/g;' \
739 -e 's/\@big_file_threshold\@/"'"$var_big_file_threshold"'"/g;' \
740 -e 's/\@upload_pack_window\@/"'"$var_upload_window"'"/g;' \
741 -e 's/\@fetch_stash_refs\@/"$Girocco::Config::fetch_stash_refs"/g;' \
742 -e 's/\@suppress_git_ssh_logging\@/"$Girocco::Config::suppress_git_ssh_logging"/g;' \
743 -e 's/\@max_file_size512\@/"$Girocco::Config::max_file_size512"/g;' \
744 -e 'close ARGV if eof;' \
745 "$basedir"/jobs/*.sh "$basedir"/jobd/*.sh \
746 "$basedir"/taskd/*.sh "$basedir"/gitweb/*.sh \
747 "$basedir"/shlib.sh "$basedir"/hooks/* \
748 "$basedir"/toolbox/*.sh "$basedir"/toolbox/*.pl \
749 "$basedir"/toolbox/reports/*.sh \
750 "$basedir"/bin/git-* "$basedir"/bin/*.sh \
751 "$basedir"/bin/create-* "$basedir"/bin/update-* \
752 "$basedir"/bin/*.cgi "$basedir"/screen/*
753 perl -I"$PWD" -M$GIROCCO_CONF -MGirocco::Validator -i -p \
754 -e 's/__BASE''DIR__/$Girocco::Config::basedir/g;' \
755 "$basedir"/cgi/*.cgi "$basedir"/gitweb/*.perl \
756 "$basedir"/jobd/*.pl "$basedir"/taskd/*.pl
757 perl -i -p \
758 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
759 -e 'close ARGV if eof;' \
760 "$basedir"/jobd/jobd.pl "$basedir"/taskd/taskd.pl \
761 "$basedir"/bin/sendmail.pl "$basedir"/bin/CACreateCert
762 perl -i -p \
763 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
764 -e 's/^#!.*sh/#!$ENV{SHBIN}/ if $. == 1;' \
765 -e 'close ARGV if eof;' \
766 "$basedir"/bin/format-readme "$basedir/cgi"/*.cgi
767 unset PERLBIN
768 unset SHBIN
770 # Dump all the cfg_ and defined_ variables to shlib_vars.sh
771 get_girocco_config_var_list >"$basedir"/shlib_vars.sh
773 if [ "${cfg_mirror_darcs:-0}" != "0" ]; then
774 echo "*** Setting up darcs-fast-export from girocco-darcs-fast-export.git..."
775 if ! [ -f girocco-darcs-fast-export.git/darcs-fast-export ] ||
776 ! [ -x girocco-darcs-fast-export.git/darcs-fast-export ]; then
777 echo "ERROR: girocco-darcs-fast-export.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
778 exit 1
780 mkdir -p "$basedir"/bin
781 cp girocco-darcs-fast-export.git/darcs-fast-export "$basedir"/bin
784 if [ "${cfg_mirror_hg:-0}" != "0" ]; then
785 echo "*** Setting up hg-fast-export from girocco-hg-fast-export.git..."
786 if ! [ -f girocco-hg-fast-export.git/hg-fast-export.py ] || ! [ -f girocco-hg-fast-export.git/hg2git.py ]; then
787 echo "ERROR: girocco-hg-fast-export.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
788 exit 1
790 mkdir -p "$basedir"/bin
791 cp girocco-hg-fast-export.git/hg-fast-export.py girocco-hg-fast-export.git/hg2git.py "$basedir"/bin
794 echo "*** Setting up markdown from markdown.git..."
795 if ! [ -f markdown.git/Markdown.pl ]; then
796 echo "ERROR: markdown.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
797 exit 1
799 mkdir -p "$basedir"/bin
800 (PERLBIN="$perlbin" && export PERLBIN &&
801 perl -p -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
802 markdown.git/Markdown.pl >"$basedir"/bin/Markdown.pl.$$ &&
803 chmod a+x "$basedir"/bin/Markdown.pl.$$ &&
804 mv -f "$basedir"/bin/Markdown.pl.$$ "$basedir"/bin/Markdown.pl)
805 test $? -eq 0
807 # Some permission sanity on basedir/bin just in case
808 find -H "$basedir"/bin -type f -exec chmod go-w '{}' +
809 chown -R -h "$cfg_mirror_user""$owngroup" "$basedir"/bin
811 if [ -n "$cfg_mirror" ]; then
812 echo "--- Remember to start $cfg_basedir/taskd/taskd.pl"
814 echo "--- Also remember to either start $cfg_basedir/jobd/jobd.pl, or add this"
815 echo "--- to the crontab of $cfg_mirror_user (adjust frequency on number of repos):"
816 echo "*/30 * * * * /usr/bin/nice -n 18 $cfg_basedir/jobd/jobd.pl -q --all-once"
819 echo "*** Setting up repository root..."
820 [ -d "$cfg_reporoot" ] || {
821 mkdir -p "$cfg_reporoot"
822 chown "$cfg_mirror_user""$owngroup" "$cfg_reporoot" ||
823 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_reporoot"
825 [ -z "$cfg_owning_group" ] ||
826 chgrp "$cfg_owning_group" "$cfg_reporoot" || echo "WARNING: Cannot chgrp $cfg_owning_group $cfg_reporoot"
827 chmod 02775 "$cfg_reporoot" || echo "WARNING: Cannot chmod $cfg_reporoot properly"
828 mkdir -p "$cfg_reporoot/_recyclebin" "$cfg_reporoot/_global/hooks" "$cfg_reporoot/_global/empty"
829 chown "$cfg_mirror_user""$owngroup" "$cfg_reporoot/_recyclebin" "$cfg_reporoot/_global" "$cfg_reporoot/_global/hooks" "$cfg_reporoot/_global/empty" ||
830 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_reporoot/{_recyclebin,_global} properly"
831 if [ "$cfg_owning_group" ]; then
832 chgrp "$cfg_owning_group" "$cfg_reporoot/_recyclebin" || echo "WARNING: Cannot chgrp $cfg_owning_group $cfg_reporoot/_recyclebin"
833 chgrp -R "$cfg_owning_group" "$cfg_reporoot/_global" || echo "WARNING: Cannot chgrp -R $cfg_owning_group $cfg_reporoot/_global"
835 chmod 02775 "$cfg_reporoot/_recyclebin" || echo "WARNING: Cannot chmod $cfg_reporoot/_recyclebin properly"
836 chmod 00755 "$cfg_reporoot/_global" "$cfg_reporoot/_global/hooks" "$cfg_reporoot/_global/empty" || echo "WARNING: Cannot chmod $cfg_reporoot/_global properly"
839 usejail=
840 [ "${cfg_disable_jailsetup:-0}" != "0" ] || [ "${cfg_chrooted:-0}" = "0" ] || usejail=1
841 if [ -n "$usejail" ]; then
842 echo "*** Setting up chroot jail for pushing..."
843 if [ -n "$isroot" ]; then
844 # jailsetup may install things from $cfg_basedir/bin into the
845 # chroot so we do a mini-update of just that portion now
846 mkdir -p "$cfg_basedir"
847 rm -rf "$cfg_basedir/bin-new"
848 cp -pR "$basedir/bin" "$cfg_basedir/bin-new" >/dev/null 2>&1
849 rm -rf "$cfg_basedir/bin-old"
850 quick_move "$cfg_basedir/bin-new" "$cfg_basedir/bin" "$cfg_basedir/bin-old"
851 rm -rf "$cfg_basedir/bin-old"
852 if [ -n "$sh_extra_chroot_installs" ]; then
853 GIROCCO_CHROOT_EXTRA_INSTALLS="$sh_extra_chroot_installs"
854 export GIROCCO_CHROOT_EXTRA_INSTALLS
856 ./jailsetup.sh
857 unset GIROCCO_CHROOT_EXTRA_INSTALLS
858 else
859 echo "WARNING: Skipping jail setup, not root"
864 echo "*** Setting up jail configuration (project database)..."
865 [ -n "$usejail" ] && [ -n "$isroot" ] || ./jailsetup.sh dbonly
866 mkdir -p "$cfg_chroot" "$cfg_chroot/etc"
867 touch "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group"
868 chown "$cfg_mirror_user""$owngroup" "$cfg_chroot/etc" ||
869 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup $cfg_chroot/etc"
870 if [ -n "$usejail" ]; then
871 chown "$cfg_cgi_user""$owngroup" "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
872 echo "WARNING: Cannot chown $cfg_cgi_user$owngroup the etc/passwd and/or etc/group files"
873 else
874 # If a chroot jail is not in use, sudo privileges are neither expected nor required
875 # which means it will not be possible to change the owner of the passwd and group
876 # files if it differs from the mirror user. And that's okay, provided the group
877 # can still be set correctly to the owning group. But, just in case we're running
878 # as root, go ahead and set the owner to the mirror user.
879 chown "$cfg_mirror_user""$owngroup" "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
880 echo "WARNING: Cannot chown $cfg_mirror_user$owngroup the etc/passwd and/or etc/group files"
882 chmod g+w "$cfg_chroot/etc/passwd" "$cfg_chroot/etc/group" ||
883 echo "WARNING: Cannot chmod g+w the etc/passwd and/or etc/group files"
884 chmod 02775 "$cfg_chroot/etc" || echo "WARNING: Cannot chmod 02775 $cfg_chroot/etc"
887 echo "*** Setting up global hook scripts..."
888 # It is absolutely CRUCIAL that hook script replacements are done atomically!
889 # Otherwise an incoming push might slip in and fail to run the hook script!
890 # The underlying rename(2) function call provides this and mv will use it.
891 # First add hook scripts
892 hooks="pre-auto-gc pre-receive post-commit post-receive update"
893 for hook in $hooks; do
894 cat "$basedir/hooks/$hook" >"$cfg_reporoot/_global/hooks/$hook.$$"
895 chown "$cfg_mirror_user""$owngroup" "$cfg_reporoot/_global/hooks/$hook.$$" ||
896 echo "WARNING: Cannot chown $cfg_reporoot/_global/hooks/$hook"
897 chmod 0755 "$cfg_reporoot/_global/hooks/$hook.$$"
898 mv -f "$cfg_reporoot/_global/hooks/$hook.$$" "$cfg_reporoot/_global/hooks/$hook"
899 done
900 # Then remove any hook scripts that do not belong
901 for hook in "$cfg_reporoot/_global/hooks"/*; do
902 hook="${hook##*/}"
903 [ -f "$cfg_reporoot/_global/hooks/$hook" ] || continue
904 case " $hooks " in *" $hook "*);;*)
905 rm -f "$cfg_reporoot/_global/hooks/$hook" ||
906 echo "WARNING: Cannot remove extraneous $cfg_reporoot/_global/hooks/$hook"
907 esac
908 done
911 echo "*** Setting up gitweb from git.git..."
912 if ! [ -f git.git/Makefile ]; then
913 echo "ERROR: git.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
914 exit 1
917 # We do not wholesale replace either webroot or cgiroot unless they are under
918 # basedir so if they exist and are not we make a copy to start working on them.
919 # We make a copy using -p which can result in some warnings so we suppress
920 # error output as it's of no consequence in this case.
921 rm -rf "$webroot" "$cgiroot"
922 [ -n "$webrootsub" ] || ! [ -d "$rwebroot" ] || cp -pR "$rwebroot" "$webroot" >/dev/null 2>&1 || :
923 [ -n "$cgirootsub" ] || ! [ -d "$rcgiroot" ] || cp -pR "$rcgiroot" "$cgiroot" >/dev/null 2>&1 || :
924 mkdir -p "$webroot" "$cgiroot"
927 cd git.git &&
928 "$MAKE" --no-print-directory --silent NO_SUBDIR=: bindir="$(dirname "$cfg_git_bin")" \
929 GITWEB_CONFIG_COMMON="" GITWEB_CONFIG_SYSTEM="" \
930 GITWEB_CONFIG="$cfg_basedir/gitweb/gitweb_config.perl" SHELL_PATH="$shbin" gitweb &&
931 chown_make gitweb &&
932 PERLBIN="$perlbin" && export PERLBIN &&
933 perl -p -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
934 -e 's/^(\s*use\s+warnings\s*;.*)$/#$1/;' gitweb/gitweb.cgi >"$cgiroot"/gitweb.cgi.$$ &&
935 chmod a+x "$cgiroot"/gitweb.cgi.$$ &&
936 chown_make "$cgiroot"/gitweb.cgi.$$ &&
937 mv -f "$cgiroot"/gitweb.cgi.$$ "$cgiroot"/gitweb.cgi &&
938 cp gitweb/static/*.png gitweb/static/*.css gitweb/static/*.js "$webroot"
940 test $? -eq 0
943 echo "*** Setting up git-browser from git-browser.git..."
944 if ! [ -f git-browser.git/git-browser.cgi ]; then
945 echo "ERROR: git-browser.git is not checked out! Did you _REALLY_ read INSTALL?" >&2
946 exit 1
948 mkdir -p "$webroot"/git-browser "$cgiroot"
950 cd git-browser.git &&
951 CFG="$cfg_basedir/gitweb/git-browser.conf" && export CFG &&
952 PERLBIN="$perlbin" && export PERLBIN && perl -p \
953 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
954 -e 's/"git-browser\.conf"/"$ENV{"CFG"}"/' git-browser.cgi >"$cgiroot"/git-browser.cgi.$$ &&
955 chmod a+x "$cgiroot"/git-browser.cgi.$$ &&
956 chown_make "$cgiroot"/git-browser.cgi.$$ &&
957 perl -p \
958 -e 's/^#!.*perl/#!$ENV{PERLBIN}/ if $. == 1;' \
959 -e 's/"git-browser\.conf"/"$ENV{"CFG"}"/' git-diff.cgi >"$cgiroot"/git-diff.cgi.$$ &&
960 chmod a+x "$cgiroot"/git-diff.cgi.$$ &&
961 chown_make "$cgiroot"/git-diff.cgi.$$ &&
962 mv -f "$cgiroot"/git-browser.cgi.$$ "$cgiroot"/git-browser.cgi &&
963 mv -f "$cgiroot"/git-diff.cgi.$$ "$cgiroot"/git-diff.cgi &&
964 for h in *.html; do
965 [ "$h" != "index.html" ] || continue
966 if [ "$h" = "by-commit.html" ] || [ "$h" = "by-date.html" ]; then
967 FAVLINE='<link rel="shortcut icon" href="/git-favicon.png" type="image/png" />' &&
968 export FAVLINE && perl -p -e 'print "$ENV{FAVLINE}\n" if m{</head>};' "$h" \
969 >"$webroot/git-browser/$h.$$" &&
970 chmod a+r "$webroot/git-browser/$h.$$" &&
971 mv -f "$webroot/git-browser/$h.$$" "$webroot/git-browser/$h"
972 else
973 cp -p "$h" "$webroot/git-browser/"
975 done
976 cp -pR *.js *.css js.lib "$webroot/git-browser/" &&
977 cp -pR JSON "$cgiroot/"
979 test $? -eq 0
980 gitwebabs="$cfg_gitweburl"
981 case "$gitwebabs" in "http://"[!/]*|"https://"[!/]*)
982 gitwebabs="${gitwebabs#*://}"
983 case "$gitwebabs" in
984 *"/"*) gitwebabs="/${gitwebabs#*/}";;
985 *) gitwebabs="";;
986 esac
987 esac
988 case "$gitwebabs" in */);;*) gitwebabs="$gitwebabs/"; esac
989 cat >"$basedir/gitweb"/git-browser.conf.$$ <<-EOT
990 gitbin: $cfg_git_bin
991 gitweb: $gitwebabs
992 warehouse: $cfg_reporoot
993 doconfig: $cfg_basedir/gitweb/gitbrowser_config.perl
995 chown_make "$basedir/gitweb"/git-browser.conf.$$
996 mv -f "$basedir/gitweb"/git-browser.conf.$$ "$basedir/gitweb"/git-browser.conf
997 esctitle="$(printf '%s\n' "$cfg_title" | LC_ALL=C sed 's/\\/\\\\/g;s/"/\\"/g;')" || :
998 cat >"$webroot"/git-browser/GitConfig.js.$$ <<-EOT
999 cfg_gitweb_url="$cfg_gitweburl/"
1000 cfg_browsercgi_url="$cfg_webadmurl/git-browser.cgi"
1001 cfg_home_url="$cfg_gitweburl/%n"
1002 cfg_home_text="summary"
1003 cfg_bycommit_title="$esctitle - %n/graphiclog1"
1004 cfg_bydate_title="$esctitle - %n/graphiclog2"
1006 chown_make "$webroot"/git-browser/GitConfig.js.$$
1007 mv -f "$webroot"/git-browser/GitConfig.js.$$ "$webroot"/git-browser/GitConfig.js
1010 echo "*** Setting up our part of the website..."
1011 mkdir -p "$webroot" "$cgiroot"
1012 cp "$basedir"/bin/snapshot.cgi "$basedir/cgi"
1013 cp "$basedir"/bin/authrequired.cgi "$basedir/cgi"
1014 [ -n "$cfg_httpspushurl" ] || rm -f "$basedir/cgi"/usercert.cgi "$cgiroot"/usercert.cgi
1015 cp "$basedir/cgi"/*.cgi "$cgiroot"
1016 rm -rf "$basedir/cgi"
1017 [ -z "$webreporoot" ] || { rm -f "$webreporoot" && ln -s "$cfg_reporoot" "$webreporoot"; }
1018 if [ -z "$cfg_httpspushurl" ] || [ -n "$cfg_pretrustedroot" ]; then
1019 grep -v 'rootcert[.]html' gitweb/indextext.html >"$basedir/gitweb/indextext.html"
1020 else
1021 cp gitweb/indextext.html "$basedir/gitweb"
1023 mv "$basedir"/html/*.css "$basedir"/html/*.js "$webroot"
1024 cp mootools.js "$webroot"
1025 cp htaccess "$webroot/.htaccess"
1026 cp cgi/htaccess "$cgiroot/.htaccess"
1027 cp git-favicon.ico "$webroot/favicon.ico"
1028 cp robots.txt "$webroot"
1029 cat gitweb/gitweb.css >>"$webroot"/gitweb.css
1032 if [ -n "$cfg_httpspushurl" ]; then
1033 echo "*** Setting up SSL certificates..."
1034 openssl="${var_openssl_bin:-openssl}"
1035 createcert() { PATH="$basedir/bin:$PATH" "$basedir/bin/CACreateCert" "$@"; }
1036 bits=2048
1037 if [ "$cfg_rsakeylength" -gt "$bits" ] 2>/dev/null; then
1038 bits="$cfg_rsakeylength"
1040 mkdir -p "$cfg_certsdir"
1041 [ -d "$cfg_certsdir" ]
1042 wwwcertcn=
1043 if [ -e "$cfg_certsdir/girocco_www_crt.pem" ]; then
1044 wwwcertcn="$(
1045 "$openssl" x509 -in "$cfg_certsdir/girocco_www_crt.pem" -noout -subject |
1046 sed -e 's,[^/]*,,'
1049 wwwcertdns=
1050 if [ -n "$cfg_wwwcertaltnames" ]; then
1051 for dnsopt in $cfg_wwwcertaltnames; do
1052 wwwcertdns="${wwwcertdns:+$wwwcertdns }--dns $dnsopt"
1053 done
1055 wwwcertdnsfile=
1056 if [ -r "$cfg_certsdir/girocco_www_crt.dns" ]; then
1057 wwwcertdnsfile="$(cat "$cfg_certsdir/girocco_www_crt.dns")"
1059 needroot=
1060 [ -e "$cfg_certsdir/girocco_client_crt.pem" ] &&
1061 [ -e "$cfg_certsdir/girocco_client_key.pem" ] &&
1062 [ -e "$cfg_certsdir/girocco_www_key.pem" ] &&
1063 [ -e "$cfg_certsdir/girocco_www_crt.pem" ] && [ "$wwwcertcn" = "/CN=$cfg_httpsdnsname" ] &&
1064 [ -e "$cfg_certsdir/girocco_root_crt.pem" ] || needroot=1
1065 if [ -n "$needroot" ] && ! [ -e "$cfg_certsdir/girocco_root_key.pem" ]; then
1066 rm -f "$cfg_certsdir/girocco_root_crt.pem" "$cfg_certsdir/girocco_root_key.pem"
1067 umask 0077
1068 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_root_key.pem" $bits
1069 chmod 0600 "$cfg_certsdir/girocco_root_key.pem"
1070 rm -f "$cfg_certsdir/girocco_root_crt.pem"
1071 umask 0022
1072 echo "Created new root key"
1074 if ! [ -e "$cfg_certsdir/girocco_root_crt.pem" ]; then
1075 createcert --root --key "$cfg_certsdir/girocco_root_key.pem" \
1076 --out "$cfg_certsdir/girocco_root_crt.pem" "girocco $cfg_nickname root certificate"
1077 rm -f "$cfg_certsdir/girocco_www_crt.pem" "$cfg_certsdir/girocco_www_chain.pem" \
1078 "$cfg_certsdir/girocco_www_fullchain.pem"
1079 rm -f "$cfg_certsdir/girocco_client_crt.pem" "$cfg_certsdir/girocco_client_suffix.pem"
1080 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
1081 rm -f "$cfg_chroot/etc/sshcerts"/*.pem
1082 echo "Created new root certificate"
1084 if ! [ -e "$cfg_certsdir/girocco_www_key.pem" ]; then
1085 umask 0077
1086 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_www_key.pem" $bits
1087 chmod 0600 "$cfg_certsdir/girocco_www_key.pem"
1088 rm -f "$cfg_certsdir/girocco_www_crt.pem"
1089 umask 0022
1090 echo "Created new www key"
1092 if ! [ -e "$cfg_certsdir/girocco_www_crt.pem" ] ||
1093 [ "$wwwcertcn" != "/CN=$cfg_httpsdnsname" ] || [ "$wwwcertdns" != "$wwwcertdnsfile" ]; then
1094 "$openssl" rsa -in "$cfg_certsdir/girocco_www_key.pem" -pubout |
1095 createcert --server --key "$cfg_certsdir/girocco_root_key.pem" \
1096 --cert "$cfg_certsdir/girocco_root_crt.pem" $wwwcertdns \
1097 --out "$cfg_certsdir/girocco_www_crt.pem" "$cfg_httpsdnsname"
1098 printf '%s\n' "$wwwcertdns" >"$cfg_certsdir/girocco_www_crt.dns"
1099 rm -f "$cfg_certsdir/girocco_www_fullchain.pem"
1100 echo "Created www certificate"
1102 if ! [ -e "$cfg_certsdir/girocco_www_chain.pem" ]; then
1103 cat "$cfg_certsdir/girocco_root_crt.pem" >"$cfg_certsdir/girocco_www_chain.pem"
1104 echo "Created www certificate chain file"
1106 if ! [ -e "$cfg_certsdir/girocco_www_fullchain.pem" ]; then
1107 cat "$cfg_certsdir/girocco_www_crt.pem" >"$cfg_certsdir/girocco_www_fullchain.pem"
1108 cat "$cfg_certsdir/girocco_www_chain.pem" >>"$cfg_certsdir/girocco_www_fullchain.pem"
1109 echo "Created www certificate full chain file"
1111 if ! [ -e "$cfg_certsdir/girocco_client_key.pem" ]; then
1112 umask 0037
1113 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_client_key.pem" $bits
1114 chmod 0640 "$cfg_certsdir/girocco_client_key.pem"
1115 rm -f "$cfg_certsdir/girocco_client_crt.pem"
1116 umask 0022
1117 echo "Created new client key"
1119 if ! [ -e "$cfg_certsdir/girocco_client_crt.pem" ]; then
1120 "$openssl" rsa -in "$cfg_certsdir/girocco_client_key.pem" -pubout |
1121 createcert --subca --key "$cfg_certsdir/girocco_root_key.pem" \
1122 --cert "$cfg_certsdir/girocco_root_crt.pem" \
1123 --out "$cfg_certsdir/girocco_client_crt.pem" "girocco $cfg_nickname client authority"
1124 rm -f "$cfg_certsdir/girocco_client_suffix.pem"
1125 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
1126 rm -f "$cfg_chroot/etc/sshcerts"/*.pem
1127 echo "Created client certificate"
1129 if ! [ -e "$cfg_certsdir/girocco_client_suffix.pem" ]; then
1130 cat "$cfg_certsdir/girocco_client_crt.pem" >"$cfg_certsdir/girocco_client_suffix.pem"
1131 echo "Created client certificate suffix file"
1133 if [ -z "$cfg_pretrustedroot" ]; then
1134 cat "$cfg_rootcert" >"$webroot/${cfg_nickname}_root_cert.pem"
1135 else
1136 rm -f "$webroot/${cfg_nickname}_root_cert.pem"
1138 if [ -n "$cfg_mob" ]; then
1139 if ! [ -e "$cfg_certsdir/girocco_mob_user_key.pem" ]; then
1140 "$openssl" genrsa -f4 -out "$cfg_certsdir/girocco_mob_user_key.pem" $bits
1141 chmod 0644 "$cfg_certsdir/girocco_mob_user_key.pem"
1142 rm -f "$cfg_certsdir/girocco_mob_user_crt.pem"
1143 echo "Created new mob user key"
1145 if ! [ -e "$cfg_certsdir/girocco_mob_user_crt.pem" ]; then
1146 "$openssl" rsa -in "$cfg_mobuserkey" -pubout |
1147 createcert --client --key "$cfg_clientkey" \
1148 --cert "$cfg_clientcert" \
1149 --out "$cfg_certsdir/girocco_mob_user_crt.pem" 'mob'
1150 echo "Created mob user client certificate"
1152 cat "$cfg_mobuserkey" >"$webroot/${cfg_nickname}_mob_key.pem"
1153 cat "$cfg_mobusercert" "$cfg_clientcertsuffix" >"$webroot/${cfg_nickname}_mob_user.pem"
1154 else
1155 rm -f "$webroot/${cfg_nickname}_mob_key.pem" "$webroot/${cfg_nickname}_mob_user.pem"
1157 else
1158 rm -f "$webroot/${cfg_nickname}_root_cert.pem"
1159 rm -f "$webroot/${cfg_nickname}_mob_key.pem" "$webroot/${cfg_nickname}_mob_user.pem"
1163 echo "*** Processing website html templates..."
1164 rm -f "$cgiroot/html.cgi"
1165 rm -rf "$cgiroot/html"
1166 mkdir -p "$cgiroot/html"
1167 for tf in "$basedir/html"/*.html; do
1168 tfb="${tf##*/}"
1169 "$perlbin" -I"$basedir" cgi/html.cgi "$webroot" "$tfb" "$basedir" >"$cgiroot/html/$tfb"
1170 rm -f "$tf"
1171 done
1173 echo "*** Formatting markdown documentation..."
1174 mkdir -p "$cgiroot/html/gfm"
1175 for d in basics.md syntax.md; do
1177 cat <<-HEADER
1178 <!DOCTYPE html>
1179 <html xmlns="http://www.w3.org/1999/xhtml">
1180 <head>
1181 <meta charset="utf-8" />
1182 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
1183 <title>$d</title>
1184 </head>
1185 <body><pre>
1186 HEADER
1187 <"markdown.git/$d" LC_ALL=C sed -e '/\[[Ll]icense\]/d' \
1188 -e 's, \([a-z][a-z]*\)\.md, \1.md.html,' \
1189 -e 's/ by adding `.md` to the URL//' \
1190 -e 's/&/\&amp;/g' -e 's/</\&lt;/g' <"markdown.git/$d"
1191 cat <<-FOOTER
1192 </pre></body>
1193 </html>
1194 FOOTER
1195 } >"$cgiroot/html/gfm/$d.html"
1197 title="Markdown: $(echo "${d%.md}" | "$perlbin" -pe '$_=ucfirst')"
1198 gwfpath="$cfg_gitwebfiles"
1199 case "$gwfpath" in *"//"*)
1200 case "$gwfpath" in *"/");;*) gwfpath="$gwfpath/"; esac
1201 gwfpath="${gwfpath#*//}"; gwfpath="${gwfpath#*/}"
1202 esac
1203 case "$gwfpath" in "/"*);;*) gwfpath="/$gwfpath"; esac
1204 gwfpath="${gwfpath%/}"
1205 cat <<-HEADER
1206 <!DOCTYPE html>
1207 <html xmlns="http://www.w3.org/1999/xhtml">
1208 <head>
1209 <meta charset="utf-8" />
1210 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
1211 <title>$title</title>
1212 <link rel="stylesheet" type="text/css" href="$gwfpath/gitweb.css" />
1213 <link rel="stylesheet" type="text/css" href="$gwfpath/girocco.css" />
1214 <link rel="shortcut icon" href="$gwfpath/git-favicon.png" type="image/png" />
1215 </head>
1216 <body style="text-align:center">
1217 <div class="readme" style="overflow:inherit;display:inline-block;text-align:left;max-width:42pc">
1218 HEADER
1219 <"markdown.git/$d" LC_ALL=C sed -e '/\[[Ll]icense\]/d' \
1220 -e 's, \([a-z][a-z]*\)\.md, \1.md.html,' \
1221 -e 's/ by adding `.md` to the URL//' |
1222 "$perlbin" "markdown.git/Markdown.pl"
1223 cat <<-FOOTER
1224 </div>
1225 </body>
1226 </html>
1227 FOOTER
1228 } >"$cgiroot/html/gfm/${d%.md}.html"
1229 done
1232 echo "*** Finalizing permissions and moving into place..."
1233 chown -R -h "$cfg_mirror_user""$owngroup" "$basedir" "$webroot" "$cgiroot"
1234 [ -z "$cfg_httpspushurl" ] || chown -R -h "$cfg_mirror_user""$owngroup" "$cfg_certsdir"
1236 # This should always be the very last thing install.sh does
1237 rm -rf "$rbasedir-old" "$rwebroot-old" "$rcgiroot-old"
1238 quick_move "$basedir" "$rbasedir" "$rbasedir-old"
1239 [ -n "$webrootsub" ] || quick_move "$webroot" "$rwebroot" "$rwebroot-old"
1240 [ -n "$cgirootsub" ] || quick_move "$cgiroot" "$rcgiroot" "$rcgiroot-old"
1241 rm -rf "$rbasedir-old" "$rwebroot-old" "$rcgiroot-old"
1242 echo "--- Update hooks and config with $cfg_basedir/toolbox/update-all-projects.sh"
1243 ! [ -S "$cfg_chroot/etc/taskd.socket" ] || {
1244 echo "*** Requesting graceful restart of running taskd (and, if running, jobd)..."
1245 touch "$cfg_chroot/etc/taskd.restart"
1246 chown_make "$cfg_chroot/etc/taskd.restart"
1247 trap ':' PIPE
1248 echo "nop" | nc_openbsd -w 5 -U "$cfg_chroot/etc/taskd.socket" || :
1249 trap - PIPE