55 lines
2.3 KiB
Python
55 lines
2.3 KiB
Python
"""Database backup/check/list and explicitly offline restore; no app initialization."""
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
import sqlite3
|
|
import sys
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from logistics_chat.database_backup import (check_database, daily_backup, restore_database,
|
|
snapshot_database, unique_backup_path)
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--db', type=Path, default=ROOT/'history.db')
|
|
parser.add_argument('--backup-dir', type=Path, default=None)
|
|
parser.add_argument('command', choices=('backup', 'daily', 'list', 'check', 'restore'))
|
|
parser.add_argument('--input', type=Path)
|
|
parser.add_argument('--service-stopped', action='store_true', help='Confirm all database users are stopped before restore')
|
|
args = parser.parse_args(argv)
|
|
database = args.db.resolve()
|
|
directory = (args.backup_dir or database.parent/'backups').resolve()
|
|
try:
|
|
if args.command == 'backup':
|
|
path = snapshot_database(database, unique_backup_path(directory, 'manual'))
|
|
print('Backup: ' + str(path))
|
|
elif args.command == 'daily':
|
|
print('Backup: ' + str(daily_backup(database, directory)))
|
|
elif args.command == 'list':
|
|
for path in sorted(directory.glob('*.db'), reverse=True):
|
|
print(json.dumps({'file':str(path), 'bytes':path.stat().st_size}, ensure_ascii=False))
|
|
elif args.command == 'check':
|
|
print(check_database(args.input or database))
|
|
elif args.command == 'restore':
|
|
if not args.service_stopped:
|
|
parser.error('Restore requires --service-stopped; stop the app and all database users first')
|
|
if args.input is None:
|
|
parser.error('Restore requires --input')
|
|
safety = restore_database(database, args.input, directory)
|
|
print('Restored: ' + str(database))
|
|
if safety:
|
|
print('Safety backup: ' + str(safety))
|
|
except (OSError, ValueError, RuntimeError, sqlite3.Error) as error:
|
|
print('Database operation failed: ' + str(error), file=sys.stderr)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
raise SystemExit(main())
|