diff --git a/.gitignore b/.gitignore index 64180bd6f..e8b28230f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ __pycache__/ /payloads/OpenCore-Legacy-Patcher /payloads/InstallAssistant.pkg.integrityDataV1 /payloads.dmg +/Universal-Binaries.dmg /payloads/OpenCore-Legacy-Patcher-*.plist /payloads/KDK.dmg *.log diff --git a/Build-Binary.command b/Build-Binary.command index 94b5da9ea..df8ab6fe7 100755 --- a/Build-Binary.command +++ b/Build-Binary.command @@ -20,7 +20,7 @@ class CreateBinary: Library for creating OpenCore-Patcher application This script's main purpose is to handle the following: - - Download external dependancies (ex. PatcherSupportPkg) + - Download external dependencies (ex. PatcherSupportPkg) - Convert payloads directory into DMG - Build Binary via Pyinstaller - Patch 'LC_VERSION_MIN_MACOSX' to OS X 10.10 @@ -275,7 +275,10 @@ class CreateBinary: for resource in required_resources: if Path(f"./{resource}").exists(): if self.args.reset_binaries: - print(f"- Removing old {resource}") + print(f" - Removing old {resource}") + # Just to be safe + assert resource, "Resource cannot be empty" + assert resource not in ("/", "."), "Resource cannot be root" rm_output = subprocess.run( ["rm", "-rf", f"./{resource}"], stdout=subprocess.PIPE, stderr=subprocess.PIPE diff --git a/docs/LICENSE.md b/docs/LICENSE.md index 21172e2b4..96a2d189a 100644 --- a/docs/LICENSE.md +++ b/docs/LICENSE.md @@ -18,6 +18,7 @@ This patcher is made of multiple external applications from different people and * [telemetrap](https://forums.macrumors.com/threads/mp3-1-others-sse-4-2-emulation-to-enable-amd-metal-driver.2206682/post-28447707) - Syncretic * [SurPlus](https://github.com/reenigneorcim/SurPlus) - Syncretic * [VMM Patch Set](https://github.com/dortania/OpenCore-Legacy-Patcher/blob/4a8f61a01da72b38a4b2250386cc4b497a31a839/payloads/Config/config.plist#L1222-L1281) - parrotgeek1 + * AMFIPass - Dhinak G * Apple Binaries - Apple Inc. * All other patches - respective authors diff --git a/payloads/Config/config.plist b/payloads/Config/config.plist index c783fb0ff..301a81b50 100644 --- a/payloads/Config/config.plist +++ b/payloads/Config/config.plist @@ -1584,6 +1584,22 @@ Arch x86_64 + BundlePath + AMFIPass.kext + Comment + AMFIPass + Enabled + + ExecutablePath + Contents/MacOS/AMFIPass + MaxKernel + + MinKernel + 20.0.0 + PlistPath + Contents/Info.plist + + Comment Aquantia Ethernet Patch Enabled diff --git a/payloads/Kexts/Acidanthera/AMFIPass-v1.3.1-RELEASE.zip b/payloads/Kexts/Acidanthera/AMFIPass-v1.3.1-RELEASE.zip new file mode 100644 index 000000000..06a04afcf Binary files /dev/null and b/payloads/Kexts/Acidanthera/AMFIPass-v1.3.1-RELEASE.zip differ diff --git a/resources/build/security.py b/resources/build/security.py index f0818c62b..ff8936998 100644 --- a/resources/build/security.py +++ b/resources/build/security.py @@ -82,3 +82,6 @@ class BuildSecurity: support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] = True support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (2) Legacy")["Enabled"] = True support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (2) Ventura")["Enabled"] = True + + logging.info("- Enabling AMFIPass") + support.BuildSupport(self.model, self.constants, self.config).enable_kext("AMFIPass.kext", self.constants.amfipass_version, self.constants.amfipass_path) diff --git a/resources/constants.py b/resources/constants.py index 16379771c..429aa8ee5 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -4,6 +4,7 @@ from pathlib import Path from typing import Optional +from packaging import version from resources import device_probe from data import os_data @@ -78,13 +79,15 @@ class Constants: ## Dortania ## https://github.com/dortania - self.backlight_injector_version: str = "1.1.0" # BacklightInjector - self.backlight_injectorA_version: str = "1.0.0" # BacklightInjector (iMac9,1) - self.smcspoof_version: str = "1.0.0" # SMC-Spoof - self.mce_version: str = "1.0.0" # AppleMCEReporterDisabler - self.btspoof_version: str = "1.0.0" # Bluetooth-Spoof - self.aspp_override_version: str = "1.0.1" # ACPI_SMC_PlatformPlugin Override - self.rsrhelper_version: str = "1.0.0" # RSRHelper + self.backlight_injector_version: str = "1.1.0" # BacklightInjector + self.backlight_injectorA_version: str = "1.0.0" # BacklightInjector (iMac9,1) + self.smcspoof_version: str = "1.0.0" # SMC-Spoof + self.mce_version: str = "1.0.0" # AppleMCEReporterDisabler + self.btspoof_version: str = "1.0.0" # Bluetooth-Spoof + self.aspp_override_version: str = "1.0.1" # ACPI_SMC_PlatformPlugin Override + self.rsrhelper_version: str = "1.0.0" # RSRHelper + self.amfipass_version: str = "1.3.1" # AMFIPass + self.amfipass_compatibility_version: str = "1.2.1" # Minimum AMFIPass version required ## Syncretic ## https://forums.macrumors.com/members/syncretic.1173816/ @@ -232,6 +235,18 @@ class Constants: os_data.os_data.ventura, ] + @property + def special_build(self): + """ + Special builds are used for testing. They do not get updates through the updater + """ + + try: + version.parse(self.patcher_version) + return False + except version.InvalidVersion: + return True + # Payload Location # Support Disk Images @@ -489,6 +504,11 @@ class Constants: def rsrhelper_path(self): return self.payload_kexts_path / Path(f"Acidanthera/RSRHelper-v{self.rsrhelper_version}-{self.kext_variant}.zip") + @property + def amfipass_path(self): + # AMFIPass is release only + return self.payload_kexts_path / Path(f"Acidanthera/AMFIPass-v{self.amfipass_version}-RELEASE.zip") + @property def innie_path(self): return self.payload_kexts_path / Path(f"Misc/Innie-v{self.innie_version}-{self.kext_variant}.zip") diff --git a/resources/defaults.py b/resources/defaults.py index 0e061ef49..d654787d0 100644 --- a/resources/defaults.py +++ b/resources/defaults.py @@ -49,7 +49,7 @@ class GenerateDefaults: self._networking_probe() self._misc_hardwares_probe() self._smbios_probe() - + self._check_amfipass_supported() def _general_probe(self) -> None: """ @@ -309,4 +309,32 @@ class GenerateDefaults: if is_key_enabled not in ["false", "0"]: subprocess.run(["defaults", "write", "-g", key, "-bool", "true"]) - subprocess.run(["defaults", "write", "-g", "Amy.MenuBar2Beta", "-bool", "false"]) \ No newline at end of file + subprocess.run(["defaults", "write", "-g", "Amy.MenuBar2Beta", "-bool", "false"]) + + def _check_amfipass_supported(self) -> None: + """ + Check if root volume supports AMFIPass + + The basic requirements of this function are: + - The host is the target + - Root volume doesn't have adhoc signed binaries + + If all of these conditions are met, it is safe to disable AMFI and CS_LV. Otherwise, for safety, leave it be. + """ + + if not self.host_is_target: + # Unknown whether the host is using old binaries + # Rebuild it once you are on the host + return + + # Check for adhoc signed binaries + if self.constants.computer.oclp_sys_signed is False: + # Root patch with new binaries, then reboot + return + + # Note: simply checking the authority is not enough, as the authority can be spoofed + # (but do we really care? this is just a simple check) + # Note: the cert will change + + self.constants.disable_amfi = False + self.constants.disable_cs_lv = False diff --git a/resources/device_probe.py b/resources/device_probe.py index f21479d92..1c129eae0 100644 --- a/resources/device_probe.py +++ b/resources/device_probe.py @@ -604,6 +604,7 @@ class Computer: oclp_sys_version: Optional[str] = None oclp_sys_date: Optional[str] = None oclp_sys_url: Optional[str] = None + oclp_sys_signed: Optional[bool] = False firmware_vendor: Optional[str] = None rosetta_active: Optional[bool] = False @@ -927,15 +928,19 @@ class Computer: def oclp_sys_patch_probe(self): path = Path("/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist") - if path.exists(): - sys_plist = plistlib.load(path.open("rb")) - if sys_plist: - if "OpenCore Legacy Patcher" in sys_plist: - self.oclp_sys_version = sys_plist["OpenCore Legacy Patcher"] - if "Time Patched" in sys_plist: - self.oclp_sys_date = sys_plist["Time Patched"] - if "Commit URL" in sys_plist: - self.oclp_sys_url = sys_plist["Commit URL"] + if not path.exists(): + self.oclp_sys_signed = True # No plist, so assume root is valid + return + sys_plist = plistlib.load(path.open("rb")) + if sys_plist: + if "OpenCore Legacy Patcher" in sys_plist: + self.oclp_sys_version = sys_plist["OpenCore Legacy Patcher"] + if "Time Patched" in sys_plist: + self.oclp_sys_date = sys_plist["Time Patched"] + if "Commit URL" in sys_plist: + self.oclp_sys_url = sys_plist["Commit URL"] + if "Custom Signature" in sys_plist: + self.oclp_sys_signed = sys_plist["Custom Signature"] def check_rosetta(self): result = subprocess.run("sysctl -in sysctl.proc_translated".split(), stdout=subprocess.PIPE).stdout.decode() diff --git a/resources/kdk_handler.py b/resources/kdk_handler.py index 0c59bf13d..fd31b27e2 100644 --- a/resources/kdk_handler.py +++ b/resources/kdk_handler.py @@ -20,7 +20,7 @@ from data import os_data KDK_INSTALL_PATH: str = "/Library/Developer/KDKs" KDK_INFO_PLIST: str = "KDKInfo.plist" -KDK_API_LINK: str = "https://raw.githubusercontent.com/dortania/KdkSupportPkg/gh-pages/manifest.json" +KDK_API_LINK: str = "https://dortania.github.io/KdkSupportPkg/manifest.json" KDK_ASSET_LIST: list = None diff --git a/resources/sys_patch/sys_patch.py b/resources/sys_patch/sys_patch.py index 6dcf7749c..5e2bd4238 100644 --- a/resources/sys_patch/sys_patch.py +++ b/resources/sys_patch/sys_patch.py @@ -67,7 +67,6 @@ class PatchSysVolume: self.skip_root_kmutil_requirement = self.hardware_details["Settings: Supports Auxiliary Cache"] - def _init_pathing(self, custom_root_mount_path: Path = None, custom_data_mount_path: Path = None) -> None: """ Initializes the pathing for root volume patching @@ -493,7 +492,7 @@ class PatchSysVolume: oclp_plist_data = plistlib.load(Path(oclp_path).open("rb")) for key in oclp_plist_data: if isinstance(oclp_plist_data[key], (bool, int)): - continue + continue if "Install" not in oclp_plist_data[key]: continue for location in oclp_plist_data[key]["Install"]: diff --git a/resources/sys_patch/sys_patch_auto.py b/resources/sys_patch/sys_patch_auto.py index dcf79841b..e1cdca83e 100644 --- a/resources/sys_patch/sys_patch_auto.py +++ b/resources/sys_patch/sys_patch_auto.py @@ -47,8 +47,7 @@ class AutomaticSysPatch: dict = updates.CheckBinaryUpdates(self.constants).check_binary_updates() if dict: - for key in dict: - version = dict[key]["Version"] + version = dict["Version"] logging.info(f"- Found new version: {version}") app = wx.App() @@ -64,7 +63,7 @@ class AutomaticSysPatch: if response == wx.ID_YES: gui_entry.EntryPoint(self.constants).start(entry=gui_entry.SupportedEntryPoints.UPDATE_APP) elif response == wx.ID_NO: - webbrowser.open(dict[key]["Github Link"]) + webbrowser.open(dict["Github Link"]) return if utilities.check_seal() is True: @@ -149,17 +148,21 @@ class AutomaticSysPatch: logging.info("- Versions match") return True + if self.constants.special_build is True: + # Version doesn't match and we're on a special build + # Special builds don't have good ways to compare versions + logging.info("- Special build detected, assuming installed is older") + return False + # Check if installed version is newer than booted version - if updates.CheckBinaryUpdates(self.constants)._check_if_build_newer( - self.constants.computer.oclp_version.split("."), self.constants.patcher_version.split(".") - ) is True: + if updates.CheckBinaryUpdates(self.constants).check_if_newer(self.constants.computer.oclp_version): logging.info("- Installed version is newer than booted version") return True args = [ "osascript", "-e", - f"""display dialog "OpenCore Legacy Patcher has detected that you are booting an outdated OpenCore build\n- Booted: {self.constants.computer.oclp_version}\n- Installed: {self.constants.patcher_version}\n\nWould you like to update the OpenCore bootloader?" """ + f"""display dialog "OpenCore Legacy Patcher has detected that you are booting {'a different' if self.constants.special_build else 'an outdated'} OpenCore build\n- Booted: {self.constants.computer.oclp_version}\n- Installed: {self.constants.patcher_version}\n\nWould you like to update the OpenCore bootloader?" """ f'with icon POSIX file "{self.constants.app_icon_path}"', ] output = subprocess.run( diff --git a/resources/sys_patch/sys_patch_detect.py b/resources/sys_patch/sys_patch_detect.py index f2518a481..5bd350c10 100644 --- a/resources/sys_patch/sys_patch_detect.py +++ b/resources/sys_patch/sys_patch_detect.py @@ -3,26 +3,16 @@ # Used when supplying data to sys_patch.py # Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk -import plistlib import logging -import py_sip_xnu +import plistlib from pathlib import Path -from resources import ( - constants, - device_probe, - utilities, - amfi_detect, - network_handler, - kdk_handler -) -from data import ( - model_array, - os_data, - sip_data, - smbios_data, - cpu_data -) +import packaging.version +import py_sip_xnu + +from data import cpu_data, model_array, os_data, sip_data, smbios_data +from resources import (amfi_detect, constants, device_probe, kdk_handler, + network_handler, utilities) class DetectRootPatch: @@ -418,7 +408,7 @@ class DetectRootPatch: bool: True if loaded, False otherwise """ - return utilities.check_kext_loaded("WhateverGreen", self.constants.detected_os) + return utilities.check_kext_loaded("as.vit9696.WhateverGreen") def _check_kdk(self): @@ -521,7 +511,7 @@ class DetectRootPatch: if self.constants.detected_os > os_data.os_data.catalina: self.brightness_legacy = True - if self.model in ["iMac7,1", "iMac8,1"] or (self.model in model_array.LegacyAudio and utilities.check_kext_loaded("AppleALC", self.constants.detected_os) is False): + if self.model in ["iMac7,1", "iMac8,1"] or (self.model in model_array.LegacyAudio and utilities.check_kext_loaded("as.vit9696.AppleALC") is False): # Special hack for systems with botched GOPs # TL;DR: No Boot Screen breaks Lilu, therefore breaking audio if self.constants.detected_os > os_data.os_data.catalina: @@ -610,6 +600,12 @@ class DetectRootPatch: if self.constants.detected_os < os_data.os_data.big_sur: return amfi_detect.AmfiConfigDetectLevel.NO_CHECK + amfipass_version = utilities.check_kext_loaded("com.dhinakg.AMFIPass") + if amfipass_version: + if packaging.version.parse(amfipass_version) >= packaging.version.parse(self.constants.amfipass_compatibility_version): + # If AMFIPass is loaded, our binaries will work + return amfi_detect.AmfiConfigDetectLevel.NO_CHECK + if self.constants.detected_os >= os_data.os_data.ventura: if self.amfi_shim_bins is True: # Currently we require AMFI outright disabled diff --git a/resources/updates.py b/resources/updates.py index 8b0df26c8..9b12df530 100644 --- a/resources/updates.py +++ b/resources/updates.py @@ -3,8 +3,11 @@ # Call check_binary_updates() to determine if any updates are available # Returns dict with Link and Version of the latest binary update if available import logging +from typing import Optional, Union -from resources import network_handler, constants +from packaging import version + +from resources import constants, network_handler REPO_LATEST_RELEASE_URL: str = "https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest" @@ -12,48 +15,62 @@ REPO_LATEST_RELEASE_URL: str = "https://api.github.com/repos/dortania/OpenCore-L class CheckBinaryUpdates: def __init__(self, global_constants: constants.Constants) -> None: self.constants: constants.Constants = global_constants + try: + self.binary_version = version.parse(self.constants.patcher_version) + except version.InvalidVersion: + assert self.constants.special_build is True, "Invalid version number for binary" + # Special builds will not have a proper version number + self.binary_version = version.parse("0.0.0") - self.binary_version = self.constants.patcher_version - self.binary_version_array = [int(x) for x in self.binary_version.split(".")] + self.latest_details = None - - def _check_if_build_newer(self, remote_version: list = None, local_version: list = None) -> bool: + def check_if_newer(self, version: Union[str, version.Version]) -> bool: """ - Check if the remote version is newer than the local version + Check if the provided version is newer than the local version Parameters: - remote_version (list): Remote version to compare against - local_version (list): Local version to compare against + version (str): Version to compare against Returns: - bool: True if remote version is newer, False if not + bool: True if the provided version is newer, False if not + """ + if self.constants.special_build is True: + return False + + return self._check_if_build_newer(version, self.binary_version) + + def _check_if_build_newer(self, first_version: Union[str, version.Version], second_version: Union[str, version.Version]) -> bool: + """ + Check if the first version is newer than the second version + + Parameters: + first_version_str (str): First version to compare against (generally local) + second_version_str (str): Second version to compare against (generally remote) + + Returns: + bool: True if first version is newer, False if not """ - if remote_version is None: - remote_version = self.remote_version_array - if local_version is None: - local_version = self.binary_version_array + if not isinstance(first_version, version.Version): + try: + first_version = version.parse(first_version) + except version.InvalidVersion: + # Special build > release build: assume special build is newer + return True + if not isinstance(second_version, version.Version): + try: + second_version = version.parse(second_version) + except version.InvalidVersion: + # Release build > special build: assume special build is newer + return False - if local_version == remote_version: + if first_version == second_version: if not self.constants.commit_info[0].startswith("refs/tags"): # Check for nightly builds return True - # Pad version numbers to match length (ie. 0.1.0 vs 0.1.0.1) - while len(remote_version) > len(local_version): - local_version.append(0) - while len(remote_version) < len(local_version): - remote_version.append(0) - - for i in range(0, len(remote_version)): - if int(remote_version[i]) < int(local_version[i]): - break - elif int(remote_version[i]) > int(local_version[i]): - return True - - return False - + return first_version > second_version def _determine_local_build_type(self) -> str: """ @@ -63,11 +80,7 @@ class CheckBinaryUpdates: str: "GUI" or "TUI" """ - if self.constants.wxpython_variant is True: - return "GUI" - else: - return "TUI" - + return "GUI" if self.constants.wxpython_variant else "TUI" def _determine_remote_type(self, remote_name: str) -> str: """ @@ -87,8 +100,7 @@ class CheckBinaryUpdates: else: return "Unknown" - - def check_binary_updates(self) -> dict: + def check_binary_updates(self) -> Optional[dict]: """ Check if any updates are available for the OpenCore Legacy Patcher binary @@ -96,7 +108,13 @@ class CheckBinaryUpdates: dict: Dictionary with Link and Version of the latest binary update if available """ - available_binaries: list = {} + if self.constants.special_build is True: + # Special builds do not get updates through the updater + return None + + if self.latest_details: + # We already checked + return self.latest_details if not network_handler.NetworkUtilities(REPO_LATEST_RELEASE_URL).verify_network_connection(): return None @@ -107,26 +125,26 @@ class CheckBinaryUpdates: if "tag_name" not in data_set: return None - self.remote_version = data_set["tag_name"] + # The release marked as latest will always be stable, and thus, have a proper version number + # But if not, let's not crash the program + try: + latest_remote_version = version.parse(data_set["tag_name"]) + except version.InvalidVersion: + return None - self.remote_version_array = self.remote_version.split(".") - self.remote_version_array = [int(x) for x in self.remote_version_array] - - if self._check_if_build_newer() is False: + if not self._check_if_build_newer(latest_remote_version, self.binary_version): return None for asset in data_set["assets"]: logging.info(f"Found asset: {asset['name']}") if self._determine_remote_type(asset["name"]) == self._determine_local_build_type(): - available_binaries.update({ - asset['name']: { - "Name": asset["name"], - "Version": self.remote_version, - "Link": asset["browser_download_url"], - "Type": self._determine_remote_type(asset["name"]), - "Github Link": f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{self.remote_version}" - } - }) - return available_binaries + self.latest_details = { + "Name": asset["name"], + "Version": latest_remote_version, + "Link": asset["browser_download_url"], + "Type": self._determine_remote_type(asset["name"]), + "Github Link": f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{latest_remote_version}", + } + return self.latest_details - return None \ No newline at end of file + return None diff --git a/resources/utilities.py b/resources/utilities.py index c5676a391..d83810f85 100644 --- a/resources/utilities.py +++ b/resources/utilities.py @@ -1,21 +1,20 @@ # Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk +import argparse +import atexit +import binascii +import logging import math import os import plistlib +import re +import shutil import subprocess from pathlib import Path -import os -import binascii -import argparse -import atexit -import shutil import py_sip_xnu -import logging - +from data import os_data, sip_data from resources import constants, ioreg -from data import sip_data, os_data def hexswap(input_hex: str): @@ -173,15 +172,35 @@ def enable_sleep_after_running(): sleep_process = None -def check_kext_loaded(kext_name, os_version): - if os_version > os_data.os_data.catalina: - kext_loaded = subprocess.run(["kmutil", "showloaded", "--list-only", "--variant-suffix", "release"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - else: - kext_loaded = subprocess.run(["kextstat", "-l"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if kext_name in kext_loaded.stdout.decode(): - return True - else: - return False +def check_kext_loaded(bundle_id: str) -> str: + """ + Checks if a kext is loaded + + Parameters: + bundle_id (str): The bundle ID of the kext to check + + Returns: + str: The version of the kext if it is loaded, or "" if it is not loaded + """ + # Name (Version) UUID + # no UUID for kextstat + pattern = re.compile(re.escape(bundle_id) + r"\s+\((?P.+)\)") + + args = ["kextstat", "-l", "-b", bundle_id] + + if Path("/usr/bin/kmutil").exists(): + args = ["kmutil", "showloaded", "--list-only", "--variant-suffix", "release", "--optional-identifier", bundle_id] + + kext_loaded = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if kext_loaded.returncode != 0: + return "" + output = kext_loaded.stdout.decode() + if not output.strip(): + return "" + match = pattern.search(output) + if match: + return match.group("version") + return "" def check_oclp_boot(): diff --git a/resources/wx_gui/gui_main_menu.py b/resources/wx_gui/gui_main_menu.py index 64103ba68..66266ef04 100644 --- a/resources/wx_gui/gui_main_menu.py +++ b/resources/wx_gui/gui_main_menu.py @@ -65,7 +65,7 @@ class MainFrame(wx.Frame): """ # Title label: OpenCore Legacy Patcher v{X.Y.Z} - title_label = wx.StaticText(self, label=f"OpenCore Legacy Patcher v{self.constants.patcher_version}", pos=(-1,10)) + title_label = wx.StaticText(self, label=f"OpenCore Legacy Patcher {'' if self.constants.special_build else 'v'}{self.constants.patcher_version}", pos=(-1, 10)) title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont")) title_label.Centre(wx.HORIZONTAL) @@ -282,22 +282,21 @@ class MainFrame(wx.Frame): if not dict: return - for entry in dict: - version = dict[entry]["Version"] - logging.info(f"New version: {version}") - dialog = wx.MessageDialog( - parent=self, - message=f"Current Version: {self.constants.patcher_version}{' (Nightly)' if not self.constants.commit_info[0].startswith('refs/tags') else ''}\nNew version: {version}\nWould you like to update?", - caption="Update Available for OpenCore Legacy Patcher!", - style=wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION - ) - dialog.SetYesNoCancelLabels("Download and install", "Ignore", "View on Github") - response = dialog.ShowModal() + version = dict["Version"] + logging.info(f"New version: {version}") + dialog = wx.MessageDialog( + parent=self, + message=f"Current Version: {self.constants.patcher_version}{' (Nightly)' if not self.constants.commit_info[0].startswith('refs/tags') else ''}\nNew version: {version}\nWould you like to update?", + caption="Update Available for OpenCore Legacy Patcher!", + style=wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION + ) + dialog.SetYesNoCancelLabels("Download and install", "Ignore", "View on Github") + response = dialog.ShowModal() - if response == wx.ID_YES: - wx.CallAfter(self.on_update, dict[entry]["Link"], version) - elif response == wx.ID_CANCEL: - webbrowser.open(dict[entry]["Github Link"]) + if response == wx.ID_YES: + wx.CallAfter(self.on_update, dict["Link"], version) + elif response == wx.ID_CANCEL: + webbrowser.open(dict["Github Link"]) def on_build_and_install(self, event: wx.Event = None): diff --git a/resources/wx_gui/gui_update.py b/resources/wx_gui/gui_update.py index f5ab367b9..03ca75265 100644 --- a/resources/wx_gui/gui_update.py +++ b/resources/wx_gui/gui_update.py @@ -48,10 +48,8 @@ class UpdateFrame(wx.Frame): if url == "" or version_label == "": dict = updates.CheckBinaryUpdates(self.constants).check_binary_updates() if dict: - for key in dict: - version_label = dict[key]["Version"] - url = dict[key]["Link"] - break + version_label = dict["Version"] + url = dict["Link"] else: wx.MessageBox("Failed to get update info", "Critical Error") sys.exit(1)