Files
BorgBackupWrapper/borg.backup.functions.verify.sh
Clemens Schwaighofer 943d1c551e Stop trapping errors und unset enviromant vars
On error just print error, but do not reset env vars, if this is done on verify error the init afterwards will store all settings in the wrong path
2025-12-03 12:38:01 +09:00

475 lines
18 KiB
Bash

#!/usr/bin/env bash
# allow variables in printf format string
# shellcheck disable=SC2059
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
fi;
# start time in seconds
START=$(date +'%s');
# set init date, or today if not file is set
BACKUP_INIT_DATE='';
if [ -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
BACKUP_INIT_DATE=$(printf '%(%c)T' "$(cat "${BASE_FOLDER}${BACKUP_INIT_FILE}" 2>/dev/null)");
fi;
# start logging from here
exec &> >(tee -a "${LOG}");
printf "${PRINTF_MASTER_BLOCK}" "START" "$(date +'%F %T')" "${MODULE}";
# show info for version always
printf "${PRINTF_INFO_STRING}" "Script version" "${VERSION}";
# show type
printf "${PRINTF_INFO_STRING}" "Backup module" "${MODULE}";
printf "${PRINTF_INFO_STRING}" "Module version" "${MODULE_VERSION}";
# borg version
printf "${PRINTF_INFO_STRING}" "Borg version" "${BORG_VERSION}";
# host name
printf "${PRINTF_INFO_STRING}" "Hostname" "${HOSTNAME}";
# show base folder always
printf "${PRINTF_INFO_STRING}" "Base folder" "${BASE_FOLDER}";
# Module init date (when init file was writen)
printf "${PRINTF_INFO_STRING}" "Module init date" "${BACKUP_INIT_DATE}";
# print last compact date if positive integer
# only if borg > 1.2
if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ "${COMPACT_INTERVAL##*[!0-9]*}" ]; then
printf "${PRINTF_INFO_STRING}" "Module compact interval" "${COMPACT_INTERVAL}";
if [ -f "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" ]; then
LAST_COMPACT_DATE=$(cat "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" 2>/dev/null);
printf "${PRINTF_INFO_STRING}" "Module last compact" \
"$(printf '%(%c)T' "${LAST_COMPACT_DATE}") ($(convert_time $(($(date +%s) - LAST_COMPACT_DATE))) ago)";
else
printf "${PRINTF_INFO_STRING}" "Module last compact" "No compact run yet"
fi;
fi;
fi;
# print last check date if positive integer
if [ "${CHECK_INTERVAL##*[!0-9]*}" ]; then
printf "${PRINTF_INFO_STRING}" "Module check interval" "${CHECK_INTERVAL}";
# get last check date
if [ -f "${BASE_FOLDER}${BACKUP_CHECK_FILE}" ]; then
LAST_CHECK_DATE=$(cat "${BASE_FOLDER}${BACKUP_CHECK_FILE}" 2>/dev/null);
printf "${PRINTF_INFO_STRING}" "Module last check" \
"$(printf '%(%c)T' "${LAST_CHECK_DATE}") ($(convert_time $(($(date +%s) - LAST_CHECK_DATE))) ago)";
else
printf "${PRINTF_INFO_STRING}" "Module last check" "No check run yet";
fi;
fi;
# if force verify is true set VERIFY to 1 unless INFO is 1
# Needs bash 4.0 at lesat for this
if [ "${FORCE_VERIFY,,}" = "true" ] && [ "${INFO}" -eq 0 ]; then
VERIFY=1;
if [ "${DEBUG}" -eq 1 ]; then
echo "Force repository verify";
fi;
fi;
# remote borg path
if [ -n "${TARGET_BORG_PATH}" ]; then
if [[ "${TARGET_BORG_PATH}" =~ \ |\' ]]; then
echo "Space found in ${TARGET_BORG_PATH}. Aborting";
echo "There are issues with passing on paths with spaces"
echo "as parameters"
exit;
fi;
OPT_REMOTE="--remote-path="$(printf "%q" "${TARGET_BORG_PATH}");
fi;
if [ -z "${TARGET_FOLDER}" ]; then
echo "[! $(date +'%F %T')] No target folder has been set yet";
exit 1;
else
# There are big issues with TARGET FOLDERS with spaces
# we should abort anything with this
if [[ "${TARGET_FOLDER}" =~ \ |\' ]]; then
echo "Space found in ${TARGET_FOLDER}. Aborting";
echo "There is some problem with passing paths with spaces as";
echo "repository base folder"
exit;
fi;
# This does not care for multiple trailing or leading slashes
# it just makes sure we have at least one set
# for if we have a single slash, remove it
TARGET_FOLDER=${TARGET_FOLDER%/}
TARGET_FOLDER=${TARGET_FOLDER#/}
# and add slash front and back and escape the path
TARGET_FOLDER=$(printf "%q" "/${TARGET_FOLDER}/");
fi;
# if we have user/host then we build the ssh command
TARGET_SERVER='';
# allow host only (if full setup in .ssh/config)
# user@host OR ssh://user@host:port/ IF TARGET_PORT is set
# user/host/port
if [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ] && [ -n "${TARGET_PORT}" ]; then
TARGET_SERVER="ssh://${TARGET_USER}@${TARGET_HOST}:${TARGET_PORT}/";
# host/port
elif [ -n "${TARGET_HOST}" ] && [ -n "${TARGET_PORT}" ]; then
TARGET_SERVER="ssh://${TARGET_HOST}:${TARGET_PORT}/";
# user/host
elif [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:";
# host
elif [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_HOST}:";
fi;
# we dont allow special characters, so we don't need to special escape it
REPOSITORY="${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE}";
printf "${PRINTF_INFO_STRING}" "Repository" "${REPOSITORY}";
# check if given compression name and level are valid
OPT_COMPRESSION='';
if [ -n "${COMPRESSION}" ]; then
# valid compression
if [ "${COMPRESSION}" = "lz4" ] || [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]; then
OPT_COMPRESSION="-C=${COMPRESSION}";
# if COMPRESSION_LEVEL, check it is a valid regex
# for zlib, zstd, lzma
if [ -n "${COMPRESSION_LEVEL}" ] && { [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]; }; then
MIN_COMPRESSION=0;
MAX_COMPRESSION=0;
case "${COMPRESSION}" in
zlib|lzma)
MIN_COMPRESSION=0;
MAX_COMPRESSION=9;
;;
zstd)
MIN_COMPRESSION=1;
MAX_COMPRESSION=22;
;;
*)
MIN_COMPRESSION=0;
MAX_COMPRESSION=0;
;;
esac;
# if [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ]
# MIN_COMPRESSION=0;
# MAX_COMPRESSION=9;
# elif [ "${COMPRESSION}" = "zstd" ]; then
# MIN_COMPRESSION=1;
# MAX_COMPRESSION=22;
# fi;
error_message="[! $(date +'%F %T')] Compression level for ${COMPRESSION} needs to be a numeric value between ${MIN_COMPRESSION} and ${MAX_COMPRESSION}: ${COMPRESSION_LEVEL}";
if ! [[ "${COMPRESSION_LEVEL}" =~ ${REGEX_NUMERIC} ]]; then
echo "${error_message}";
exit 1;
elif [ "${COMPRESSION_LEVEL}" -lt "${MIN_COMPRESSION}" ] || [ "${COMPRESSION_LEVEL}" -gt "${MAX_COMPRESSION}" ]; then
echo "${error_message}";
exit 1;
else
OPT_COMPRESSION=${OPT_COMPRESSION}","${COMPRESSION_LEVEL};
fi;
fi;
else
echo "[! $(date +'%F %T')] Compress setting need to be lz4, zstd, zlib or lzma. Or empty for no compression: ${COMPRESSION}";
exit 1;
fi;
fi;
# home folder, needs to be set if there is eg a HOME=/ in the crontab
if [ ! -w "${HOME}" ] || [ "${HOME}" = '/' ]; then
HOME=$(eval echo "$(whoami)");
fi;
# keep optionfs (for files)
KEEP_OPTIONS=();
# keep info string (for files)
KEEP_INFO="";
# override standard keep for tagged backups
if [ -n "${ONE_TIME_TAG}" ]; then
BACKUP_SET="{now:%Y-%m-%dT%H:%M:%S}";
# set empty to avoid problems
KEEP_OPTIONS=("");
else
# build options and info string,
# also flag BACKUP_SET check if hourly is set
BACKUP_SET_VERIFY=0;
if [ "${KEEP_LAST}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-last=${KEEP_LAST}");
KEEP_INFO="${KEEP_INFO}, last: ${KEEP_LAST}";
fi;
if [ "${KEEP_HOURS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-hourly=${KEEP_HOURS}");
KEEP_INFO="${KEEP_INFO}, hourly: ${KEEP_HOURS}";
BACKUP_SET_VERIFY=1;
fi;
if [ "${KEEP_DAYS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-daily=${KEEP_DAYS}");
KEEP_INFO="${KEEP_INFO}, daily: ${KEEP_DAYS}";
fi;
if [ "${KEEP_WEEKS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-weekly=${KEEP_WEEKS}");
KEEP_INFO="${KEEP_INFO}, weekly: ${KEEP_WEEKS}";
fi;
if [ "${KEEP_MONTHS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-monthly=${KEEP_MONTHS}");
KEEP_INFO="${KEEP_INFO}, monthly: ${KEEP_MONTHS}";
fi;
if [ "${KEEP_YEARS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-yearly=${KEEP_YEARS}");
KEEP_INFO="${KEEP_INFO}, yearly: ${KEEP_YEARS}";
fi;
if [ -n "${KEEP_WITHIN}" ]; then
# check for invalid string. can only be number + H|d|w|m|y
if [[ "${KEEP_WITHIN}" =~ ^[0-9]+[Hdwmy]{1}$ ]]; then
KEEP_OPTIONS+=("--keep-within=${KEEP_WITHIN}");
KEEP_INFO="${KEEP_INFO}, within: ${KEEP_WITHIN}";
if [[ "${KEEP_WITHIN}" == *"H"* ]]; then
BACKUP_SET_VERIFY=1;
fi;
else
echo "[! $(date +'%F %T')] KEEP_WITHIN has invalid string.";
exit 1;
fi;
fi;
# abort if KEEP_OPTIONS is empty
if [ "${#KEEP_OPTIONS[@]}" -eq "0" ]; then
echo "[! $(date +'%F %T')] It seems no KEEP_* entries where set in a valid format.";
exit 1;
fi;
# set BACKUP_SET if empty, set to Year-month-day
if [ -z "${BACKUP_SET}" ]; then
BACKUP_SET="{now:%Y-%m-%d}";
fi;
# backup set check, and there is no hour entry (%H) in the archive string
# we add T%H:%M:%S in this case, before the last }
if [ ${BACKUP_SET_VERIFY} -eq 1 ] && [[ "${BACKUP_SET}" != *"%H"* ]]; then
BACKUP_SET=$(echo "${BACKUP_SET}" | sed -e "s/}/T%H:%M:%S}/");
fi;
fi;
# check if we have lock file, check pid in lock file, if no matching pid found
# running remove lock file
if [ -f "${BASE_FOLDER}${BACKUP_LOCK_FILE}" ]; then
LOCK_PID=$(cat "${BASE_FOLDER}${BACKUP_LOCK_FILE}" 2>/dev/null);
# check if lock file pid has an active program attached to it
if [ -f "/proc/${LOCK_PID}/cmdline" ]; then
echo "Script is already running on PID: ${$}";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
else
echo "[#] Clean up stale lock file for PID: ${LOCK_PID}";
rm "${BASE_FOLDER}${BACKUP_LOCK_FILE}";
fi;
fi;
echo "${$}" > "${BASE_FOLDER}${BACKUP_LOCK_FILE}";
# for folders list split set to "#" and keep the old setting as is
_IFS=${IFS};
IFS="#";
# turn off for non file
if [ "${MODULE}" != "file" ]; then
IFS=${_IFS};
fi;
# borg call, replace ##...## parts during run
# used in all modules, except 'file'
_BORG_CALL="${BORG_COMMAND} create ${OPT_REMOTE} -v ${OPT_LIST} ${OPT_PROGRESS} ${OPT_COMPRESSION} -s --stdin-name ##FILENAME## ${REPOSITORY}::##BACKUP_SET## -";
_BORG_PRUNE="${BORG_COMMAND} prune ${OPT_REMOTE} -v --list ${OPT_PROGRESS} ${DRY_RUN_STATS} -P ##BACKUP_SET_PREFIX## ${KEEP_OPTIONS[*]} ${REPOSITORY}";
# general borg settings
# set base path to config directory to keep cache/config separated
export BORG_BASE_DIR="${BASE_FOLDER}";
# ignore non encrypted access
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK="${_BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK}";
# ignore moved repo access
export BORG_RELOCATED_REPO_ACCESS_IS_OK="${_BORG_RELOCATED_REPO_ACCESS_IS_OK}";
# and for debug print that tout
if [ "${DEBUG}" -eq 1 ]; then
echo "export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=${_BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK};";
echo "export BORG_RELOCATED_REPO_ACCESS_IS_OK=${_BORG_RELOCATED_REPO_ACCESS_IS_OK};";
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";";
fi;
# prepare debug commands only
COMMAND_EXPORT="export BORG_BASE_DIR=\"${BASE_FOLDER}\";"
COMMAND_INFO="${COMMAND_EXPORT}${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY}";
# if the is not there, call init to create it
# if this is user@host, we need to use ssh command to verify if the file is there
# else a normal verify is ok
# unless explicit given, verify is skipped
# MARK: VERIFY / INFO
if [ "${VERIFY}" -eq 1 ] || [ "${INIT}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "VERIFY" "$(date +'%F %T')" "${MODULE}";
if [ -n "${TARGET_SERVER}" ]; then
if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY} 2>&1|grep \"Repository ID:\"";
fi;
# use borg info and verify if it returns "Repository ID:" in the first line
REPO_VERIFY=$(${BORG_COMMAND} info ${OPT_REMOTE} "${REPOSITORY}" 2>&1);
if ! $?; then
echo "[!] Repository verify error: ${REPO_VERIFY}";
REPO_VERIFY="";
else
REPO_VERIFY=$(echo "${REPO_VERIFY}" | grep "Repository ID:");
fi;
# | grep "Repository ID:"
# this is currently a hack to work round the error code in borg info
# this checks if REPO_VERIFY holds this error message and then starts init
if [[ -z "${REPO_VERIFY}" ]] || [[ "${REPO_VERIFY}" =~ ${REGEX_ERROR} ]]; then
INIT_REPOSITORY=1;
fi;
elif [ ! -d "${REPOSITORY}" ]; then
INIT_REPOSITORY=1;
fi;
# if verrify but no init and repo is there but init file is missing set it
if [ "${VERIFY}" -eq 1 ] && [ "${INIT}" -eq 0 ] && [ "${INIT_REPOSITORY}" -eq 0 ] &&
[ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
# write init file
echo "[!] Add missing init verify file";
date +%s > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
fi;
# end if verified but repository is not here
if [ "${VERIFY}" -eq 1 ] && [ "${INIT}" -eq 0 ] && [ "${INIT_REPOSITORY}" -eq 1 ]; then
echo "[! $(date +'%F %T')] No repository. Please run with -I flag to initialze repository";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
fi;
if [ "${EXIT}" -eq 1 ] && [ "${VERIFY}" -eq 1 ] && [ "${INIT}" -eq 0 ]; then
echo "Repository exists";
echo "For more information run:"
echo "${COMMAND_INFO}";
. "${DIR}/borg.backup.functions.close.sh";
exit;
fi;
fi;
# MARK: INIT
if [ "${INIT}" -eq 1 ] && [ "${INIT_REPOSITORY}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "INIT" "$(date +'%F %T')" "${MODULE}";
if [ "${DEBUG}" -eq 1 ] || [ "${DRYRUN}" -eq 1 ]; then
echo "${BORG_COMMAND} init ${OPT_REMOTE} -e ${ENCRYPTION} ${OPT_VERBOSE} ${REPOSITORY}";
echo "${BORG_COMMAND} key export ${REPOSITORY}";
echo "${BORG_COMMAND} key export --paper ${REPOSITORY}";
fi
if [ "${DRYRUN}" -eq 0 ]; then
# should trap and exit properly here
${BORG_COMMAND} init ${OPT_REMOTE} -e "${ENCRYPTION}" ${OPT_VERBOSE} "${REPOSITORY}";
# show the key file
if [ "${ENCRYPTION}" = "keyfile" ]; then
echo "--- [ENCRYPTION KEY] --[START]-------------------------------------------------->";
echo "Store the key and password in a safe place";
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";borg key export [--paper] ${REPOSITORY}";
echo "----[BORG KEY] -------------------------------->";
${BORG_COMMAND} key export "${REPOSITORY}";
echo "----[BORG KEY:paper] -------------------------->";
${BORG_COMMAND} key export --paper "${REPOSITORY}";
echo "--- [ENCRYPTION KEY] --[END ]-------------------------------------------------->";
fi;
# write init file
date +%s > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
echo "Repository initialized";
echo "For more information run:"
echo "${COMMAND_INFO}";
fi
. "${DIR}/borg.backup.functions.close.sh";
# exit after init
exit;
elif [ "${INIT}" -eq 1 ] && [ "${INIT_REPOSITORY}" -eq 0 ]; then
echo "[! $(date +'%F %T')] Repository already initialized";
echo "For more information run:"
echo "${COMMAND_INFO}";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
fi;
# verify for init file
if [ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
echo "[! $(date +'%F %T')] It seems the repository has never been initialized."
echo "Please run -I to initialize or if already initialzed run with -C for init update."
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
fi;
# MARK: LIST / PRINT
# PRINT OUT current data, only do this if REPO exists
if [ "${PRINT}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "PRINT" "$(date +'%F %T')" "${MODULE}";
FORMAT="{archive:<45} {comment:6} {start} - {end} [{id}] ({username}@{hostname}){NL}"
# show command on debug or dry run
if [ "${DEBUG}" -eq 1 ] || [ "${DRYRUN}" -eq 1 ]; then
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} list ${OPT_REMOTE} --format ${FORMAT} ${REPOSITORY}";
fi;
# run info command if not a dry drun
if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMMAND} list ${OPT_REMOTE} --format "${FORMAT}" "${REPOSITORY}" ;
fi;
if [ "${VERBOSE}" -eq 1 ]; then
echo "";
echo "Base command info:"
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} [COMMAND] ${OPT_REMOTE} ${REPOSITORY}::[BACKUP] [PATH]";
echo "Replace [COMMAND] with list for listing or extract for restoring backup data."
echo "Replace [BACKUP] with archive name."
echo "If no [PATH] is given then all files will be restored."
echo "Before extracting -n (dry run) is recommended to use."
echo "If archive size is needed the info command with archive name has to be used."
echo "When listing files in an archive set (::SET) the --format command can be used."
echo "Example: \"{mode} {user:6} {group:6} {size:8d} {csize:8d} {dsize:8d} {dcsize:8d} {mtime} {path}{extra} [{health}]{NL}\""
else
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} [COMMAND] ${OPT_REMOTE} [FORMAT] ${REPOSITORY}::[BACKUP] [PATH]";
fi;
. "${DIR}/borg.backup.functions.close.sh";
exit;
fi;
# run borg compact command and exit
if [ "${COMPACT}" -eq 1 ]; then
. "${DIR}/borg.backup.functions.compact.sh";
. "${DIR}/borg.backup.functions.close.sh";
exit;
fi;
# run borg check command and exit
if [ "${CHECK}" -eq 1 ]; then
. "${DIR}/borg.backup.functions.check.sh";
. "${DIR}/borg.backup.functions.close.sh";
exit;
fi;
# DELETE ONE TIME TAG
if [ -n "${DELETE_ONE_TIME_TAG}" ]; then
printf "${PRINTF_SUB_BLOCK}" "DELETE" "$(date +'%F %T')" "${MODULE}";
# if a "*" is inside we don't do ONE archive, but globbing via -a option
DELETE_ARCHIVE=""
OPT_GLOB="";
# this is more or less for debug only
if [[ "${DELETE_ONE_TIME_TAG}" =~ $REGEX_GLOB ]]; then
OPT_GLOB="-a '${DELETE_ONE_TIME_TAG}'"
else
DELETE_ARCHIVE="::"${DELETE_ONE_TIME_TAG};
fi
# if this is borg <1.2 OPT_LIST does not work
if [ "$(version "$BORG_VERSION")" -lt "$(version "1.2.0")" ]; then
OPT_LIST="";
fi;
# if exists, delete and exit
# show command on debug or dry run
if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} delete ${OPT_REMOTE} ${OPT_LIST} -s ${OPT_GLOB} ${REPOSITORY}${DELETE_ARCHIVE}";
fi;
# run delete command if not a dry drun
# NOTE seems to be glob is not working if wrapped into another variable
if [[ "${DELETE_ONE_TIME_TAG}" =~ $REGEX_GLOB ]]; then
${BORG_COMMAND} delete ${OPT_REMOTE} ${OPT_LIST} ${DRY_RUN_STATS} -a "${DELETE_ONE_TIME_TAG}" ${REPOSITORY};
else
${BORG_COMMAND} delete ${OPT_REMOTE} ${OPT_LIST} ${DRY_RUN_STATS} ${REPOSITORY}${DELETE_ARCHIVE};
fi;
# if not a dry run, compact repository after delete
# not that compact only works on borg 1.2
if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMMAND} compact ${OPT_REMOTE} "${REPOSITORY}";
fi;
if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} compact ${OPT_REMOTE} ${REPOSITORY}";
fi;
fi;
. "${DIR}/borg.backup.functions.close.sh";
exit;
fi;
# __END__