#!/bin/sh
set -eu

SUPERVISE_PREFIX=/var/run/runit/supervise.

is_service() {
	[ -x "$1/run" ]
}

create_services() {
	local target
	for target in "$@"; do
		if [ -r "${target}" ]; then
			echo "svclone: ${target} already exists" 1>&2
			return 1
		fi
		mkdir -p "${target}/log"
		# shellcheck disable=SC2016
		printf '#!/bin/sh\n[ -r conf ] && . ./conf\nexec %s ${OPTS}\n' "${target##*/}" >"${target}/run"
		printf '#!/bin/sh\nexec logger -t %s\n' "${target##*/}" >"${target}/log/run"
		chmod 755 "${target}/run" "${target}/log/run"
		ln -sf "${SUPERVISE_PREFIX}$(uuidgen)" "${target}/supervise"
		ln -sf "${SUPERVISE_PREFIX}$(uuidgen)" "${target}/log/supervise"
	done
}

clone_services() {
	local err
	local source
	local target
	source="$1"
	shift
	if ! is_service "${source}"; then
		echo "svclone: ${source} is not a service directory" 1>&2
		return 1
	fi
	err=0
	for target in "$@"; do
		if [ -r "${target}" ]; then
			echo "svclone: ${target} already exists" 1>&2
			err=1
		fi
		mkdir -p "${target}"
		tar -C "${source}" --exclude supervise --exclude '*~' -Lcf - . | tar -C "${target}" -xf -
		find -d "${target}" -type d | while read -r file; do
			if [ -x "${file}/run" ]; then
				ln -sf "${SUPERVISE_PREFIX}$(uuidgen)" "${file}/supervise"
			fi
		done
	done
	return ${err}
}

regen_supervise() {
	local err
	local target
	err=0
	for target in "$@"; do
		if ! is_service "${target}"; then
			echo "svclone: ${target} is not a service directory" 1>&2
			err=1
		fi
		find -d "${target}" -type d | while read -r file; do
			if [ -x "${file}/run" ]; then
				ln -sf "${SUPERVISE_PREFIX}$(uuidgen)" "${file}/supervise"
			fi
		done
	done
	return ${err}
}

remove_supervise() {
	local err
	local target
	err=0
	for target in "$@"; do
		if ! is_service "${target}"; then
			echo "svclone: ${target} is not a service directory" 1>&2
			err=1
		fi
		find -d "${target}" -name supervise -and \( -type l -or -type d \) |
			while read -r file; do
				rm -rf "${file}"
			done
	done
	return ${err}
}

usage() {
	echo "usage: svclone [-crsu] svdir ..." 1>&2
	echo "       svclone [-u] source target ..." 1>&2
	return 64
}

main() {
	local cflag
	local rflag
	local sflag
	cflag=
	rflag=
	sflag=
	tflag=
	while getopts ":crstu" arg; do
		case ${arg} in
		c) cflag=1 ;;
		r) rflag=1 ;;
		s) sflag=1 ;;
		t) tflag=1 ;;
		u) SUPERVISE_PREFIX="/var/run/runit/users/${USER}/supervise." ;;
		*) usage ;;
		esac
	done
	shift $((OPTIND - 1))

	if [ -n "${cflag}" ]; then
		create_services "$@"
	elif [ -n "${sflag}" ]; then
		remove_supervise "$@"
		regen_supervise "$@"
	elif [ -n "${rflag}" ]; then
		remove_supervise "$@"
	elif [ $# -ge 2 ]; then
		if [ -n "${tflag}" ]; then
			source="/usr/local/etc/sv/$1-template"
		else
			source="$1"
		fi
		shift 1
		clone_services "${source}" "$@"
	else
		usage
	fi
}

main "$@"
