11import logging
22import os
33import sys
4+ from typing import Any , Dict , List , Tuple
45
56from PyQt5 import QtCore
67from PyQt5 .QtWidgets import QMessageBox
78
9+ from vorta .borg .break_lock import BorgBreakJob
810from vorta .borg .create import BorgCreateJob
11+ from vorta .borg .jobs_manager import JobsManager
912from vorta .borg .version import BorgVersionJob
10- from vorta .borg .break_lock import BorgBreakJob
11- from vorta .config import TEMP_DIR , PROFILE_BOOTSTRAP_FILE
13+ from vorta .config import PROFILE_BOOTSTRAP_FILE , TEMP_DIR
1214from vorta .i18n import init_translations , translate
13- from vorta .store . models import BackupProfileModel , SettingsModel
14- from vorta .store . connection import cleanup_db
15+ from vorta .notifications import VortaNotifications
16+ from vorta .profile_export import ProfileExport
1517from vorta .qt_single_application import QtSingleApplication
1618from vorta .scheduler import VortaScheduler
17- from vorta .borg .jobs_manager import JobsManager
19+ from vorta .store .connection import cleanup_db
20+ from vorta .store .models import BackupProfileModel , SettingsModel
1821from vorta .tray_menu import TrayMenu
1922from vorta .utils import borg_compat , parse_args
2023from vorta .views .main_window import MainWindow
21- from vorta .notifications import VortaNotifications
22- from vorta .profile_export import ProfileExport
2324
2425logger = logging .getLogger (__name__ )
2526
@@ -39,7 +40,7 @@ class VortaApp(QtSingleApplication):
3940 backup_cancelled_event = QtCore .pyqtSignal ()
4041 backup_log_event = QtCore .pyqtSignal (str , dict )
4142 backup_progress_event = QtCore .pyqtSignal (str )
42- check_failed_event = QtCore .pyqtSignal (str )
43+ check_failed_event = QtCore .pyqtSignal (dict )
4344
4445 def __init__ (self , args_raw , single_app = False ):
4546 super ().__init__ (APP_ID , args_raw )
@@ -288,11 +289,62 @@ def bootstrap_profile(self, bootstrap_file=PROFILE_BOOTSTRAP_FILE):
288289 default_profile = BackupProfileModel (name = 'Default' )
289290 default_profile .save ()
290291
291- def check_failed_response (self , repo_url ):
292- msg = QMessageBox ()
293- msg .setIcon (QMessageBox .Critical )
294- msg .setStandardButtons (QMessageBox .Ok )
295- msg .setWindowTitle (self .tr ('Repo Check Failed' ))
296- msg .setText (self .tr ('Repository data check for repo %s failed' ) % repo_url )
297- msg .setInformativeText (self .tr ('Repair or recreate the repository soon to avoid missing data.' ))
298- msg .exec ()
292+ def check_failed_response (self , result : Dict [str , Any ]):
293+ """
294+ Process the signal that a repo consistency check failed.
295+
296+ Displays a `QMessageBox` with an error message depending on the
297+ return code of the `BorgJob`.
298+
299+ Parameters
300+ ----------
301+ repo_url : str
302+ The url of the repo of concern
303+ """
304+ # extract data from the params for the borg job
305+ repo_url = result ['params' ]['repo_url' ]
306+ returncode = result ['returncode' ]
307+ errors : List [Tuple [int , str ]] = result ['errors' ]
308+ error_message = errors [0 ][1 ] if errors else ''
309+
310+ # Switch over returncodes
311+ if returncode == 0 :
312+ # No fail
313+ logger .warning (
314+ 'VortaApp.check_failed_response was called with returncode 0' )
315+ elif returncode == 130 :
316+ # Keyboard interupt
317+ pass
318+ else : # Real error
319+ # Create QMessageBox
320+ msg = QMessageBox ()
321+ msg .setIcon (QMessageBox .Icon .Critical ) # changed for warning
322+ msg .setStandardButtons (QMessageBox .Ok )
323+ msg .setWindowTitle (self .tr ('Repo Check Failed' ))
324+
325+ if returncode == 1 :
326+ # warning
327+ msg .setIcon (QMessageBox .Icon .Warning )
328+ text = self .tr ('Borg exited with a warning message. See logs for details.' )
329+ infotext = error_message
330+ elif returncode > 128 :
331+ # 128+N - killed by signal N (e.g. 137 == kill -9)
332+ signal = returncode - 128
333+ text = (
334+ self .tr ('Repository data check for repo was killed by signal %s.' )
335+ % (signal )
336+ )
337+ infotext = self .tr ('The process running the check job got a kill signal. Try again.' )
338+ else :
339+ # Real error
340+ text = (
341+ self .tr ('Repository data check for repo %s failed. Error code %s' )
342+ % (repo_url , returncode )
343+ )
344+ infotext = error_message + '\n '
345+ infotext += self .tr ('Consider repairing or recreating the repository soon to avoid missing data.' )
346+
347+ msg .setText (text )
348+ msg .setInformativeText (infotext )
349+ # Display messagebox
350+ msg .exec ()
0 commit comments