# retoor import sys from devplacepy.cli._shared import _audit_cli def cmd_backups_list(args): from devplacepy.services.backup import store backups = store.list_backups() if not backups: print("No backups recorded") return for backup in backups: size = store.human_bytes(int(backup.get("size_bytes") or 0)) print( f"{backup['uid']} {backup.get('target', ''):<9} " f"{backup.get('status', ''):<8} {size:>10} " f"{backup.get('created_at', '')} {backup.get('filename', '')}" ) def cmd_backups_run(args): from devplacepy.services.backup import store from devplacepy.services.jobs import queue if not store.is_valid_target(args.target): print(f"Unknown target '{args.target}'. Choose one of: {', '.join(store.BACKUP_TARGETS)}") sys.exit(1) job_uid = queue.enqueue( "backup", {"target": args.target, "schedule_uid": "", "created_by": "cli"}, owner_kind="system", owner_id="cli", preferred_name=f"{store.target_label(args.target)} (cli)", ) store.create_backup(target=args.target, created_by="cli", job_uid=job_uid) _audit_cli( "cli.backups.run", f"CLI enqueued {args.target} backup", metadata={"target": args.target, "job_uid": job_uid}, ) print(f"Enqueued {args.target} backup job {job_uid} (processed by the running server)") def cmd_backups_prune(args): from devplacepy.services.backup import store removed = store.prune_orphans() _audit_cli("cli.backups.prune", f"CLI pruned {removed} orphan backups", metadata={"count": removed}) print(f"Pruned {removed} orphan backup record(s)") def cmd_backups_clear(args): from devplacepy.services.backup import store removed = store.clear_all() _audit_cli("cli.backups.clear", f"CLI cleared all backups ({removed})", metadata={"count": removed}) print(f"Cleared {removed} backup(s) and their archives") def register_backups(subparsers): backups = subparsers.add_parser("backups", help="Backup management") backups_sub = backups.add_subparsers(title="action", dest="action") backups_sub.add_parser("list", help="List recorded backups").set_defaults( func=cmd_backups_list ) backups_run = backups_sub.add_parser( "run", help="Enqueue a backup (processed by the running server)" ) backups_run.add_argument( "target", choices=["database", "uploads", "keys", "full"], help="What to back up", ) backups_run.set_defaults(func=cmd_backups_run) backups_sub.add_parser( "prune", help="Remove backup records whose archive file is missing" ).set_defaults(func=cmd_backups_prune) backups_sub.add_parser( "clear", help="Delete every backup archive and record" ).set_defaults(func=cmd_backups_clear)