#!/usr/bin/env bash set -euo pipefail # === METADATA === SCRIPT_NAME="$(basename "$0")" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SKILL_ROOT="$(dirname "$SCRIPT_DIR")" # === CONFIGURATION === : "${NODE_NAME:=node-a}" : "${BACKUP_LABEL:=manual}" : "${OUTPUT_DIR:=$SKILL_ROOT/outputs}" : "${BACKUP_SOURCES:=}" : "${BACKUP_EXCLUDES:=.git,node_modules,target,dist,outputs}" # === FUNCTIONS === log_plan() { echo "[PLAN] $(date -Iseconds) $*"; } die() { echo "[ERROR] $(date -Iseconds) $*" >&2; exit 1; } estimate_size() { local total=0 IFS=',' read -r -a sources <<< "$BACKUP_SOURCES" IFS=',' read -r -a excludes <<< "$BACKUP_EXCLUDES" for src in "${sources[@]}"; do src="${src/#\~/$HOME}" if [[ -e "$src" ]]; then # Build find exclude args local find_excludes=() for ex in "${excludes[@]}"; do find_excludes+=(-name "$ex" -prune -o) done local size size=$(find "$src" "${find_excludes[@]}" -type f -print0 2>/dev/null | \ xargs -0 stat -c%s 2>/dev/null | \ awk '{sum+=$1} END {print sum+0}') total=$((total + size)) fi done echo "$total" } main() { [[ -n "$BACKUP_SOURCES" ]] || die "BACKUP_SOURCES is required (comma-separated paths)." local ts run_id run_dir ts="$(date -Iseconds | tr ':' '-')" run_id="${NODE_NAME}_${BACKUP_LABEL}_${ts}" run_dir="$OUTPUT_DIR/runs/$run_id" log_plan "=== Backup Plan ===" log_plan "Run ID: $run_id" log_plan "Run directory: $run_dir" log_plan "Archive: $run_dir/archive.tar.gz" log_plan "Manifest: $run_dir/manifest.json" echo "" log_plan "=== Sources ===" IFS=',' read -r -a sources <<< "$BACKUP_SOURCES" for src in "${sources[@]}"; do src="${src/#\~/$HOME}" if [[ -e "$src" ]]; then log_plan " [OK] $src" else log_plan " [MISSING] $src" fi done echo "" log_plan "=== Excludes ===" IFS=',' read -r -a excludes <<< "$BACKUP_EXCLUDES" for ex in "${excludes[@]}"; do log_plan " - $ex" done echo "" log_plan "=== Size Estimate ===" local est_bytes est_mb est_bytes=$(estimate_size) est_mb=$((est_bytes / 1024 / 1024)) log_plan "Estimated uncompressed: ${est_mb} MB ($est_bytes bytes)" log_plan "Compressed size will be smaller (typically 30-70% of original)" echo "" log_plan "Next: ./scripts/11_backup_apply.sh (requires DRY_RUN=0)" } [[ "${BASH_SOURCE[0]}" == "$0" ]] && main "$@"