94 lines
2.5 KiB
Bash
Executable file
94 lines
2.5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
set -Eeuo pipefail
|
|
|
|
usage() {
|
|
echo "Usage: $0 BACKUP.tar.gz" >&2
|
|
}
|
|
|
|
if [[ "$#" -ne 1 ]]; then
|
|
usage
|
|
exit 2
|
|
fi
|
|
|
|
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
INPUT="$1"
|
|
if [[ "$INPUT" != /* ]]; then
|
|
INPUT="$(cd "$(dirname "$INPUT")" && pwd)/$(basename "$INPUT")"
|
|
fi
|
|
|
|
test -f "$INPUT" || { echo "Archive not found: $INPUT" >&2; exit 1; }
|
|
gzip -t "$INPUT"
|
|
|
|
STAGE="$(mktemp -d "$ROOT_DIR/.data-switch.XXXXXX")"
|
|
OLD="$(mktemp -d "$ROOT_DIR/.data-previous.XXXXXX")"
|
|
COMMITTED=false
|
|
|
|
cleanup() {
|
|
rm -rf "$STAGE"
|
|
if [[ "$COMMITTED" == false ]]; then
|
|
if [[ -d "$OLD/public" ]]; then
|
|
rm -rf "$ROOT_DIR/public"
|
|
mv "$OLD/public" "$ROOT_DIR/public"
|
|
fi
|
|
if [[ -d "$OLD/dbs" ]]; then
|
|
rm -rf "$ROOT_DIR/dbs"
|
|
mv "$OLD/dbs" "$ROOT_DIR/dbs"
|
|
fi
|
|
fi
|
|
rm -rf "$OLD"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
tar -C "$STAGE" -xzf "$INPUT"
|
|
test -d "$STAGE/public" || { echo "Archive has no public/ directory" >&2; exit 1; }
|
|
test -d "$STAGE/dbs" || { echo "Archive has no dbs/ directory" >&2; exit 1; }
|
|
|
|
mapfile -t DATABASES < <(find "$STAGE/dbs" -maxdepth 1 -type f -name '*.sqlite' -print)
|
|
if [[ "${#DATABASES[@]}" -eq 0 ]]; then
|
|
echo "Archive contains no SQLite databases" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for database in "${DATABASES[@]}"; do
|
|
DB_FILE="$database" node <<'NODE'
|
|
const Database = require("better-sqlite3");
|
|
const db = new Database(process.env.DB_FILE, { readonly: true });
|
|
const result = db.pragma("quick_check", { simple: true });
|
|
db.close();
|
|
if (result !== "ok") {
|
|
console.error(`${process.env.DB_FILE}: quick_check returned ${result}`);
|
|
process.exit(1);
|
|
}
|
|
NODE
|
|
done
|
|
|
|
for process_dir in /proc/[0-9]*; do
|
|
PROCESS_CWD="$(readlink "$process_dir/cwd" 2>/dev/null || true)"
|
|
PROCESS_CMD="$(tr '\0' ' ' < "$process_dir/cmdline" 2>/dev/null || true)"
|
|
if [[ "$PROCESS_CWD" == "$ROOT_DIR" ]] &&
|
|
[[ "$PROCESS_CMD" =~ (^|[[:space:]])(\./)?index\.js([[:space:]]|$) ]]; then
|
|
echo "Refusing to switch data while the local Bliss server is running." >&2
|
|
echo "Stop it first, then rerun this command." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|
PREVIOUS="$ROOT_DIR/backups/bliss-local-before-$STAMP.tar.gz"
|
|
mkdir -p "$ROOT_DIR/backups"
|
|
|
|
echo "Saving current local data to $PREVIOUS"
|
|
tar -C "$ROOT_DIR" -czf "$PREVIOUS" public dbs
|
|
gzip -t "$PREVIOUS"
|
|
|
|
mv "$ROOT_DIR/public" "$OLD/public"
|
|
mv "$ROOT_DIR/dbs" "$OLD/dbs"
|
|
mv "$STAGE/public" "$ROOT_DIR/public"
|
|
mv "$STAGE/dbs" "$ROOT_DIR/dbs"
|
|
COMMITTED=true
|
|
|
|
echo "Activated data from: $INPUT"
|
|
echo "Previous local data: $PREVIOUS"
|
|
echo "To switch back:"
|
|
printf ' %q %q\n' "$0" "$PREVIOUS"
|