From 004423fb3000a99f2f8625e2f18d36c733613a9b Mon Sep 17 00:00:00 2001 From: deajan Date: Wed, 16 Apr 2025 21:02:04 +0200 Subject: [PATCH] GUI: Add --no-lock when running viewer, see #155 --- npbackup/__main__.py | 6 ++++++ npbackup/core/runner.py | 13 +++++++++++++ npbackup/gui/__main__.py | 10 ++++++++++ npbackup/gui/helpers.py | 3 +++ npbackup/restic_wrapper/__init__.py | 18 ++++++++++++++++-- npbackup/runner_interface.py | 1 + 6 files changed, 49 insertions(+), 2 deletions(-) diff --git a/npbackup/__main__.py b/npbackup/__main__.py index cc1735c..f4e7ab6 100644 --- a/npbackup/__main__.py +++ b/npbackup/__main__.py @@ -282,6 +282,11 @@ This is free software, and you are welcome to redistribute it under certain cond action="store_true", help="Run operations without cache", ) + parser.add_argument( + "--no-lock", + action="store_true", + help="Run operations without lock", + ) parser.add_argument("--license", action="store_true", help="Show license") parser.add_argument( "--auto-upgrade", action="store_true", help="Auto upgrade NPBackup" @@ -605,6 +610,7 @@ This is free software, and you are welcome to redistribute it under certain cond "json_output": args.json, "backend_binary": backend_binary, "no_cache": args.no_cache, + "no_lock": args.no_lock, "operation": None, "op_args": {}, } diff --git a/npbackup/core/runner.py b/npbackup/core/runner.py index 51baaa6..a42b262 100644 --- a/npbackup/core/runner.py +++ b/npbackup/core/runner.py @@ -271,6 +271,7 @@ class NPBackupRunner: self._struct_output = False self._binary = None self._no_cache = False + self._no_lock = False self.restic_runner = None self.minimum_backup_age = None self._exec_time = None @@ -324,6 +325,17 @@ class NPBackupRunner: self.write_logs(msg, level="critical", raise_error="ValueError") self._no_cache = value + @property + def no_lock(self) -> bool: + return self._no_lock + + @no_lock.setter + def no_lock(self, value: bool): + if not isinstance(value, bool): + msg = f"Bogus no_lock parameter given: {value}" + self.write_logs(msg, level="critical", raise_error="ValueError") + self._no_lock = value + @property def verbose(self): return self._verbose @@ -957,6 +969,7 @@ class NPBackupRunner: self.restic_runner.verbose = self.verbose self.restic_runner.dry_run = self.dry_run self.restic_runner.no_cache = self.no_cache + self.restic_runner.no_lock = self.no_lock self.restic_runner.live_output = self.live_output self.restic_runner.json_output = self.json_output self.restic_runner.struct_output = self.struct_output diff --git a/npbackup/gui/__main__.py b/npbackup/gui/__main__.py index 82171b5..1e5a610 100644 --- a/npbackup/gui/__main__.py +++ b/npbackup/gui/__main__.py @@ -63,6 +63,7 @@ from npbackup.restic_wrapper import schema logger = getLogger() backend_binary = None +__no_lock = False # This bool allows to not show errors on freshly configured repos or first runs, when repo isn't initialized yet # Also prevents showing errors when config was just changed @@ -334,6 +335,7 @@ def ls_window(parent_window: sg.Window, repo_config: dict, snapshot_id: str) -> __autoclose=True, __compact=True, __backend_binary=backend_binary, + __no_lock=__no_lock, ) if not result or not result["result"]: sg.Popup(_t("main_gui.snapshot_is_empty")) @@ -463,6 +465,7 @@ def restore_window( restore_includes=restore_includes, __backend_binary=backend_binary, __autoclose=True, + __no_lock=__no_lock, ) return result["result"] @@ -515,6 +518,7 @@ def backup(repo_config: dict) -> bool: __compact=False, __gui_msg=gui_msg, __backend_binary=backend_binary, + __no_lock=__no_lock, ) return result["result"] @@ -530,6 +534,7 @@ def forget_snapshot(repo_config: dict, snapshot_ids: List[str]) -> bool: __gui_msg=gui_msg, __autoclose=True, __backend_binary=backend_binary, + __no_lock=__no_lock, ) return result["result"] @@ -537,6 +542,7 @@ def forget_snapshot(repo_config: dict, snapshot_ids: List[str]) -> bool: def _main_gui(viewer_mode: bool): global logger global backend_binary + global __no_lock global GUI_STATUS_IGNORE_ERRORS def check_for_auto_upgrade(config_file: str, full_config: dict) -> bool: @@ -645,6 +651,7 @@ def _main_gui(viewer_mode: bool): __compact=True, __backend_binary=backend_binary, __ignore_errors=GUI_STATUS_IGNORE_ERRORS, + __no_lock=__no_lock, ) GUI_STATUS_IGNORE_ERRORS = False try: @@ -879,6 +886,9 @@ def _main_gui(viewer_mode: bool): sg.PopupError(msg, keep_on_top=True) sys.exit(73) + if viewer_mode: + __no_lock = True + # Let's try to read standard restic repository env variables viewer_repo_uri = os.environ.get("RESTIC_REPOSITORY", None) viewer_repo_password = os.environ.get("RESTIC_PASSWORD", None) diff --git a/npbackup/gui/helpers.py b/npbackup/gui/helpers.py index ea32095..64b9481 100644 --- a/npbackup/gui/helpers.py +++ b/npbackup/gui/helpers.py @@ -83,6 +83,7 @@ def gui_thread_runner( __stdout: bool = True, __backend_binary: str = None, __ignore_errors: bool = False, + __no_lock: bool = False, *args, **kwargs, ) -> Union[dict, str]: @@ -126,6 +127,8 @@ def gui_thread_runner( if __ignore_errors: runner.produce_metrics = False + runner.no_lock = __no_lock + # We'll always use json output in GUI mode runner.json_output = True # in GUI mode, we'll use struct output instead of json whenever it's possible diff --git a/npbackup/restic_wrapper/__init__.py b/npbackup/restic_wrapper/__init__.py index e5d1cf6..0747228 100644 --- a/npbackup/restic_wrapper/__init__.py +++ b/npbackup/restic_wrapper/__init__.py @@ -7,8 +7,8 @@ __intname__ = "npbackup.restic_wrapper" __author__ = "Orsiris de Jong" __copyright__ = "Copyright (C) 2022-2025 NetInvent" __license__ = "GPL-3.0-only" -__build__ = "2025041001" -__version__ = "2.6.0" +__build__ = "2025041601" +__version__ = "2.6.1" from typing import Tuple, List, Optional, Callable, Union @@ -75,6 +75,7 @@ class ResticRunner: self._live_output = False self._dry_run = False self._no_cache = False + self._no_lock = False self._json_output = False self._struct_output = False @@ -251,6 +252,17 @@ class ResticRunner: else: raise ValueError("Bogus no_cache value given") + @property + def no_lock(self) -> bool: + return self._no_lock + + @no_lock.setter + def no_lock(self, value: bool): + if isinstance(value, bool): + self._no_lock = value + else: + raise ValueError("Bogus no_lock value given") + @property def json_output(self) -> bool: return self._json_output @@ -653,6 +665,8 @@ class ResticRunner: args += " --json" if self.no_cache: args += " --no-cache" + if self.no_lock: + args += " --no-lock" return args def init( diff --git a/npbackup/runner_interface.py b/npbackup/runner_interface.py index 47a65ea..084bbd6 100644 --- a/npbackup/runner_interface.py +++ b/npbackup/runner_interface.py @@ -55,6 +55,7 @@ def entrypoint(*args, **kwargs): npbackup_runner.live_output = not json_output npbackup_runner.json_output = json_output npbackup_runner.no_cache = kwargs.pop("no_cache", False) + npbackup_runner.no_lock = kwargs.pop("no_lock", False) if backend_binary: npbackup_runner.binary = backend_binary result = npbackup_runner.__getattribute__(operation)(