From 93a2eeb8b59e0abba9cd9d6407b06ef8c2f7bbd2 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Fri, 29 Apr 2022 21:33:31 -0600 Subject: [PATCH] Only list newest installers by default --- CHANGELOG.md | 1 + gui/gui_main.py | 35 ++++++++++++++++++++++------- resources/installer.py | 50 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20b2a0957..c7f53c0ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ - Grey out return buttons while performing sensitive tasks - Add `Currently Booted SIP` info to SIP Settings - Add Disk Highlighting during Build/Install for previously installed disks + - Only list newest installers by default (reload to show older binaries) - Remove manual root unpatching - Removed due to reliablity issues - `bless` based reversion still supported in Big Sur+ diff --git a/gui/gui_main.py b/gui/gui_main.py index dfd57eee9..c2790e01b 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -1102,7 +1102,7 @@ class wx_python_gui: self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40) - def grab_installer_data(self, event=None): + def grab_installer_data(self, event=None, ias=None): self.frame.DestroyChildren() # Header @@ -1136,7 +1136,12 @@ class wx_python_gui: wx.GetApp().Yield() # Download installer catalog - available_installers = installer.list_downloadable_macOS_installers(self.constants.payload_path, "PublicSeed") + if ias is None: + print("- Downloading installer catalog...") + available_installers = installer.list_downloadable_macOS_installers(self.constants.payload_path, "PublicSeed") + else: + print("- Using existing installer catalog...") + available_installers = ias self.frame.DestroyChildren() @@ -1156,13 +1161,12 @@ class wx_python_gui: ) self.subheader.Centre(wx.HORIZONTAL) - - # Sort Installers by 'Version' - # By default Apple adds new builds to the end of the list, so we need to sort them by version - available_installers = {k: v for k, v in sorted(available_installers.items(), key=lambda x: x[1]['Version'])} + available_installers_backup = available_installers.copy() i = -20 if available_installers: + if ias is None: + available_installers = installer.only_list_newest_installers(available_installers) for app in available_installers: print(f"macOS {available_installers[app]['Version']} ({available_installers[app]['Build']} - {utilities.human_fmt(available_installers[app]['Size'])} - {available_installers[app]['Source']}) - {available_installers[app]['Variant']}") if available_installers[app]['Variant'] in ["DeveloperSeed" , "PublicSeed"]: @@ -1191,11 +1195,23 @@ class wx_python_gui: self.install_selection.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)) self.install_selection.Centre(wx.HORIZONTAL) + self.load_all_installers = wx.Button(self.frame, label="Reload with all installers") + self.load_all_installers.SetPosition( + wx.Point( + self.install_selection.GetPosition().x, + self.install_selection.GetPosition().y + self.install_selection.GetSize().height + 7 + ) + ) + self.load_all_installers.Bind(wx.EVT_BUTTON, lambda event: self.reload_macos_installer_catalog(ias=available_installers_backup)) + self.load_all_installers.Centre(wx.HORIZONTAL) + if ias or not available_installers: + self.load_all_installers.Disable() + self.return_to_main_menu = wx.Button(self.frame, label="Return to Main Menu") self.return_to_main_menu.SetPosition( wx.Point( - self.install_selection.GetPosition().x, - self.install_selection.GetPosition().y + self.install_selection.GetSize().height + 10 + self.load_all_installers.GetPosition().x, + self.load_all_installers.GetPosition().y + self.load_all_installers.GetSize().height + 5 ) ) self.return_to_main_menu.Bind(wx.EVT_BUTTON, self.main_menu) @@ -1203,6 +1219,9 @@ class wx_python_gui: self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40) + def reload_macos_installer_catalog(self, event=None, ias=None): + self.grab_installer_data(ias=ias) + def download_macos_click(self, installer_name, installer_link): self.frame.DestroyChildren() diff --git a/resources/installer.py b/resources/installer.py index 8f6e76e28..8da2e8f7c 100644 --- a/resources/installer.py +++ b/resources/installer.py @@ -169,6 +169,56 @@ def list_downloadable_macOS_installers(download_path, catalog): }) except KeyError: pass + available_apps = {k: v for k, v in sorted(available_apps.items(), key=lambda x: x[1]['Version'])} + return available_apps + +def only_list_newest_installers(available_apps): + # Takes a dictionary of available installers + # Returns a dictionary of only the newest installers + # This is used to avoid overwhelming the user with installer options + + # Only strip OSes that we know are supported + supported_versions = ["10.13", "10.14", "10.15", "11", "12"] + + for version in supported_versions: + remote_version_minor = 0 + remote_version_security = 0 + + # First determine the largest version + for ia in available_apps: + if available_apps[ia]["Version"].startswith(version): + if available_apps[ia]["Variant"] not in ["DeveloperSeed", "PublicSeed"]: + remote_version = available_apps[ia]["Version"].split(".") + if remote_version[0] == "10": + remote_version.pop(0) + remote_version.pop(0) + else: + remote_version.pop(0) + if int(remote_version[0]) > remote_version_minor: + remote_version_minor = int(remote_version[0]) + if len(remote_version) > 1: + if int(remote_version[1]) > remote_version_security: + remote_version_security = int(remote_version[1]) + + # Now remove all versions that are not the largest + for ia in list(available_apps): + if available_apps[ia]["Version"].startswith(version): + remote_version = available_apps[ia]["Version"].split(".") + if remote_version[0] == "10": + remote_version.pop(0) + remote_version.pop(0) + else: + remote_version.pop(0) + if int(remote_version[0]) < remote_version_minor: + available_apps.pop(ia) + elif int(remote_version[0]) == remote_version_minor: + if len(remote_version) > 1: + if int(remote_version[1]) < remote_version_security: + available_apps.pop(ia) + else: + if remote_version_security > 0: + available_apps.pop(ia) + return available_apps def format_drive(disk_id):