mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-23 10:45:20 -05:00
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com> Co-authored-by: Michael Genson <genson.michael@gmail.com>
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user