1import os
2import time
3from pathlib import Path
4
5import click
6
7from .core import DatabaseBackups
8
9
10@click.group("backups")
11def cli():
12 """Local database backups"""
13 pass
14
15
16@cli.command("list")
17def list_backups():
18 backups_handler = DatabaseBackups()
19 backups = backups_handler.find_backups()
20 if not backups:
21 click.secho("No backups found", fg="yellow")
22 return
23
24 for backup in backups:
25 click.secho(
26 f"{backup.name} ({backup.updated_at().strftime('%Y-%m-%d %H:%M:%S')})",
27 bold=True,
28 )
29
30 for backup_file in backup.iter_files():
31 size = os.path.getsize(backup_file)
32 click.echo(f"- {backup_file.name} ({size / 1024 / 1024:.2f} MB)")
33
34 click.echo()
35
36
37@cli.command("create")
38@click.option("--pg-dump", default="pg_dump", envvar="PG_DUMP")
39@click.argument("backup_name", default="")
40def create_backup(backup_name, pg_dump):
41 backups_handler = DatabaseBackups()
42
43 if not backup_name:
44 backup_name = f"backup_{time.strftime('%Y%m%d_%H%M%S')}"
45
46 try:
47 backup_dir = backups_handler.create(
48 backup_name,
49 pg_dump=pg_dump,
50 )
51 except Exception as e:
52 click.secho(str(e), fg="red")
53 exit(1)
54
55 click.secho(f"Backup created in {backup_dir.relative_to(Path.cwd())}", fg="green")
56
57
58@cli.command("restore")
59@click.option("--latest", is_flag=True)
60@click.option("--pg-restore", default="pg_restore", envvar="PG_RESTORE")
61@click.argument("backup_name", default="")
62def restore_backup(backup_name, latest, pg_restore):
63 backups_handler = DatabaseBackups()
64
65 if backup_name and latest:
66 click.secho("Only one of --latest or backup_name is allowed", fg="red")
67 exit(1)
68
69 if not backup_name and not latest:
70 click.secho("Backup name or --latest is required", fg="red")
71 exit(1)
72
73 if not backup_name and latest:
74 backup_name = backups_handler.find_backups()[0].name
75
76 click.secho(f"Restoring backup {backup_name}...", bold=True)
77
78 try:
79 backups_handler.restore(
80 backup_name,
81 pg_restore=pg_restore,
82 )
83 except Exception as e:
84 click.secho(str(e), fg="red")
85 exit(1)
86 click.echo(f"Backup {backup_name} restored successfully.")
87
88
89@cli.command("delete")
90@click.argument("backup_name")
91def delete_backup(backup_name):
92 backups_handler = DatabaseBackups()
93 try:
94 backups_handler.delete(backup_name)
95 except Exception as e:
96 click.secho(str(e), fg="red")
97 return
98 click.secho(f"Backup {backup_name} deleted", fg="green")
99
100
101@cli.command("clear")
102@click.confirmation_option(prompt="Are you sure you want to delete all backups?")
103def clear_backups():
104 backups_handler = DatabaseBackups()
105 backups = backups_handler.find_backups()
106 for backup in backups:
107 backup.delete()
108 click.secho("All backups deleted", fg="green")