From 4f0b6057863a267e901c46a1a0cbd665d43cf117 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Thu, 25 May 2023 11:25:13 -0600 Subject: [PATCH] logging_handler.py: Reveal log on crash --- CHANGELOG.md | 10 +++++++++ resources/arguments.py | 2 +- resources/logging_handler.py | 3 +++ resources/macos_installer_handler.py | 3 +-- .../wx_gui/gui_macos_installer_download.py | 17 +++++++++++--- resources/wx_gui/gui_macos_installer_flash.py | 22 ++++++++++++++----- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b009160da..ef13677db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ ## 0.6.7 - Backend changes: - Call `setpgrp()` to prevent app from being killed if parent process is killed (ie. LaunchAgents) + - Rework logging handler: + - Implement formatted logging + - Allowing easier debugging + - Implement per-version file logging + - ex. OpenCore-Patcher-0.6.7.log + - Remove old logs after 1 week of inactivity + - Reduce log rollover to 1MB + - Reveal log file in Finder on main thread crash + - Resolve SharedSupport.dmg pathing error during macOS Installer Verification + - Applicable to systems with 2 (or more) USB Installers with the same name plugged in ## 0.6.6 - Implement option to disable ColorSync downgrade on HD 3000 Macs diff --git a/resources/arguments.py b/resources/arguments.py index d96672564..62d6eb3d7 100644 --- a/resources/arguments.py +++ b/resources/arguments.py @@ -50,7 +50,7 @@ class arguments: """ Enter validation mode """ - + logging.info("Set Validation Mode") validation.PatcherValidation(self.constants) diff --git a/resources/logging_handler.py b/resources/logging_handler.py index 6590509b4..d8136725d 100644 --- a/resources/logging_handler.py +++ b/resources/logging_handler.py @@ -216,6 +216,9 @@ class InitializeLoggingSupport: applescript.AppleScript(f'display dialog "{error_msg}" with title "OpenCore Legacy Patcher ({self.constants.patcher_version})" buttons {{"OK"}} default button "OK" with icon caution giving up after 30').run() + # Open log location + subprocess.run(["open", "--reveal", self.log_filepath]) + def custom_thread_excepthook(args) -> None: """ diff --git a/resources/macos_installer_handler.py b/resources/macos_installer_handler.py index a7e08d975..04a8f6bd2 100644 --- a/resources/macos_installer_handler.py +++ b/resources/macos_installer_handler.py @@ -53,7 +53,7 @@ class InstallerCreation(): bool: True if successful, False otherwise """ - logging.info("Extracting macOS installer from InstallAssistant.pkg\n This may take some time") + logging.info("Extracting macOS installer from InstallAssistant.pkg") try: applescript.AppleScript( f'''do shell script "installer -pkg {Path(download_path)}/InstallAssistant.pkg -target /"''' @@ -201,7 +201,6 @@ fi if not any(all_disks[disk]['removable'] is False for partition in all_disks[disk]): continue - logging.info(f"disk {disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})") list_disks.update({ disk: { "identifier": all_disks[disk]["identifier"], diff --git a/resources/wx_gui/gui_macos_installer_download.py b/resources/wx_gui/gui_macos_installer_download.py index c80b4949b..adc569164 100644 --- a/resources/wx_gui/gui_macos_installer_download.py +++ b/resources/wx_gui/gui_macos_installer_download.py @@ -36,6 +36,8 @@ class macOSInstallerDownloadFrame(wx.Frame): self.available_installers = None self.available_installers_latest = None + self.catalog_seed: macos_installer_handler.SeedType = macos_installer_handler.SeedType.DeveloperSeed + self.frame_modal = wx.Dialog(parent, title=title, size=(330, 200)) self._generate_elements(self.frame_modal) @@ -102,7 +104,8 @@ class macOSInstallerDownloadFrame(wx.Frame): # Grab installer catalog def _fetch_installers(): - remote_obj = macos_installer_handler.RemoteInstallerCatalog(seed_override=macos_installer_handler.SeedType.DeveloperSeed) + logging.info(f"Fetching installer catalog: {macos_installer_handler.SeedType(self.catalog_seed).name}") + remote_obj = macos_installer_handler.RemoteInstallerCatalog(seed_override=self.catalog_seed) self.available_installers = remote_obj.available_apps self.available_installers_latest = remote_obj.available_apps_latest @@ -138,8 +141,9 @@ class macOSInstallerDownloadFrame(wx.Frame): installers = self.available_installers_latest if show_full is False else self.available_installers if installers: spacer = 0 + logging.info(f"Available installers on SUCatalog ({'All entries' if show_full else 'Latest only'}):") for app in installers: - logging.info(f"macOS {installers[app]['Version']} ({installers[app]['Build']}):\n - Size: {utilities.human_fmt(installers[app]['Size'])}\n - Source: {installers[app]['Source']}\n - Variant: {installers[app]['Variant']}\n - Link: {installers[app]['Link']}\n") + logging.info(f"- macOS {installers[app]['Version']} ({installers[app]['Build']}):\n - Size: {utilities.human_fmt(installers[app]['Size'])}\n - Source: {installers[app]['Source']}\n - Variant: {installers[app]['Variant']}\n - Link: {installers[app]['Link']}\n") extra = " Beta" if installers[app]['Variant'] in ["DeveloperSeed" , "PublicSeed"] else "" installer_button = wx.Button(dialog, label=f"macOS {installers[app]['Version']}{extra} ({installers[app]['Build']} - {utilities.human_fmt(installers[app]['Size'])})", pos=(-1, subtitle_label.GetPosition()[1] + subtitle_label.GetSize()[1] + 5 + spacer), size=(270, 30)) @@ -172,6 +176,7 @@ class macOSInstallerDownloadFrame(wx.Frame): """ Download macOS installer """ + logging.info(f"Selected macOS {app['Version']} ({app['Build']})") # Notify user whether their model is compatible with the selected installer problems = [] @@ -185,6 +190,7 @@ class macOSInstallerDownloadFrame(wx.Frame): problems.append("Lack of internal Keyboard/Mouse in macOS installer.") if problems: + logging.warning(f"Potential issues with {model} and {app['Version']} ({app['Build']}): {problems}") problems = "\n".join(problems) dlg = wx.MessageDialog(self.frame_modal, f"Your model ({model}) may not be fully supported by this installer. You may encounter the following issues:\n\n{problems}\n\nFor more information, see associated page. Otherwise, we recommend using macOS Monterey", "Potential Issues", wx.YES_NO | wx.CANCEL | wx.ICON_WARNING) dlg.SetYesNoCancelLabels("View Github Issue", "Download Anyways", "Cancel") @@ -198,6 +204,7 @@ class macOSInstallerDownloadFrame(wx.Frame): host_space = utilities.get_free_space() needed_space = app['Size'] * 2 if host_space < needed_space: + logging.error(f"Insufficient space to download and extract: {utilities.human_fmt(host_space)} available vs {utilities.human_fmt(needed_space)} required") dlg = wx.MessageDialog(self.frame_modal, f"You do not have enough free space to download and extract this installer. Please free up some space and try again\n\n{utilities.human_fmt(host_space)} available vs {utilities.human_fmt(needed_space)} required", "Insufficient Space", wx.OK | wx.ICON_WARNING) dlg.ShowModal() return @@ -249,6 +256,7 @@ class macOSInstallerDownloadFrame(wx.Frame): chunklist_stream = network_handler.NetworkUtilities().get(chunklist_link).content if chunklist_stream: + logging.info("Validating macOS installer") utilities.disable_sleep_while_running() chunk_obj = integrity_verification.ChunklistVerification(self.constants.payload_path / Path("InstallAssistant.pkg"), chunklist_stream) if chunk_obj.chunks: @@ -265,10 +273,13 @@ class macOSInstallerDownloadFrame(wx.Frame): wx.App.Get().Yield() if chunk_obj.status == integrity_verification.ChunklistStatus.FAILURE: - wx.MessageBox("Chunklist validation failed.\n\nThis generally happens when downloading on unstable connections such as WiFi or cellular.\n\nPlease try redownloading again on a stable connection (ie. Ethernet)", "Corrupted Installer!", wx.OK | wx.ICON_ERROR) + logging.error(f"Chunklist validation failed: Hash mismatch on {chunk_obj.current_chunk}") + wx.MessageBox(f"Chunklist validation failed: Hash mismatch on {chunk_obj.current_chunk}\n\nThis generally happens when downloading on unstable connections such as WiFi or cellular.\n\nPlease try redownloading again on a stable connection (ie. Ethernet)", "Corrupted Installer!", wx.OK | wx.ICON_ERROR) self.on_return_to_main_menu() return + logging.info("macOS installer validated") + # Extract installer title_label.SetLabel("Extracting macOS Installer") title_label.Centre(wx.HORIZONTAL) diff --git a/resources/wx_gui/gui_macos_installer_flash.py b/resources/wx_gui/gui_macos_installer_flash.py index 4295a88bf..fef0c066e 100644 --- a/resources/wx_gui/gui_macos_installer_flash.py +++ b/resources/wx_gui/gui_macos_installer_flash.py @@ -132,6 +132,7 @@ class macOSInstallerFlashFrame(wx.Frame): def on_select(self, installer: dict) -> None: + logging.info(f"Selected installer: {installer['Short Name']} ({installer['Version']} ({installer['Build']}))") self.frame_modal.Destroy() for child in self.GetChildren(): @@ -186,8 +187,9 @@ class macOSInstallerFlashFrame(wx.Frame): if self.available_disks: spacer = 5 entries = len(self.available_disks) + logging.info("Available disks:") for disk in self.available_disks: - logging.info(f"{disk}: {self.available_disks[disk]['name']} - {utilities.human_fmt(self.available_disks[disk]['size'])}") + logging.info(f" - {disk}: {self.available_disks[disk]['name']} - {utilities.human_fmt(self.available_disks[disk]['size'])}") disk_button = wx.Button(self.frame_modal, label=f"{disk}: {self.available_disks[disk]['name']} - {utilities.human_fmt(self.available_disks[disk]['size'])}", pos=(-1, warning_label.GetPosition()[1] + warning_label.GetSize()[1] + spacer), size=(300, 30)) disk_button.Bind(wx.EVT_BUTTON, lambda event, temp=disk: self.on_select_disk(self.available_disks[temp], installer)) disk_button.Centre(wx.HORIZONTAL) @@ -222,6 +224,8 @@ class macOSInstallerFlashFrame(wx.Frame): if answer != wx.YES: return + logging.info(f"Selected disk: {disk['name']}") + self.frame_modal.Destroy() for child in self.GetChildren(): @@ -262,6 +266,7 @@ class macOSInstallerFlashFrame(wx.Frame): # Prepare resources if self._prepare_resources(installer['Path'], disk['identifier']) is False: + logging.error("Failed to prepare resources, cannot continue.") wx.MessageBox("Failed to prepare resources, cannot continue.", "Error", wx.OK | wx.ICON_ERROR) self.on_return_to_main_menu() return @@ -281,6 +286,7 @@ class macOSInstallerFlashFrame(wx.Frame): initial_bytes_written = float(utilities.monitor_disk_output(root_disk)) self.result = False def _flash(): + logging.info(f"Flashing {installer['Path']} to {root_disk}") self.result = self._flash_installer(root_disk) thread = threading.Thread(target=_flash) @@ -298,6 +304,7 @@ class macOSInstallerFlashFrame(wx.Frame): wx.Yield() if self.result is False: + logging.error("Failed to flash installer, cannot continue.") self.on_return_to_main_menu() return @@ -522,12 +529,15 @@ class macOSInstallerFlashFrame(wx.Frame): kdk_dmg_path.unlink() def _validate_installer_pkg(self, disk: str) -> bool: - verification_success = False + logging.info("Validating installer pkg") error_message = "" def _integrity_check(): nonlocal error_message - path = utilities.grab_mount_point_from_disk(disk + "s2") - dmg_path = path + f"/{path.split('/')[2]}.app/Contents/SharedSupport/SharedSupport.dmg" + for folder in Path(utilities.grab_mount_point_from_disk(disk + "s2")).glob("*.app"): + if folder.is_dir(): + dmg_path = folder / "Contents" / "SharedSupport" / "SharedSupport.dmg" + break + if not Path(dmg_path).exists(): logging.error(f"Failed to find {dmg_path}") error_message = f"Failed to find {dmg_path}" @@ -547,10 +557,10 @@ class macOSInstallerFlashFrame(wx.Frame): while thread.is_alive(): wx.Yield() - if verification_success: + if error_message == "": + logging.info("Installer pkg validated") return error_message - logging.error(error_message) return error_message