#!/bin/sh
# Merge service tiers into /etc/runit/runsvdir/merged additively so longruns
# started in 01-core stay supervised when 02-base/default are added.
# Called from stage 2 after the initial tier is already active (or merged).

set -e

MERGED=/etc/runit/runsvdir/merged
initial=${1:-default}

waves_enabled=0
if [ -f /etc/runit/runsvdir-waves.enabled ] || [ -f /etc/runit/native.boot.run ]; then
	waves_enabled=1
fi
[ "$waves_enabled" = 1 ] || exit 0

mkdir -p "$MERGED"

merge_tier() {
	_tier=$1
	_dir=/etc/runit/runsvdir/$_tier
	[ -d "$_dir" ] || return 0
	for _link in "$_dir"/*; do
		[ -L "$_link" ] || continue
		_name=${_link##*/}
		case "$_name" in
			.*) continue ;;
		esac
		if [ -e "$MERGED/$_name" ] || [ -L "$MERGED/$_name" ]; then
			continue
		fi
		if [ -d "/etc/sv/$_name" ]; then
			ln -sf "/etc/sv/$_name" "$MERGED/$_name"
		else
			ln -sf "$(readlink "$_link")" "$MERGED/$_name"
		fi
	done
	unset _tier _dir _link _name
}

trigger_rescan() {
	cur=
	if [ -r /etc/runit/runsvdir/current ]; then
		cur=$(readlink -f /etc/runit/runsvdir/current 2>/dev/null) || true
	fi
	if [ -n "$cur" ] && [ -d "$cur" ]; then
		: > "$cur/.forced-rescan" 2>/dev/null || true
	fi
}

ensure_merged_current() {
	cur=
	if [ -r /etc/runit/runsvdir/current ]; then
		cur=$(readlink -f /etc/runit/runsvdir/current 2>/dev/null) || true
	fi
	case "$cur" in
		*/merged) return 0 ;;
	esac
	runsvchdir merged || return 1
	trigger_rescan
}

# Merge every tier that has symlinks; wait on each tier's .needs after merge.
for tier in 01-core 02-base default; do
	dir=/etc/runit/runsvdir/$tier
	[ -d "$dir" ] || continue
	if [ -z "$(find "$dir" -maxdepth 1 -type l -print -quit 2>/dev/null)" ]; then
		continue
	fi
	merge_tier "$tier"
	ensure_merged_current || true
	sleep 1
	/lib/runit/wait-tier "$tier" || true
done

unset tier dir initial MERGED
exit 0
