Fix startup_check and verification
This commit is contained in:
parent
761204aa80
commit
45163eafb5
|
@ -19,6 +19,7 @@ from rare import cache_dir, resources_path
|
||||||
from rare.components.dialogs.launch_dialog import LaunchDialog
|
from rare.components.dialogs.launch_dialog import LaunchDialog
|
||||||
from rare.components.main_window import MainWindow
|
from rare.components.main_window import MainWindow
|
||||||
from rare.components.tray_icon import TrayIcon
|
from rare.components.tray_icon import TrayIcon
|
||||||
|
from rare.utils import legendary_utils
|
||||||
from rare.utils.utils import set_color_pallete, set_style_sheet
|
from rare.utils.utils import set_color_pallete, set_style_sheet
|
||||||
|
|
||||||
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
|
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
|
||||||
|
@ -158,11 +159,15 @@ class App(QApplication):
|
||||||
self.mainwindow.show_window_centralized()
|
self.mainwindow.show_window_centralized()
|
||||||
|
|
||||||
def start_app(self):
|
def start_app(self):
|
||||||
|
|
||||||
for igame in self.core.get_installed_list():
|
for igame in self.core.get_installed_list():
|
||||||
if not os.path.exists(igame.executable):
|
if not os.path.exists(igame.install_path):
|
||||||
|
legendary_utils.uninstall(igame.app_name, self.core)
|
||||||
|
logger.info(f"Uninstalled {igame.title}, because no game files exist")
|
||||||
|
continue
|
||||||
|
if not os.path.exists(os.path.join(igame.install_path, igame.executable)):
|
||||||
igame.needs_verification = True
|
igame.needs_verification = True
|
||||||
self.core.lgd.set_installed_game(igame.app_name, igame)
|
self.core.lgd.set_installed_game(igame.app_name, igame)
|
||||||
|
logger.info(f"{igame.title} needs verification")
|
||||||
|
|
||||||
self.mainwindow = MainWindow()
|
self.mainwindow = MainWindow()
|
||||||
self.launch_dialog.close()
|
self.launch_dialog.close()
|
||||||
|
|
|
@ -88,17 +88,17 @@ class GameInfo(QWidget, Ui_GameInfo):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
self.verify_widget.setCurrentIndex(1)
|
self.verify_widget.setCurrentIndex(1)
|
||||||
verify_worker = VerifyWorker(self.core, self.game.app_name)
|
verify_worker = VerifyWorker(self.game.app_name)
|
||||||
verify_worker.signals.status.connect(self.verify_staistics)
|
verify_worker.signals.status.connect(self.verify_staistics)
|
||||||
verify_worker.signals.summary.connect(self.finish_verify)
|
verify_worker.signals.summary.connect(self.finish_verify)
|
||||||
self.verify_progress.setValue(0)
|
self.verify_progress.setValue(0)
|
||||||
self.verify_threads[self.game.app_name] = verify_worker
|
self.verify_threads[self.game.app_name] = verify_worker
|
||||||
self.verify_pool.start(verify_worker)
|
self.verify_pool.start(verify_worker)
|
||||||
|
|
||||||
def verify_staistics(self, progress):
|
def verify_staistics(self, num, total, app_name):
|
||||||
# checked, max, app_name
|
# checked, max, app_name
|
||||||
if progress[2] == self.game.app_name:
|
if app_name == self.game.app_name:
|
||||||
self.verify_progress.setValue(progress[0] * 100 // progress[1])
|
self.verify_progress.setValue(num * 100 // total)
|
||||||
|
|
||||||
def finish_verify(self, failed, missing, app_name):
|
def finish_verify(self, failed, missing, app_name):
|
||||||
if failed == missing == 0:
|
if failed == missing == 0:
|
||||||
|
|
|
@ -4,11 +4,11 @@ import shutil
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QRunnable
|
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QRunnable
|
||||||
from PyQt5.QtWidgets import QMessageBox
|
|
||||||
|
|
||||||
from legendary.core import LegendaryCore
|
from legendary.core import LegendaryCore
|
||||||
from legendary.models.game import VerifyResult
|
from legendary.models.game import VerifyResult
|
||||||
from legendary.utils.lfs import validate_files
|
from legendary.utils.lfs import validate_files
|
||||||
|
from rare import shared
|
||||||
|
|
||||||
logger = getLogger("Legendary Utils")
|
logger = getLogger("Legendary Utils")
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ def update_manifest(app_name: str, core: LegendaryCore):
|
||||||
|
|
||||||
|
|
||||||
class VerifySignals(QObject):
|
class VerifySignals(QObject):
|
||||||
status = pyqtSignal(tuple)
|
status = pyqtSignal(int, int, str)
|
||||||
summary = pyqtSignal(int, int, str)
|
summary = pyqtSignal(int, int, str)
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,97 +100,65 @@ class VerifyWorker(QRunnable):
|
||||||
num: int = 0
|
num: int = 0
|
||||||
total: int = 1 # set default to 1 to avoid DivisionByZero before it is initialized
|
total: int = 1 # set default to 1 to avoid DivisionByZero before it is initialized
|
||||||
|
|
||||||
def __init__(self, core, app_name):
|
def __init__(self, app_name):
|
||||||
super(VerifyWorker, self).__init__()
|
super(VerifyWorker, self).__init__()
|
||||||
self.core, self.app_name = core, app_name
|
self.app_name = app_name
|
||||||
self.signals = VerifySignals()
|
self.signals = VerifySignals()
|
||||||
self.setAutoDelete(True)
|
self.setAutoDelete(True)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.core.is_installed(self.app_name):
|
if not shared.core.is_installed(self.app_name):
|
||||||
logger.error(f'Game "{self.app_name}" is not installed')
|
logger.error(f'Game "{self.app_name}" is not installed')
|
||||||
return
|
return
|
||||||
igame = self.core.get_installed_game(self.app_name)
|
|
||||||
|
|
||||||
logger.info(f'Loading installed manifest for "{igame.title}"')
|
logger.info(f'Loading installed manifest for "{self.app_name}"')
|
||||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
igame = shared.core.get_installed_game(self.app_name)
|
||||||
if not manifest_data:
|
manifest_data, _ = shared.core.get_installed_manifest(self.app_name)
|
||||||
update_manifest(self.app_name, self.core)
|
manifest = shared.core.load_manifest(manifest_data)
|
||||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
|
||||||
if not manifest_data:
|
|
||||||
self.signals.summary.emit(-1, -1, self.app_name)
|
|
||||||
return
|
|
||||||
|
|
||||||
manifest = self.core.load_manifest(manifest_data)
|
files = sorted(manifest.file_manifest_list.elements,
|
||||||
|
key=lambda a: a.filename.lower())
|
||||||
files = sorted(
|
|
||||||
manifest.file_manifest_list.elements, key=lambda a: a.filename.lower()
|
|
||||||
)
|
|
||||||
|
|
||||||
# build list of hashes
|
# build list of hashes
|
||||||
file_list = [(f.filename, f.sha_hash.hex()) for f in files]
|
file_list = [(f.filename, f.sha_hash.hex()) for f in files]
|
||||||
self.total = len(file_list)
|
total = len(file_list)
|
||||||
self.num = 0
|
num = 0
|
||||||
failed = []
|
failed = []
|
||||||
missing = []
|
missing = []
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
logger.info(f'Verifying "{igame.title}" version "{manifest.meta.build_version}"')
|
||||||
|
|
||||||
logger.info(
|
|
||||||
f'Verifying "{igame.title}" version "{manifest.meta.build_version}"'
|
|
||||||
)
|
|
||||||
repair_file = []
|
repair_file = []
|
||||||
try:
|
for result, path, result_hash, _ in validate_files(igame.install_path, file_list):
|
||||||
for result, path, result_hash in validate_files(
|
num += 1
|
||||||
igame.install_path, file_list
|
self.signals.status.emit(num, total, self.app_name)
|
||||||
):
|
|
||||||
self.signals.status.emit((self.num, self.total, self.app_name))
|
|
||||||
self.num += 1
|
|
||||||
|
|
||||||
if result == VerifyResult.HASH_MATCH:
|
if result == VerifyResult.HASH_MATCH:
|
||||||
repair_file.append(f"{result_hash}:{path}")
|
repair_file.append(f"{result_hash}:{path}")
|
||||||
continue
|
continue
|
||||||
elif result == VerifyResult.HASH_MISMATCH:
|
elif result == VerifyResult.HASH_MISMATCH:
|
||||||
logger.error(f'File does not match hash: "{path}"')
|
logger.error(f'File does not match hash: "{path}"')
|
||||||
repair_file.append(f"{result_hash}:{path}")
|
repair_file.append(f"{result_hash}:{path}")
|
||||||
failed.append(path)
|
failed.append(path)
|
||||||
elif result == VerifyResult.FILE_MISSING:
|
elif result == VerifyResult.FILE_MISSING:
|
||||||
logger.error(f'File is missing: "{path}"')
|
logger.error(f'File is missing: "{path}"')
|
||||||
missing.append(path)
|
missing.append(path)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(f'Other failure (see log), treating file as missing: "{path}"')
|
||||||
f'Other failure (see log), treating file as missing: "{path}"'
|
missing.append(path)
|
||||||
)
|
|
||||||
missing.append(path)
|
|
||||||
except OSError as e:
|
|
||||||
QMessageBox.warning(
|
|
||||||
None, "Error", _translate("VerifyWorker", "Path does not exist")
|
|
||||||
)
|
|
||||||
logger.error(str(e))
|
|
||||||
except ValueError as e:
|
|
||||||
QMessageBox.warning(
|
|
||||||
None, "Error", _translate("VerifyWorker", "No files to validate")
|
|
||||||
)
|
|
||||||
logger.error(str(e))
|
|
||||||
|
|
||||||
# always write repair file, even if all match
|
# always write repair file, even if all match
|
||||||
if repair_file:
|
if repair_file:
|
||||||
repair_filename = os.path.join(
|
repair_filename = os.path.join(shared.core.lgd.get_tmp_path(), f'{self.app_name}.repair')
|
||||||
self.core.lgd.get_tmp_path(), f"{self.app_name}.repair"
|
with open(repair_filename, 'w') as f:
|
||||||
)
|
f.write('\n'.join(repair_file))
|
||||||
with open(repair_filename, "w") as f:
|
|
||||||
f.write("\n".join(repair_file))
|
|
||||||
logger.debug(f'Written repair file to "{repair_filename}"')
|
logger.debug(f'Written repair file to "{repair_filename}"')
|
||||||
|
|
||||||
if not missing and not failed:
|
if not missing and not failed:
|
||||||
logger.info("Verification finished successfully.")
|
logger.info('Verification finished successfully.')
|
||||||
self.signals.summary.emit(0, 0, self.app_name)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.warning(
|
||||||
f"Verification finished, {len(failed)} file(s) corrupted, {len(missing)} file(s) are missing."
|
f'Verification failed, {len(failed)} file(s) corrupted, {len(missing)} file(s) are missing.')
|
||||||
)
|
self.signals.summary.emit(len(failed), len(missing), self.app_name)
|
||||||
self.signals.summary.emit(len(failed), len(missing), self.app_name)
|
|
||||||
|
|
||||||
|
|
||||||
def import_game(core: LegendaryCore, app_name: str, path: str) -> str:
|
def import_game(core: LegendaryCore, app_name: str, path: str) -> str:
|
||||||
|
|
Loading…
Reference in a new issue