backup-container/src/borg-common.sh
Andras Schmelczer 4f98c40b15
All checks were successful
Docker / build (push) Successful in 21s
ShellCheck / shellcheck (push) Successful in 4s
Fix remote repo init
2026-09-27 20:57:02 +01:00

64 lines
2.1 KiB
Shell

#!/bin/bash
export BORG_RSH='ssh -oBatchMode=yes'
borg_ensure_repository() {
local status=0
borg_wait info || status=$?
(( status != 0 )) || return 0
# Borg 1.4 reports InvalidRepository over SSH as generic RPC exit code 2,
# even with modern exit codes enabled. Let init validate the destination:
# it accepts missing/empty directories and refuses existing data.
if (( status == 2 || status == 13 || status == 15 )); then
echo 'Repository could not be opened. Attempting Borg initialization...'
status=0
borg_wait init --encryption=repokey || status=$?
# Another client may have initialized it after the initial check.
if (( status == 10 )); then
borg_wait info
else
return "$status"
fi
else
echo "Cannot access repository (Borg exit status $status). Skipping backup." >&2
return "$status"
fi
}
# Borg expands placeholders in both names and archive filters. Only the filter
# needs glob escaping; user-supplied prefixes are literal in both places.
borg_literal_prefix() {
local mode=$1 prefix=$2 character index
for ((index = 0; index < ${#prefix}; index++)); do
character=${prefix:index:1}
case "$character" in
'{') printf '{{' ;;
'}') printf '}}' ;;
'['|'?'|'*')
if [[ $mode == glob ]]; then
printf '[%s]' "$character"
else
printf '%s' "$character"
fi
;;
*) printf '%s' "$character" ;;
esac
done
}
# Never break another client's repository/cache lock. Borg 1.4 only accepts
# finite waits, so retry lock timeouts forever; other errors must propagate.
borg_wait() {
local status
while true; do
if BORG_EXIT_CODES=modern borg "$@" --lock-wait=60; then
return 0
else
status=$?
fi
if (( status != 73 )); then
return "$status"
fi
echo "Repository or cache is locked; continuing to wait..." >&2
done
}