feat: add non-destructive file-restore mode to restore.sh
This commit is contained in:
+21
@@ -65,6 +65,27 @@ list_archives() {
|
|||||||
borg list --lock-wait 60
|
borg list --lock-wait 60
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extract_path() {
|
||||||
|
local rel_path="$1" dest_dir="$2" archive="$3"
|
||||||
|
mkdir -p "$dest_dir"
|
||||||
|
( cd "$dest_dir" && run_cmd borg extract --lock-wait 600 "${REPO}::${archive}" "${ARCHIVE_TARGET_PATH}/${rel_path}" )
|
||||||
|
echo "${dest_dir%/}/${ARCHIVE_TARGET_PATH}/${rel_path}"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_file() {
|
||||||
|
local rel_path="$1" dest
|
||||||
|
resolve_archive
|
||||||
|
dest="${DEST:-/tmp/restore-file-$$}"
|
||||||
|
step "Restoring '$rel_path' from archive $RESOLVED_ARCHIVE into $dest"
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
log "[DRY-RUN] would extract ${ARCHIVE_TARGET_PATH}/${rel_path} from ${REPO}::${RESOLVED_ARCHIVE} into $dest"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local final
|
||||||
|
final="$(extract_path "$rel_path" "$dest" "$RESOLVED_ARCHIVE" | tail -n1)"
|
||||||
|
log "Restored file available at: $final"
|
||||||
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
Usage:
|
Usage:
|
||||||
|
|||||||
@@ -59,10 +59,44 @@ test_list_archives() {
|
|||||||
rm -rf "$mockdir"
|
rm -rf "$mockdir"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_file_restore_extracts_to_dest() {
|
||||||
|
local mockdir dest out final
|
||||||
|
mockdir="$(mktemp -d)"
|
||||||
|
dest="$(mktemp -d)"
|
||||||
|
setup_mock_bin "$mockdir"
|
||||||
|
out="$(PATH="$mockdir:$PATH" bash "$RESTORE" file photos/img.jpg --dest "$dest")"
|
||||||
|
final="$dest/home/srv/files/content/photos/img.jpg"
|
||||||
|
assert_contains "$out" "Restored file available at: $final" "file mode reports final path"
|
||||||
|
if [[ -f "$final" ]]; then
|
||||||
|
echo "PASS: extracted file exists on disk"
|
||||||
|
else
|
||||||
|
echo "FAIL: extracted file missing at $final"
|
||||||
|
FAILURES=$((FAILURES + 1))
|
||||||
|
fi
|
||||||
|
rm -rf "$mockdir" "$dest"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_file_restore_dry_run_makes_no_borg_call() {
|
||||||
|
local mockdir dest
|
||||||
|
mockdir="$(mktemp -d)"
|
||||||
|
dest="$(mktemp -d)"
|
||||||
|
setup_mock_bin "$mockdir"
|
||||||
|
PATH="$mockdir:$PATH" bash "$RESTORE" file photos/img.jpg --dest "$dest" --dry-run >/dev/null
|
||||||
|
if [[ -s "$mockdir/mock.log" ]] && grep -q "^borg extract" "$mockdir/mock.log"; then
|
||||||
|
echo "FAIL: dry-run invoked borg extract"
|
||||||
|
FAILURES=$((FAILURES + 1))
|
||||||
|
else
|
||||||
|
echo "PASS: dry-run made no borg extract call"
|
||||||
|
fi
|
||||||
|
rm -rf "$mockdir" "$dest"
|
||||||
|
}
|
||||||
|
|
||||||
test_help_exits_zero
|
test_help_exits_zero
|
||||||
test_no_args_exits_one
|
test_no_args_exits_one
|
||||||
test_unknown_command_exits_one
|
test_unknown_command_exits_one
|
||||||
test_list_archives
|
test_list_archives
|
||||||
|
test_file_restore_extracts_to_dest
|
||||||
|
test_file_restore_dry_run_makes_no_borg_call
|
||||||
|
|
||||||
echo "-----"
|
echo "-----"
|
||||||
if [[ "$FAILURES" -gt 0 ]]; then
|
if [[ "$FAILURES" -gt 0 ]]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user