Add optional secondary backup location

This commit is contained in:
thePR0M3TH3AN
2025-07-03 11:54:06 -04:00
parent 1d4c6cc146
commit aa1edddf9f
2 changed files with 48 additions and 5 deletions

View File

@@ -40,12 +40,14 @@ class BackupManager:
BACKUP_FILENAME_TEMPLATE = "entries_db_backup_{timestamp}.json.enc" BACKUP_FILENAME_TEMPLATE = "entries_db_backup_{timestamp}.json.enc"
def __init__(self, fingerprint_dir: Path, config_manager: ConfigManager): def __init__(self, fingerprint_dir: Path, config_manager: ConfigManager):
""" """Initialize BackupManager for a specific profile.
Initializes the BackupManager with the fingerprint directory.
Parameters: Parameters
fingerprint_dir (Path): The directory corresponding to the fingerprint. ----------
config_manager (ConfigManager): Configuration manager for profile settings. fingerprint_dir : Path
Directory for this profile.
config_manager : ConfigManager
Configuration manager used for retrieving settings.
""" """
self.fingerprint_dir = fingerprint_dir self.fingerprint_dir = fingerprint_dir
self.config_manager = config_manager self.config_manager = config_manager
@@ -76,10 +78,30 @@ class BackupManager:
shutil.copy2(index_file, backup_file) shutil.copy2(index_file, backup_file)
logger.info(f"Backup created successfully at '{backup_file}'.") logger.info(f"Backup created successfully at '{backup_file}'.")
print(colored(f"Backup created successfully at '{backup_file}'.", "green")) print(colored(f"Backup created successfully at '{backup_file}'.", "green"))
self._create_additional_backup(backup_file)
except Exception as e: except Exception as e:
logger.error(f"Failed to create backup: {e}", exc_info=True) logger.error(f"Failed to create backup: {e}", exc_info=True)
print(colored(f"Error: Failed to create backup: {e}", "red")) print(colored(f"Error: Failed to create backup: {e}", "red"))
def _create_additional_backup(self, backup_file: Path) -> None:
"""Write a copy of *backup_file* to the configured secondary location."""
path = self.config_manager.get_additional_backup_path()
if not path:
return
try:
dest_dir = Path(path).expanduser()
dest_dir.mkdir(parents=True, exist_ok=True)
dest_file = dest_dir / f"{self.fingerprint_dir.name}_{backup_file.name}"
shutil.copy2(backup_file, dest_file)
logger.info(f"Additional backup created at '{dest_file}'.")
except Exception as e: # pragma: no cover - best-effort logging
logger.error(
f"Failed to write additional backup to '{path}': {e}",
exc_info=True,
)
def restore_latest_backup(self) -> None: def restore_latest_backup(self) -> None:
try: try:
backup_files = sorted( backup_files = sorted(

View File

@@ -63,3 +63,24 @@ def test_backup_restore_workflow(monkeypatch):
current = vault.load_index() current = vault.load_index()
backup_mgr.restore_backup_by_timestamp(1111) backup_mgr.restore_backup_by_timestamp(1111)
assert vault.load_index() == current assert vault.load_index() == current
def test_additional_backup_location(monkeypatch):
with TemporaryDirectory() as tmpdir, TemporaryDirectory() as extra:
fp_dir = Path(tmpdir)
vault, enc_mgr = create_vault(fp_dir, TEST_SEED, TEST_PASSWORD)
cfg_mgr = ConfigManager(vault, fp_dir)
cfg_mgr.set_additional_backup_path(extra)
backup_mgr = BackupManager(fp_dir, cfg_mgr)
vault.save_index({"schema_version": 2, "entries": {"a": {}}})
monkeypatch.setattr(time, "time", lambda: 3333)
backup_mgr.create_backup()
backup = fp_dir / "backups" / "entries_db_backup_3333.json.enc"
assert backup.exists()
extra_file = Path(extra) / f"{fp_dir.name}_entries_db_backup_3333.json.enc"
assert extra_file.exists()
assert extra_file.stat().st_mode & 0o777 == 0o600