mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-23 19:40:15 +10:00
logging_handler.py: Reveal log on crash
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -3,6 +3,16 @@
|
|||||||
## 0.6.7
|
## 0.6.7
|
||||||
- Backend changes:
|
- Backend changes:
|
||||||
- Call `setpgrp()` to prevent app from being killed if parent process is killed (ie. LaunchAgents)
|
- 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
|
## 0.6.6
|
||||||
- Implement option to disable ColorSync downgrade on HD 3000 Macs
|
- Implement option to disable ColorSync downgrade on HD 3000 Macs
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class arguments:
|
|||||||
"""
|
"""
|
||||||
Enter validation mode
|
Enter validation mode
|
||||||
"""
|
"""
|
||||||
|
logging.info("Set Validation Mode")
|
||||||
validation.PatcherValidation(self.constants)
|
validation.PatcherValidation(self.constants)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
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:
|
def custom_thread_excepthook(args) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class InstallerCreation():
|
|||||||
bool: True if successful, False otherwise
|
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:
|
try:
|
||||||
applescript.AppleScript(
|
applescript.AppleScript(
|
||||||
f'''do shell script "installer -pkg {Path(download_path)}/InstallAssistant.pkg -target /"'''
|
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]):
|
if not any(all_disks[disk]['removable'] is False for partition in all_disks[disk]):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logging.info(f"disk {disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})")
|
|
||||||
list_disks.update({
|
list_disks.update({
|
||||||
disk: {
|
disk: {
|
||||||
"identifier": all_disks[disk]["identifier"],
|
"identifier": all_disks[disk]["identifier"],
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class macOSInstallerDownloadFrame(wx.Frame):
|
|||||||
self.available_installers = None
|
self.available_installers = None
|
||||||
self.available_installers_latest = 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.frame_modal = wx.Dialog(parent, title=title, size=(330, 200))
|
||||||
|
|
||||||
self._generate_elements(self.frame_modal)
|
self._generate_elements(self.frame_modal)
|
||||||
@@ -102,7 +104,8 @@ class macOSInstallerDownloadFrame(wx.Frame):
|
|||||||
|
|
||||||
# Grab installer catalog
|
# Grab installer catalog
|
||||||
def _fetch_installers():
|
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 = remote_obj.available_apps
|
||||||
self.available_installers_latest = remote_obj.available_apps_latest
|
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
|
installers = self.available_installers_latest if show_full is False else self.available_installers
|
||||||
if installers:
|
if installers:
|
||||||
spacer = 0
|
spacer = 0
|
||||||
|
logging.info(f"Available installers on SUCatalog ({'All entries' if show_full else 'Latest only'}):")
|
||||||
for app in installers:
|
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 ""
|
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))
|
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
|
Download macOS installer
|
||||||
"""
|
"""
|
||||||
|
logging.info(f"Selected macOS {app['Version']} ({app['Build']})")
|
||||||
|
|
||||||
# Notify user whether their model is compatible with the selected installer
|
# Notify user whether their model is compatible with the selected installer
|
||||||
problems = []
|
problems = []
|
||||||
@@ -185,6 +190,7 @@ class macOSInstallerDownloadFrame(wx.Frame):
|
|||||||
problems.append("Lack of internal Keyboard/Mouse in macOS installer.")
|
problems.append("Lack of internal Keyboard/Mouse in macOS installer.")
|
||||||
|
|
||||||
if problems:
|
if problems:
|
||||||
|
logging.warning(f"Potential issues with {model} and {app['Version']} ({app['Build']}): {problems}")
|
||||||
problems = "\n".join(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 = 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")
|
dlg.SetYesNoCancelLabels("View Github Issue", "Download Anyways", "Cancel")
|
||||||
@@ -198,6 +204,7 @@ class macOSInstallerDownloadFrame(wx.Frame):
|
|||||||
host_space = utilities.get_free_space()
|
host_space = utilities.get_free_space()
|
||||||
needed_space = app['Size'] * 2
|
needed_space = app['Size'] * 2
|
||||||
if host_space < needed_space:
|
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 = 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()
|
dlg.ShowModal()
|
||||||
return
|
return
|
||||||
@@ -249,6 +256,7 @@ class macOSInstallerDownloadFrame(wx.Frame):
|
|||||||
|
|
||||||
chunklist_stream = network_handler.NetworkUtilities().get(chunklist_link).content
|
chunklist_stream = network_handler.NetworkUtilities().get(chunklist_link).content
|
||||||
if chunklist_stream:
|
if chunklist_stream:
|
||||||
|
logging.info("Validating macOS installer")
|
||||||
utilities.disable_sleep_while_running()
|
utilities.disable_sleep_while_running()
|
||||||
chunk_obj = integrity_verification.ChunklistVerification(self.constants.payload_path / Path("InstallAssistant.pkg"), chunklist_stream)
|
chunk_obj = integrity_verification.ChunklistVerification(self.constants.payload_path / Path("InstallAssistant.pkg"), chunklist_stream)
|
||||||
if chunk_obj.chunks:
|
if chunk_obj.chunks:
|
||||||
@@ -265,10 +273,13 @@ class macOSInstallerDownloadFrame(wx.Frame):
|
|||||||
wx.App.Get().Yield()
|
wx.App.Get().Yield()
|
||||||
|
|
||||||
if chunk_obj.status == integrity_verification.ChunklistStatus.FAILURE:
|
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()
|
self.on_return_to_main_menu()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
logging.info("macOS installer validated")
|
||||||
|
|
||||||
# Extract installer
|
# Extract installer
|
||||||
title_label.SetLabel("Extracting macOS Installer")
|
title_label.SetLabel("Extracting macOS Installer")
|
||||||
title_label.Centre(wx.HORIZONTAL)
|
title_label.Centre(wx.HORIZONTAL)
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
|
|
||||||
|
|
||||||
def on_select(self, installer: dict) -> None:
|
def on_select(self, installer: dict) -> None:
|
||||||
|
logging.info(f"Selected installer: {installer['Short Name']} ({installer['Version']} ({installer['Build']}))")
|
||||||
self.frame_modal.Destroy()
|
self.frame_modal.Destroy()
|
||||||
|
|
||||||
for child in self.GetChildren():
|
for child in self.GetChildren():
|
||||||
@@ -186,8 +187,9 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
if self.available_disks:
|
if self.available_disks:
|
||||||
spacer = 5
|
spacer = 5
|
||||||
entries = len(self.available_disks)
|
entries = len(self.available_disks)
|
||||||
|
logging.info("Available disks:")
|
||||||
for disk in self.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 = 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.Bind(wx.EVT_BUTTON, lambda event, temp=disk: self.on_select_disk(self.available_disks[temp], installer))
|
||||||
disk_button.Centre(wx.HORIZONTAL)
|
disk_button.Centre(wx.HORIZONTAL)
|
||||||
@@ -222,6 +224,8 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
if answer != wx.YES:
|
if answer != wx.YES:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
logging.info(f"Selected disk: {disk['name']}")
|
||||||
|
|
||||||
self.frame_modal.Destroy()
|
self.frame_modal.Destroy()
|
||||||
|
|
||||||
for child in self.GetChildren():
|
for child in self.GetChildren():
|
||||||
@@ -262,6 +266,7 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
|
|
||||||
# Prepare resources
|
# Prepare resources
|
||||||
if self._prepare_resources(installer['Path'], disk['identifier']) is False:
|
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)
|
wx.MessageBox("Failed to prepare resources, cannot continue.", "Error", wx.OK | wx.ICON_ERROR)
|
||||||
self.on_return_to_main_menu()
|
self.on_return_to_main_menu()
|
||||||
return
|
return
|
||||||
@@ -281,6 +286,7 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
initial_bytes_written = float(utilities.monitor_disk_output(root_disk))
|
initial_bytes_written = float(utilities.monitor_disk_output(root_disk))
|
||||||
self.result = False
|
self.result = False
|
||||||
def _flash():
|
def _flash():
|
||||||
|
logging.info(f"Flashing {installer['Path']} to {root_disk}")
|
||||||
self.result = self._flash_installer(root_disk)
|
self.result = self._flash_installer(root_disk)
|
||||||
|
|
||||||
thread = threading.Thread(target=_flash)
|
thread = threading.Thread(target=_flash)
|
||||||
@@ -298,6 +304,7 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
wx.Yield()
|
wx.Yield()
|
||||||
|
|
||||||
if self.result is False:
|
if self.result is False:
|
||||||
|
logging.error("Failed to flash installer, cannot continue.")
|
||||||
self.on_return_to_main_menu()
|
self.on_return_to_main_menu()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -522,12 +529,15 @@ class macOSInstallerFlashFrame(wx.Frame):
|
|||||||
kdk_dmg_path.unlink()
|
kdk_dmg_path.unlink()
|
||||||
|
|
||||||
def _validate_installer_pkg(self, disk: str) -> bool:
|
def _validate_installer_pkg(self, disk: str) -> bool:
|
||||||
verification_success = False
|
logging.info("Validating installer pkg")
|
||||||
error_message = ""
|
error_message = ""
|
||||||
def _integrity_check():
|
def _integrity_check():
|
||||||
nonlocal error_message
|
nonlocal error_message
|
||||||
path = utilities.grab_mount_point_from_disk(disk + "s2")
|
for folder in Path(utilities.grab_mount_point_from_disk(disk + "s2")).glob("*.app"):
|
||||||
dmg_path = path + f"/{path.split('/')[2]}.app/Contents/SharedSupport/SharedSupport.dmg"
|
if folder.is_dir():
|
||||||
|
dmg_path = folder / "Contents" / "SharedSupport" / "SharedSupport.dmg"
|
||||||
|
break
|
||||||
|
|
||||||
if not Path(dmg_path).exists():
|
if not Path(dmg_path).exists():
|
||||||
logging.error(f"Failed to find {dmg_path}")
|
logging.error(f"Failed to find {dmg_path}")
|
||||||
error_message = 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():
|
while thread.is_alive():
|
||||||
wx.Yield()
|
wx.Yield()
|
||||||
|
|
||||||
if verification_success:
|
if error_message == "":
|
||||||
|
logging.info("Installer pkg validated")
|
||||||
return error_message
|
return error_message
|
||||||
|
|
||||||
logging.error(error_message)
|
|
||||||
return error_message
|
return error_message
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user