#!/bin/bash

# Copyright 2019 eomanis
# 
# This file is part of borgit.
# 
# borgit is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
# 
# borgit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with borgit.  If not, see <http://www.gnu.org/licenses/>.

set -o nounset
set -o noclobber
set -o errexit
shopt -qs inherit_errexit

getVersion () {
	"$borgit" "--version" && return $? || return $?
}

printHelp () {
	echo -n "borgem "; getVersion
	echo -n \
"Same-repository multi-job frontend for borgit

Usage:
  borgem
    [-r|--repo-config repoConfigurationFile]
    [-s|--archive-suffix archiveSuffix]
    [--]
    jobConfigurationFile [jobConfigurationFile...]
  borgem --help
  borgem --version

E.g.
  borgem --repo-config repos/system-online -- \\
  jobs/ftp-server jobs/web-server jobs/etc

Calls borgit multiple times, once for every given job configuration
file; all borgit calls use the same repository configuration and archive
suffix.

The default archive suffix is the current UTC date in ISO 8601
format with a leading dot. Example:
  .2019-10-30

The --repo-config option may be given multiple times if the repository
options are distributed over more than a single repository
configuration file.
"
}

# Find borgit
borgit="$(dirname "$0")/borgit"

# Make sure borgit is available
if ! type "$borgit" &> /dev/null; then
	echo "ERROR  (borgem) Companion application \"$borgit\" is not available or not executable" >&2
	exit 1
fi

# Catch missing arguments
if test $# -eq 0; then
	printHelp
	exit 1
fi

# Catch --help as single argument
if test $# -eq 1 && test "$1" = "--help"; then
	printHelp
	exit 0
fi

# Catch --version as single argument
if test $# -eq 1 && test "$1" = "--version"; then
	getVersion
	exit 0
fi

# Set internal global variables
failedJobConfigs=()

# Set defaults
archiveSuffix=".$(date --utc --iso-8601)"
repoConfigs=()
jobConfigs=()

# Parse the arguments
trailingArgs=false
while test $# -gt 0; do
	if ! $trailingArgs && test "$1" = "--"; then
		trailingArgs=true; shift
	elif $trailingArgs || ! { test ${#1} -ge 1 && test "${1:0:1}" = "-"; }; then
		# Trailing arguments section reached, or the argument does not
		# start with "-": Must be a job config
		jobConfigs+=( "$1" ); shift
	elif test "$1" = "-r" || test "$1" = "--repo-config"; then
		test $# -ge 2 || { echo "ERROR  (borgem) No value given for argument \"$1\"" >&2; exit 1; }
		shift
		repoConfigs+=( "$1" ); shift
	elif test "$1" = "-s" || test "$1" = "--archive-suffix"; then
		test $# -ge 2 || { echo "ERROR  (borgem) No value given for argument \"$1\"" >&2; exit 1; }
		shift
		archiveSuffix="$1"; shift
	else
		echo "ERROR  (borgem) Unknown argument \"$1\"" >&2; exit 1
	fi
done
unset trailingArgs

# Warn and exit if no backup jobs have been given
if test ${#jobConfigs[@]} -eq 0; then
	echo " WARN  (borgem) No backup jobs specified, not doing anything" >&2
	exit 0
fi

# Print a summary
echo -n " INFO  (borgem) This is borgem " >&2; getVersion >&2
if test ${#repoConfigs[@]} -ge 1; then
	echo -n " INFO  (borgem) Repository configuration files:" >&2
	for repoConfig in "${repoConfigs[@]}"; do
		echo -n " \"$repoConfig\"" >&2
	done
	echo "" >&2
else
	echo " INFO  (borgem) No repository configuration files specified" >&2
fi
echo " INFO  (borgem) Borg archive suffix: \"$archiveSuffix\"" >&2
echo " INFO  (borgem) Running ${#jobConfigs[@]} backup job(s)" >&2

# Sequentially run the given backup jobs
for jobConfig in "${jobConfigs[@]}"; do
	exitCode=0

	"$borgit" --archive-suffix "$archiveSuffix" -- "${repoConfigs[@]}" "$jobConfig" || exitCode=$?
	if test "$exitCode" -ne 0; then
		failedJobConfigs+=( "$jobConfig" )
		echo "ERROR  (borgem) Job \"$jobConfig\": \"$borgit\" returned with exit code $exitCode" >&2
	fi
done

# Print a result
if test "${#failedJobConfigs[@]}" -gt 0; then
	echo -n " WARN  (borgem) ${#failedJobConfigs[@]} of ${#jobConfigs[@]} backup job(s) failed:" >&2
	for failedJobConfig in "${failedJobConfigs[@]}"; do
		echo -n " \"$failedJobConfig\"" >&2
	done
	echo "" >&2
	exit 2
fi
echo " INFO  (borgem) All backup jobs have been run without errors" >&2