diff --git a/mealie/services/backups_v2/backup_v2.py b/mealie/services/backups_v2/backup_v2.py index 01c192448..3caa19401 100644 --- a/mealie/services/backups_v2/backup_v2.py +++ b/mealie/services/backups_v2/backup_v2.py @@ -4,6 +4,7 @@ import shutil from pathlib import Path from zipfile import ZipFile +from mealie.core.config import get_app_settings from mealie.services._base_service import BaseService from mealie.services.backups_v2.alchemy_exporter import AlchemyExporter from mealie.services.backups_v2.backup_file import BackupFile @@ -13,6 +14,12 @@ class BackupSchemaMismatch(Exception): ... class BackupV2(BaseService): + EXCLUDE_DIRS = {"backups", ".temp"} + EXCLUDE_FILES = {"mealie.db", "mealie.log"} + EXCLUDE_EXTENTIONS = {".zip"} + + RESTORE_FILES = {".secret"} + def __init__(self, db_url: str | None = None) -> None: super().__init__() @@ -33,10 +40,6 @@ class BackupV2(BaseService): def backup(self) -> Path: # sourcery skip: merge-nested-ifs, reintroduce-else, remove-redundant-continue - exclude = {"mealie.db", "mealie.log", ".secret"} - exclude_ext = {".zip"} - exclude_dirs = {"backups", ".temp"} - timestamp = datetime.datetime.now(datetime.UTC).strftime("%Y.%m.%d.%H.%M.%S") backup_name = f"mealie_{timestamp}.zip" @@ -48,11 +51,11 @@ class BackupV2(BaseService): zip_file.writestr("database.json", json.dumps(database_json)) for data_file in self.directories.DATA_DIR.glob("**/*"): - if data_file.name in exclude: + if data_file.name in self.EXCLUDE_FILES: continue - if data_file.is_file() and data_file.suffix not in exclude_ext: - if data_file.parent.name in exclude_dirs: + if data_file.is_file() and data_file.suffix not in self.EXCLUDE_EXTENTIONS: + if data_file.parent.name in self.EXCLUDE_DIRS: continue zip_file.write(data_file, f"data/{data_file.relative_to(self.directories.DATA_DIR)}") @@ -62,11 +65,20 @@ class BackupV2(BaseService): def _copy_data(self, data_path: Path) -> None: for f in data_path.iterdir(): if f.is_file(): + if f.name not in self.RESTORE_FILES: + continue + + shutil.copyfile(f, self.directories.DATA_DIR / f.name) continue shutil.rmtree(self.directories.DATA_DIR / f.name) shutil.copytree(f, self.directories.DATA_DIR / f.name) + # since we copied a new .secret, AppSettings has the wrong secret info + self.logger.info("invalidating appsettings cache") + get_app_settings.cache_clear() + self.settings = get_app_settings() + def restore(self, backup_path: Path) -> None: self.logger.info("initializing backup restore") @@ -105,5 +117,4 @@ class BackupV2(BaseService): self.logger.info("restoring data directory") self._copy_data(contents.data_directory) self.logger.info("data directory restored successfully") - self.logger.info("backup restore complete") diff --git a/tests/unit_tests/services_tests/backup_v2_tests/test_backup_v2.py b/tests/unit_tests/services_tests/backup_v2_tests/test_backup_v2.py index 9f38ced16..754b632fa 100644 --- a/tests/unit_tests/services_tests/backup_v2_tests/test_backup_v2.py +++ b/tests/unit_tests/services_tests/backup_v2_tests/test_backup_v2.py @@ -249,6 +249,8 @@ def test_database_restore_data(): settings = get_app_settings() backup_v2 = BackupV2(settings.DB_URL) + + backup_v2.directories.BACKUP_DIR.mkdir(parents=True, exist_ok=True) original_data_backup = backup_v2.backup() try: