From b32e5d32b000566eff44fa59385c97ce3c5fe04b Mon Sep 17 00:00:00 2001 From: KKlochko Date: Fri, 17 Jan 2025 20:49:28 +0200 Subject: [PATCH] Add the restore command. --- .../service/backup_restore_service.py | 22 +++++++++++++ .../configuration/configuration.py | 13 ++++++++ .../cli/components/backup/backup.py | 33 ++++++++++++++++++- .../prompts/applications/prompts/__init__.py | 4 +++ .../prompts/choose_prompt_port.py | 8 +++++ .../applications/prompts/fzf_prompt.py | 9 +++++ 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 tui_rsync/core/shared_kernel/components/backup/application/service/backup_restore_service.py create mode 100644 tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/__init__.py create mode 100644 tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/choose_prompt_port.py create mode 100644 tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/fzf_prompt.py diff --git a/tui_rsync/core/shared_kernel/components/backup/application/service/backup_restore_service.py b/tui_rsync/core/shared_kernel/components/backup/application/service/backup_restore_service.py new file mode 100644 index 0000000..f4aa088 --- /dev/null +++ b/tui_rsync/core/shared_kernel/components/backup/application/service/backup_restore_service.py @@ -0,0 +1,22 @@ +from tui_rsync.core.components.backup.application.backup_commands import BackupSyncCommand, BackupSyncCommandDryRun +from tui_rsync.core.components.backup_plan.application.repository import BackupPlanRepositoryPort +from tui_rsync.core.shared_kernel.components.common import UUID +from tui_rsync.user_interface.cli.shared_kernel.components.prompts.applications.prompts import ChoosePromptPort + + +class BackupRestoreService: + def __init__(self, backup_plan_repository: BackupPlanRepositoryPort): + self.backup_plan_repository = backup_plan_repository + + def sync_by_plan_id(self, uuid: UUID, choose_prompt: ChoosePromptPort, args: str = '', dry_run: bool = False): + backup_plan = self.backup_plan_repository.get_by_id(uuid) + + destinations = (destination.path for destination in backup_plan.destinations) + destination = choose_prompt.choose(destinations) + + if dry_run: + backup_command = BackupSyncCommandDryRun(destination, backup_plan.source.path, args) + backup_command.run() + else: + backup_command = BackupSyncCommand(destination, backup_plan.source.path, args) + backup_command.run() diff --git a/tui_rsync/infrastructure/configuration/configuration.py b/tui_rsync/infrastructure/configuration/configuration.py index 361ea96..a0b5514 100644 --- a/tui_rsync/infrastructure/configuration/configuration.py +++ b/tui_rsync/infrastructure/configuration/configuration.py @@ -8,8 +8,11 @@ from tui_rsync.core.components.backup_plan.application.services.backup_plan_serv from tui_rsync.core.ports.configuration import UserDataPathsPort from tui_rsync.core.ports.orm import DatabaseManagerPort from tui_rsync.core.shared_kernel.components.backup.application.service import BackupSyncService +from tui_rsync.core.shared_kernel.components.backup.application.service.backup_restore_service import \ + BackupRestoreService from tui_rsync.infrastructure.configuration import UserDataPaths from tui_rsync.infrastructure.orm import SqliteDatabaseManager +from tui_rsync.user_interface.cli.shared_kernel.components.prompts.applications.prompts import ChoosePromptFzf class Configuration(Module): @@ -47,3 +50,13 @@ class Configuration(Module): @singleton def provide_backup_sync_service(self, backup_plan_repository: BackupPlanRepositoryPort) -> BackupSyncService: return BackupSyncService(backup_plan_repository) + + @provider + @singleton + def provide_backup_restore_service(self, backup_plan_repository: BackupPlanRepositoryPort) -> BackupRestoreService: + return BackupRestoreService(backup_plan_repository) + + @provider + @singleton + def provide_choose_prompt_fzf(self) -> ChoosePromptFzf: + return ChoosePromptFzf() diff --git a/tui_rsync/user_interface/cli/components/backup/backup.py b/tui_rsync/user_interface/cli/components/backup/backup.py index 39802f2..a9eaa51 100644 --- a/tui_rsync/user_interface/cli/components/backup/backup.py +++ b/tui_rsync/user_interface/cli/components/backup/backup.py @@ -22,8 +22,11 @@ from rich.console import Console import typer from tui_rsync.core.shared_kernel.components.backup.application.service import BackupSyncService +from tui_rsync.core.shared_kernel.components.backup.application.service.backup_restore_service import \ + BackupRestoreService from tui_rsync.core.shared_kernel.components.common import UUID from tui_rsync.infrastructure.configuration import CurrentConfiguration +from tui_rsync.user_interface.cli.shared_kernel.components.prompts.applications.prompts import ChoosePromptFzf console = Console() sync = typer.Typer() @@ -42,7 +45,7 @@ def one( ) ): """ - [green b]Sync[/] a [yellow]source[/] with the [yellow b]label[/] and its backups. + [green b]Sync[/] a [yellow]source[/] to [yellow]destination[/] for the [yellow b]backup plan id[/]. [yellow b]Skips[/] if not available. """ @@ -54,3 +57,31 @@ def one( # TODO add args service.sync_by_plan_id(UUID(id), '-avuP', dry) + + +@sync.command() +def restore( + id: str = typer.Option( + None, "--id", "-i", + help="[b]The id[/] is an uniq identification of a [b]backup plan[/].", + show_default=False + ), + dry: bool = typer.Option( + False, "-d", "--dry-run", + help="The command will [b]show[/] information about what will be changed.", + ) +): + """ + [green b]Sync[/] a [yellow]destination[/] to the [yellow]source[/] for the [yellow b]backup plan id[/]. + [yellow b]Skips[/] if not available. + """ + + service: BackupRestoreService = CurrentConfiguration.get(BackupRestoreService) + choose_prompt: ChoosePromptFzf = CurrentConfiguration.get(ChoosePromptFzf) + + if id is None: + console.print("[red b][ERROR][/] Backup plan does not exists!!!") + return + + # TODO add args + service.sync_by_plan_id(UUID(id), choose_prompt, '-avuP', dry) diff --git a/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/__init__.py b/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/__init__.py new file mode 100644 index 0000000..2f7d4c5 --- /dev/null +++ b/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/__init__.py @@ -0,0 +1,4 @@ +from .choose_prompt_port import ChoosePromptPort +from .fzf_prompt import ChoosePromptFzf + +__all__ = ['ChoosePromptPort', 'ChoosePromptFzf'] diff --git a/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/choose_prompt_port.py b/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/choose_prompt_port.py new file mode 100644 index 0000000..a2b5c1f --- /dev/null +++ b/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/choose_prompt_port.py @@ -0,0 +1,8 @@ +from abc import ABC, abstractmethod + + +class ChoosePromptPort(ABC): + @staticmethod + @abstractmethod + def choose(iterator) -> str: + pass diff --git a/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/fzf_prompt.py b/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/fzf_prompt.py new file mode 100644 index 0000000..0aa08f9 --- /dev/null +++ b/tui_rsync/user_interface/cli/shared_kernel/components/prompts/applications/prompts/fzf_prompt.py @@ -0,0 +1,9 @@ +from .choose_prompt_port import ChoosePromptPort +from pyfzf import FzfPrompt + + +class ChoosePromptFzf(ChoosePromptPort): + @staticmethod + def choose(iterator) -> str: + fzf = FzfPrompt() + return fzf.prompt(iterator)[0]