From 416138344a7c3649a98ec8210b20cc0d4565b403 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 14:10:13 -0600 Subject: [PATCH 01/11] Switch to onedir option --- .github/workflows/build-app-wxpython.yml | 3 +- OpenCore-Patcher-GUI.spec | 38 ++++++++------ gui/gui_main.py | 6 +++ resources/constants.py | 1 + resources/main.py | 67 ++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-app-wxpython.yml b/.github/workflows/build-app-wxpython.yml index 8f3dc2acf..8d499a487 100644 --- a/.github/workflows/build-app-wxpython.yml +++ b/.github/workflows/build-app-wxpython.yml @@ -17,10 +17,11 @@ jobs: steps: - uses: actions/checkout@v3 - run: python3 create_offline_build.py + - run: zip -r payloads.zip payloads - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher-GUI.spec - run: python3 ./payloads/binary.py $branch $commiturl $commitdate - run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' - - run: cd dist; zip -r ../OpenCore-Patcher-wxPython.app.zip OpenCore-Patcher.app + - run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip - run: ./../sign-wxpython.sh - run: packagesbuild ./payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj - run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip diff --git a/OpenCore-Patcher-GUI.spec b/OpenCore-Patcher-GUI.spec index 42a26a826..fe93946de 100644 --- a/OpenCore-Patcher-GUI.spec +++ b/OpenCore-Patcher-GUI.spec @@ -7,9 +7,9 @@ block_cipher = None a = Analysis(['OpenCore-Patcher-GUI.command'], - pathex=['resources', 'data', 'gui'], + pathex=[], binaries=[], - datas=[('payloads', 'payloads')], + datas=[('payloads.zip', '.')], hiddenimports=[], hookspath=[], hooksconfig={}, @@ -23,34 +23,38 @@ pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, + a.scripts, [], + exclude_binaries=True, name='OpenCore-Patcher', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, - upx_exclude=[], - runtime_tmpdir=None, console=False, disable_windowed_traceback=False, target_arch=None, codesign_identity=None, entitlements_file=None ) -app = BUNDLE(exe, +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='OpenCore-Patcher') +app = BUNDLE(coll, name='OpenCore-Patcher.app', icon="payloads/OC-Patcher.icns", bundle_identifier="com.dortania.opencore-legacy-patcher-wxpython", info_plist={ - "CFBundleShortVersionString": constants.Constants().patcher_version, - "NSHumanReadableCopyright": constants.Constants().copyright_date, - "LSMinimumSystemVersion": "10.10.0", - "NSRequiresAquaSystemAppearance": False, - "NSHighResolutionCapable": True, - "Build Date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), - "BuildMachineOSBuild": subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().strip(), - "NSPrincipalClass": "NSApplication", + "CFBundleShortVersionString": constants.Constants().patcher_version, + "NSHumanReadableCopyright": constants.Constants().copyright_date, + "LSMinimumSystemVersion": "10.10.0", + "NSRequiresAquaSystemAppearance": False, + "NSHighResolutionCapable": True, + #"Build Date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + #"BuildMachineOSBuild": subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().strip(), + "NSPrincipalClass": "NSApplication", }) diff --git a/gui/gui_main.py b/gui/gui_main.py index a7778cc4b..cae12e80a 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -563,6 +563,10 @@ class wx_python_gui: def build_start(self, event=None): self.build_opencore.Disable() + + while self.constants.unpack_thread.is_alive(): + time.sleep(0.1) + build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore() # Once finished, change build_opencore button to "Install OpenCore" self.build_opencore.SetLabel("🔩 Install OpenCore") @@ -819,6 +823,8 @@ class wx_python_gui: # Button: Start Root Patching # Button: Revert Root Patches # Button: Return to Main Menu + while self.constants.unpack_thread.is_alive(): + time.sleep(0.1) self.frame.DestroyChildren() # Header diff --git a/resources/constants.py b/resources/constants.py index 3e66c683d..048bc001b 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -106,6 +106,7 @@ class Constants: self.launcher_script = None # Determine launch file (if run via Python) self.ignore_updates = False # Ignore OCLP updates self.wxpython_variant = False # Determine if using wxPython variant + self.unpack_thread = None # Determine if unpack thread finished ## Hardware self.computer: device_probe.Computer = None # type: ignore diff --git a/resources/main.py b/resources/main.py index a15bbcc85..0a82dde57 100644 --- a/resources/main.py +++ b/resources/main.py @@ -4,7 +4,11 @@ from __future__ import print_function import subprocess import sys +import tempfile from pathlib import Path +import atexit +import time +import threading from resources import build, cli_menu, constants, utilities, device_probe, os_probe, defaults, arguments, install, tui_helpers from data import model_array @@ -40,7 +44,10 @@ class OpenCoreLegacyPatcher: launcher_script = launcher_script.replace("/resources/main.py", "/OpenCore-Patcher-GUI.command") self.constants.launcher_binary = launcher_binary self.constants.launcher_script = launcher_script + self.constants.unpack_thread = threading.Thread(target=self.reroute_payloads) + self.constants.unpack_thread.start() defaults.generate_defaults.probe(self.computer.real_model, True, self.constants) + if utilities.check_cli_args() is not None: print("- Detected arguments, switching to CLI mode") self.constants.gui_mode = True # Assumes no user interaction is required @@ -54,6 +61,66 @@ class OpenCoreLegacyPatcher: else: print(f"- No arguments present, loading {'GUI' if self.constants.wxpython_variant is True else 'TUI'} mode") + def reroute_payloads(self): + # if self.constants.launcher_binary and self.constants.wxpython_variant is True and not self.constants.launcher_script: + if True: + print("- Running in Binary GUI mode, switching to tmp directory") + self.temp_dir = tempfile.TemporaryDirectory() + print(f"- New payloads location: {self.temp_dir.name}") + # hdiutil create ./tmp.dmg -megabytes 32000 -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -megabytes 32000 + # hdiutil convert ./tmp.dmg -format UDZO -o payloads.dmg + + # hdiutil attach ./payloads.dmg -mountpoint tmp -nobrowse + + # create payloads directory + print("- Creating payloads directory") + Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True) + + use_zip = False + # unzip payloads.zip to payloads directory + + if use_zip is True: + print("- Unzipping payloads.zip") + output = subprocess.run(["unzip", "-o", "-q", "-d", self.temp_dir.name, f"{self.constants.payload_path}.zip"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if output.returncode == 0: + print(f"- Unzipped payloads.zip successfully: {self.temp_dir.name}") + self.constants.current_path = Path(self.temp_dir.name) + self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") + print(f"self.constants.current_path: {self.constants.current_path}") + print(f"self.constants.payload_path: {self.constants.payload_path}") + else: + print("- Failed to unzip payloads.zip, skipping") + else: + output = subprocess.run(["hdiutil", "attach", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay"))], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if output.returncode == 0: + print("- Mounted payloads.dmg") + self.constants.current_path = Path(self.temp_dir.name) + self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") + print(f"self.constants.current_path: {self.constants.current_path}") + print(f"self.constants.payload_path: {self.constants.payload_path}") + atexit.register(self.clean_up) + + else: + print("- Failed to mount payloads.dmg") + print(f"Output: {output.stdout.decode()}") + print(f"Return Code: {output.returncode}") + print("- Exiting...") + sys.exit(1) + + def clean_up(self): + output = subprocess.run(["hdiutil", "detach", f"{self.temp_dir.name}/payloads"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if output.returncode == 0: + print("- Unmounted payloads.dmg successfully") + else: + print("- Failed to unmount payloads.dmg, sleeping for 1 seconds and trying again") + time.sleep(1) + output = subprocess.run(["hdiutil", "detach", f"{self.temp_dir.name}/payloads"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if output.returncode == 0: + print("- Unmounted payloads.dmg successfully") + else: + print("- Failed to unmount payloads.dmg, skipping") + + def main_menu(self): response = None while not (response and response == -1): From b98fa0ced951a41f163d0f8a451c18865068dcb1 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 14:19:50 -0600 Subject: [PATCH 02/11] Add password to zip --- .github/workflows/build-app-wxpython.yml | 2 +- resources/main.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-app-wxpython.yml b/.github/workflows/build-app-wxpython.yml index 8d499a487..1542eca17 100644 --- a/.github/workflows/build-app-wxpython.yml +++ b/.github/workflows/build-app-wxpython.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v3 - run: python3 create_offline_build.py - - run: zip -r payloads.zip payloads + - run: zip -P password -r payloads.zip payloads - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher-GUI.spec - run: python3 ./payloads/binary.py $branch $commiturl $commitdate - run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' diff --git a/resources/main.py b/resources/main.py index 0a82dde57..78aabe990 100644 --- a/resources/main.py +++ b/resources/main.py @@ -76,12 +76,12 @@ class OpenCoreLegacyPatcher: print("- Creating payloads directory") Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True) - use_zip = False + use_zip = True # unzip payloads.zip to payloads directory if use_zip is True: print("- Unzipping payloads.zip") - output = subprocess.run(["unzip", "-o", "-q", "-d", self.temp_dir.name, f"{self.constants.payload_path}.zip"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = subprocess.run(["unzip", "-P", "password", "-o", "-q", "-d", self.temp_dir.name, f"{self.constants.payload_path}.zip"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if output.returncode == 0: print(f"- Unzipped payloads.zip successfully: {self.temp_dir.name}") self.constants.current_path = Path(self.temp_dir.name) @@ -90,6 +90,8 @@ class OpenCoreLegacyPatcher: print(f"self.constants.payload_path: {self.constants.payload_path}") else: print("- Failed to unzip payloads.zip, skipping") + print(f"Output: {output.stdout.decode('utf-8')}") + print(f"Return code: {output.returncode}") else: output = subprocess.run(["hdiutil", "attach", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay"))], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if output.returncode == 0: From 053641bf4f4afdb08a05bf2719e07991aad450e3 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 16:08:47 -0600 Subject: [PATCH 03/11] Set dmg as mount type --- .github/workflows/build-app-wxpython.yml | 2 +- OpenCore-Patcher-GUI.spec | 2 +- gui/gui_main.py | 21 ++++++++++++--- resources/main.py | 33 ++++++++++-------------- resources/sys_patch_download.py | 3 +-- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build-app-wxpython.yml b/.github/workflows/build-app-wxpython.yml index 1542eca17..b8e8cdbdb 100644 --- a/.github/workflows/build-app-wxpython.yml +++ b/.github/workflows/build-app-wxpython.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v3 - run: python3 create_offline_build.py - - run: zip -P password -r payloads.zip payloads + - run: hdiutil create ./tmp.dmg -megabytes 32000 -format UDZO -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -passphrase password -encryption - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher-GUI.spec - run: python3 ./payloads/binary.py $branch $commiturl $commitdate - run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' diff --git a/OpenCore-Patcher-GUI.spec b/OpenCore-Patcher-GUI.spec index fe93946de..ddda03cd8 100644 --- a/OpenCore-Patcher-GUI.spec +++ b/OpenCore-Patcher-GUI.spec @@ -9,7 +9,7 @@ block_cipher = None a = Analysis(['OpenCore-Patcher-GUI.command'], pathex=[], binaries=[], - datas=[('payloads.zip', '.')], + datas=[('payloads.dmg', '.')], hiddenimports=[], hookspath=[], hooksconfig={}, diff --git a/gui/gui_main.py b/gui/gui_main.py index cae12e80a..8a8453dd5 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -823,8 +823,6 @@ class wx_python_gui: # Button: Start Root Patching # Button: Revert Root Patches # Button: Return to Main Menu - while self.constants.unpack_thread.is_alive(): - time.sleep(0.1) self.frame.DestroyChildren() # Header @@ -1010,7 +1008,22 @@ class wx_python_gui: ) ) self.developer_note.Centre(wx.HORIZONTAL) - self.frame.SetSize(-1, self.developer_note.GetPosition().y + self.developer_note.GetSize().height + 80) + + self.progress_bar_new = wx.Gauge(self.frame, range=100, size=(200, 10)) + self.progress_bar_new.SetPosition( + wx.Point( + self.developer_note.GetPosition().x, + self.developer_note.GetPosition().y + self.developer_note.GetSize().height + 10 + ) + ) + self.progress_bar_new.SetValue(0) + self.progress_bar_new.Centre(wx.HORIZONTAL) + self.progress_bar_new.Pulse() + + self.frame.SetSize(-1, self.progress_bar_new.GetPosition().y + self.progress_bar_new.GetSize().height + 60) + self.frame.Show() + while self.constants.unpack_thread.is_alive(): + wx.GetApp().Yield() # Download resources sys.stdout=menu_redirect.RedirectLabel(self.developer_note) @@ -1154,6 +1167,8 @@ class wx_python_gui: sys.stdout = menu_redirect.RedirectText(self.text_box, True) sys.stderr = menu_redirect.RedirectText(self.text_box, True) wx.GetApp().Yield() + while self.constants.unpack_thread.is_alive(): + time.sleep(0.1) try: sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants, self.patches).start_unpatch() except Exception as e: diff --git a/resources/main.py b/resources/main.py index 78aabe990..d91bd7afb 100644 --- a/resources/main.py +++ b/resources/main.py @@ -1,6 +1,7 @@ # Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk from __future__ import print_function +import plistlib import subprocess import sys @@ -46,6 +47,7 @@ class OpenCoreLegacyPatcher: self.constants.launcher_script = launcher_script self.constants.unpack_thread = threading.Thread(target=self.reroute_payloads) self.constants.unpack_thread.start() + defaults.generate_defaults.probe(self.computer.real_model, True, self.constants) if utilities.check_cli_args() is not None: @@ -67,7 +69,7 @@ class OpenCoreLegacyPatcher: print("- Running in Binary GUI mode, switching to tmp directory") self.temp_dir = tempfile.TemporaryDirectory() print(f"- New payloads location: {self.temp_dir.name}") - # hdiutil create ./tmp.dmg -megabytes 32000 -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -megabytes 32000 + # hdiutil create ./tmp.dmg -megabytes 32000 -format UDZO -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -passphrase password -encryption # hdiutil convert ./tmp.dmg -format UDZO -o payloads.dmg # hdiutil attach ./payloads.dmg -mountpoint tmp -nobrowse @@ -76,7 +78,7 @@ class OpenCoreLegacyPatcher: print("- Creating payloads directory") Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True) - use_zip = True + use_zip = False # unzip payloads.zip to payloads directory if use_zip is True: @@ -86,22 +88,18 @@ class OpenCoreLegacyPatcher: print(f"- Unzipped payloads.zip successfully: {self.temp_dir.name}") self.constants.current_path = Path(self.temp_dir.name) self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") - print(f"self.constants.current_path: {self.constants.current_path}") - print(f"self.constants.payload_path: {self.constants.payload_path}") else: print("- Failed to unzip payloads.zip, skipping") print(f"Output: {output.stdout.decode('utf-8')}") print(f"Return code: {output.returncode}") else: - output = subprocess.run(["hdiutil", "attach", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay"))], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + self.clean_up() + output = subprocess.run(["hdiutil", "attach", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay")), "-passphrase", "password"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if output.returncode == 0: print("- Mounted payloads.dmg") self.constants.current_path = Path(self.temp_dir.name) self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") - print(f"self.constants.current_path: {self.constants.current_path}") - print(f"self.constants.payload_path: {self.constants.payload_path}") atexit.register(self.clean_up) - else: print("- Failed to mount payloads.dmg") print(f"Output: {output.stdout.decode()}") @@ -110,17 +108,14 @@ class OpenCoreLegacyPatcher: sys.exit(1) def clean_up(self): - output = subprocess.run(["hdiutil", "detach", f"{self.temp_dir.name}/payloads"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if output.returncode == 0: - print("- Unmounted payloads.dmg successfully") - else: - print("- Failed to unmount payloads.dmg, sleeping for 1 seconds and trying again") - time.sleep(1) - output = subprocess.run(["hdiutil", "detach", f"{self.temp_dir.name}/payloads"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if output.returncode == 0: - print("- Unmounted payloads.dmg successfully") - else: - print("- Failed to unmount payloads.dmg, skipping") + # Grab info on all dmgs mounted + dmg_info = subprocess.run(["hdiutil", "info", "-plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + dmg_info = plistlib.loads(dmg_info.stdout) + + for image in dmg_info["images"]: + if image["image-path"].endswith("payloads.dmg"): + print(f"- Unmounting payloads.dmg") + subprocess.run(["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def main_menu(self): diff --git a/resources/sys_patch_download.py b/resources/sys_patch_download.py index 31a2d9cd9..f2c2c9451 100644 --- a/resources/sys_patch_download.py +++ b/resources/sys_patch_download.py @@ -23,8 +23,7 @@ class grab_patcher_support_pkg: shutil.rmtree(self.constants.payload_local_binaries_root_path) download_result = None - local_zip = Path(self.constants.payload_path) / f"Universal-Binaries.zip" - if Path(local_zip).exists(): + if Path(self.constants.payload_local_binaries_root_path_zip).exists(): print(f"- Found local Universal-Binaries.zip, skipping download") download_result = True else: From 4cff4b7675ed921bd2162dda6334a069a335703c Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 16:25:11 -0600 Subject: [PATCH 04/11] Fix dmg name --- .github/workflows/build-app-wxpython.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-app-wxpython.yml b/.github/workflows/build-app-wxpython.yml index b8e8cdbdb..ddf175e6c 100644 --- a/.github/workflows/build-app-wxpython.yml +++ b/.github/workflows/build-app-wxpython.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v3 - run: python3 create_offline_build.py - - run: hdiutil create ./tmp.dmg -megabytes 32000 -format UDZO -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -passphrase password -encryption + - run: hdiutil create ./payloads.dmg -megabytes 32000 -format UDZO -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -passphrase password -encryption - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher-GUI.spec - run: python3 ./payloads/binary.py $branch $commiturl $commitdate - run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' From 45a04d5965c0a222bb6fc9115164a0d1e29ff8b7 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 16:37:17 -0600 Subject: [PATCH 05/11] gui_main.py: Adjust non-Metal detection --- gui/gui_main.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/gui/gui_main.py b/gui/gui_main.py index 8a8453dd5..90e08344c 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -103,8 +103,9 @@ class wx_python_gui: def use_non_metal_alternative(self): if self.constants.detected_os >= os_data.os_data.monterey: - if self.constants.host_is_non_metal is True: - return True + if Path("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLightOld.dylib").exists(): + if self.constants.host_is_non_metal is True: + return True return False def pulse_alternative(self, progress_bar): @@ -1009,20 +1010,21 @@ class wx_python_gui: ) self.developer_note.Centre(wx.HORIZONTAL) - self.progress_bar_new = wx.Gauge(self.frame, range=100, size=(200, 10)) - self.progress_bar_new.SetPosition( + self.progress_bar = wx.Gauge(self.frame, range=100, size=(200, 10)) + self.progress_bar.SetPosition( wx.Point( self.developer_note.GetPosition().x, self.developer_note.GetPosition().y + self.developer_note.GetSize().height + 10 ) ) - self.progress_bar_new.SetValue(0) - self.progress_bar_new.Centre(wx.HORIZONTAL) - self.progress_bar_new.Pulse() + self.progress_bar.SetValue(0) + self.progress_bar.Centre(wx.HORIZONTAL) + self.progress_bar.Pulse() - self.frame.SetSize(-1, self.progress_bar_new.GetPosition().y + self.progress_bar_new.GetSize().height + 60) + self.frame.SetSize(-1, self.progress_bar.GetPosition().y + self.progress_bar.GetSize().height + 60) self.frame.Show() while self.constants.unpack_thread.is_alive(): + self.pulse_alternative(self.progress_bar) wx.GetApp().Yield() # Download resources From 3ed3c14668a8317302bbcab7da3f16e5e2932cf0 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 16:55:17 -0600 Subject: [PATCH 06/11] Remove unused code path --- resources/main.py | 58 ++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/resources/main.py b/resources/main.py index d91bd7afb..78798de25 100644 --- a/resources/main.py +++ b/resources/main.py @@ -59,53 +59,39 @@ class OpenCoreLegacyPatcher: if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): print("- Rerouting payloads location") self.constants.payload_path = sys._MEIPASS / Path("payloads") + print("- Waiting for payloads to unpack...") + while self.constants.unpack_thread.is_alive(): + time.sleep(0.1) arguments.arguments().parse_arguments(self.constants) else: print(f"- No arguments present, loading {'GUI' if self.constants.wxpython_variant is True else 'TUI'} mode") def reroute_payloads(self): - # if self.constants.launcher_binary and self.constants.wxpython_variant is True and not self.constants.launcher_script: - if True: + if self.constants.launcher_binary and self.constants.wxpython_variant is True and not self.constants.launcher_script: print("- Running in Binary GUI mode, switching to tmp directory") self.temp_dir = tempfile.TemporaryDirectory() print(f"- New payloads location: {self.temp_dir.name}") - # hdiutil create ./tmp.dmg -megabytes 32000 -format UDZO -ov -volname "payloads" -fs HFS+ -srcfolder ./payloads -passphrase password -encryption - # hdiutil convert ./tmp.dmg -format UDZO -o payloads.dmg - - # hdiutil attach ./payloads.dmg -mountpoint tmp -nobrowse - - # create payloads directory print("- Creating payloads directory") Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True) - - use_zip = False - # unzip payloads.zip to payloads directory - - if use_zip is True: - print("- Unzipping payloads.zip") - output = subprocess.run(["unzip", "-P", "password", "-o", "-q", "-d", self.temp_dir.name, f"{self.constants.payload_path}.zip"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if output.returncode == 0: - print(f"- Unzipped payloads.zip successfully: {self.temp_dir.name}") - self.constants.current_path = Path(self.temp_dir.name) - self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") - else: - print("- Failed to unzip payloads.zip, skipping") - print(f"Output: {output.stdout.decode('utf-8')}") - print(f"Return code: {output.returncode}") + self.clean_up() + output = subprocess.run( + [ + "hdiutil", "attach", "-noverify", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), + "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay")), "-passphrase", "password" + ], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT + ) + if output.returncode == 0: + print("- Mounted payloads.dmg") + self.constants.current_path = Path(self.temp_dir.name) + self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") + atexit.register(self.clean_up) else: - self.clean_up() - output = subprocess.run(["hdiutil", "attach", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay")), "-passphrase", "password"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if output.returncode == 0: - print("- Mounted payloads.dmg") - self.constants.current_path = Path(self.temp_dir.name) - self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") - atexit.register(self.clean_up) - else: - print("- Failed to mount payloads.dmg") - print(f"Output: {output.stdout.decode()}") - print(f"Return Code: {output.returncode}") - print("- Exiting...") - sys.exit(1) + print("- Failed to mount payloads.dmg") + print(f"Output: {output.stdout.decode()}") + print(f"Return Code: {output.returncode}") + print("- Exiting...") + sys.exit(1) def clean_up(self): # Grab info on all dmgs mounted From ccdfe740d9a4251e015d2548d4ce02b71f62450e Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 17:14:46 -0600 Subject: [PATCH 07/11] Add Build info to GUI --- .gitignore | 1 + OpenCore-Patcher-GUI.spec | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6ef1dbd29..cb41309cf 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ __pycache__/ /payloads/Universal-Binaries /payloads/OpenCore-Legacy-Patcher /payloads/InstallAssistant.pkg.integrityDataV1 +/payloads.dmg diff --git a/OpenCore-Patcher-GUI.spec b/OpenCore-Patcher-GUI.spec index ddda03cd8..c01a12f89 100644 --- a/OpenCore-Patcher-GUI.spec +++ b/OpenCore-Patcher-GUI.spec @@ -54,7 +54,7 @@ app = BUNDLE(coll, "LSMinimumSystemVersion": "10.10.0", "NSRequiresAquaSystemAppearance": False, "NSHighResolutionCapable": True, - #"Build Date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), - #"BuildMachineOSBuild": subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().strip(), + "Build Date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "BuildMachineOSBuild": subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().strip(), "NSPrincipalClass": "NSApplication", }) From 3134530b4cbf873a3bc3e6ad9267082e718ae964 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 19:41:13 -0600 Subject: [PATCH 08/11] Move payload reroutes to dedicated class --- gui/gui_main.py | 2 +- resources/main.py | 44 ++----------------------- resources/reroute_payloads.py | 61 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 43 deletions(-) create mode 100644 resources/reroute_payloads.py diff --git a/gui/gui_main.py b/gui/gui_main.py index 90e08344c..5b868071b 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -1288,7 +1288,7 @@ class wx_python_gui: thread_ia = threading.Thread(target=ia) thread_ia.start() - while thread_ia.is_alive(): + while thread_ia.is_alive() or self.constants.unpack_thread.is_alive(): self.pulse_alternative(self.progress_bar) wx.GetApp().Yield() available_installers = self.available_installers diff --git a/resources/main.py b/resources/main.py index 78798de25..47ac4ac4d 100644 --- a/resources/main.py +++ b/resources/main.py @@ -1,17 +1,14 @@ # Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk from __future__ import print_function -import plistlib import subprocess import sys -import tempfile from pathlib import Path -import atexit import time import threading -from resources import build, cli_menu, constants, utilities, device_probe, os_probe, defaults, arguments, install, tui_helpers +from resources import build, cli_menu, constants, utilities, device_probe, os_probe, defaults, arguments, install, tui_helpers, reroute_payloads from data import model_array class OpenCoreLegacyPatcher: @@ -45,7 +42,7 @@ class OpenCoreLegacyPatcher: launcher_script = launcher_script.replace("/resources/main.py", "/OpenCore-Patcher-GUI.command") self.constants.launcher_binary = launcher_binary self.constants.launcher_script = launcher_script - self.constants.unpack_thread = threading.Thread(target=self.reroute_payloads) + self.constants.unpack_thread = threading.Thread(target=reroute_payloads.reroute_payloads(self.constants).setup_tmp_disk_image) self.constants.unpack_thread.start() defaults.generate_defaults.probe(self.computer.real_model, True, self.constants) @@ -66,43 +63,6 @@ class OpenCoreLegacyPatcher: else: print(f"- No arguments present, loading {'GUI' if self.constants.wxpython_variant is True else 'TUI'} mode") - def reroute_payloads(self): - if self.constants.launcher_binary and self.constants.wxpython_variant is True and not self.constants.launcher_script: - print("- Running in Binary GUI mode, switching to tmp directory") - self.temp_dir = tempfile.TemporaryDirectory() - print(f"- New payloads location: {self.temp_dir.name}") - print("- Creating payloads directory") - Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True) - self.clean_up() - output = subprocess.run( - [ - "hdiutil", "attach", "-noverify", f"{self.constants.payload_path}.dmg", "-mountpoint", Path(self.temp_dir.name / Path("payloads")), - "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay")), "-passphrase", "password" - ], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT - ) - if output.returncode == 0: - print("- Mounted payloads.dmg") - self.constants.current_path = Path(self.temp_dir.name) - self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") - atexit.register(self.clean_up) - else: - print("- Failed to mount payloads.dmg") - print(f"Output: {output.stdout.decode()}") - print(f"Return Code: {output.returncode}") - print("- Exiting...") - sys.exit(1) - - def clean_up(self): - # Grab info on all dmgs mounted - dmg_info = subprocess.run(["hdiutil", "info", "-plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - dmg_info = plistlib.loads(dmg_info.stdout) - - for image in dmg_info["images"]: - if image["image-path"].endswith("payloads.dmg"): - print(f"- Unmounting payloads.dmg") - subprocess.run(["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - def main_menu(self): response = None diff --git a/resources/reroute_payloads.py b/resources/reroute_payloads.py new file mode 100644 index 000000000..2a407e60a --- /dev/null +++ b/resources/reroute_payloads.py @@ -0,0 +1,61 @@ +# Reoute binaries to tmp directory, and mount a disk image of the payloads +# Implements a shadowfile to avoid direct writes to the dmg +# Copyright (C) 2022, Mykola Grymalyuk + +import sys +import plistlib +from pathlib import Path +import subprocess +import tempfile +import atexit + +class reroute_payloads: + def __init__(self, constants): + self.constants = constants + + def setup_tmp_disk_image(self): + # Create a temp directory to mount the payloads.dmg + # Then reroute r/w to this new temp directory + # Currently only applicable for GUI variant + if self.constants.launcher_binary and self.constants.wxpython_variant is True and not self.constants.launcher_script: + print("- Running in Binary GUI mode, switching to tmp directory") + self.temp_dir = tempfile.TemporaryDirectory() + print(f"- New payloads location: {self.temp_dir.name}") + print("- Creating payloads directory") + Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True) + self.unmount_active_dmgs() + output = subprocess.run( + [ + "hdiutil", "attach", "-noverify", f"{self.constants.payload_path}.dmg", + "-mountpoint", Path(self.temp_dir.name / Path("payloads")), + "-nobrowse", "-shadow", Path(self.temp_dir.name / Path("payloads_overlay")), + "-passphrase", "password" + ], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT + ) + if output.returncode == 0: + print("- Mounted payloads.dmg") + self.constants.current_path = Path(self.temp_dir.name) + self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads") + atexit.register(self.unmount_active_dmgs) + else: + print("- Failed to mount payloads.dmg") + print(f"Output: {output.stdout.decode()}") + print(f"Return Code: {output.returncode}") + print("- Exiting...") + sys.exit(1) + + def unmount_active_dmgs(self): + # Find all DMGs that are mounted, and forcefully unmount them + # If our disk image was previously mounted, we need to unmount it to use again + # This can happen if we crash during a previous scession, however 'atexit' class should hopefully avoid this + dmg_info = subprocess.run(["hdiutil", "info", "-plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + dmg_info = plistlib.loads(dmg_info.stdout) + + for image in dmg_info["images"]: + if image["image-path"].endswith("payloads.dmg"): + print(f"- Unmounting payloads.dmg") + subprocess.run( + ["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT + ) \ No newline at end of file From e6d69d5d478637f42327b2df7030c35542b8e054 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 19:46:42 -0600 Subject: [PATCH 09/11] Sync changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31e7a5f77..4d6544285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Fix Bluetooth support in 12.4 Release - Applicable for BCM2046 and BCM2070 chipsets - Fix backported to 0.4.5 release +- GUI Enhancements: + - Greatly increase GUI load times (300-800% on average) ## 0.4.5 - Fix AutoPatcher.pkg download on releases From c8a70764b824eb0101ea306b1b9af600a7be4a57 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 19:53:59 -0600 Subject: [PATCH 10/11] CHANGELOG.md: Adjust wording --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d6544285..7fc548012 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - Applicable for BCM2046 and BCM2070 chipsets - Fix backported to 0.4.5 release - GUI Enhancements: - - Greatly increase GUI load times (300-800% on average) + - Greatly speed up GUI load times (300-800% on average) ## 0.4.5 - Fix AutoPatcher.pkg download on releases From 23119dedc93ecd3b29c4c173ba5c990757c7cd27 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Wed, 18 May 2022 20:11:14 -0600 Subject: [PATCH 11/11] Add better CLI error handling --- CHANGELOG.md | 2 +- resources/constants.py | 1 + resources/main.py | 1 + resources/sys_patch.py | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fc548012..ce9e745b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - Applicable for BCM2046 and BCM2070 chipsets - Fix backported to 0.4.5 release - GUI Enhancements: - - Greatly speed up GUI load times (300-800% on average) + - Greatly improve GUI load times (300-800% on average) ## 0.4.5 - Fix AutoPatcher.pkg download on releases diff --git a/resources/constants.py b/resources/constants.py index 048bc001b..c1e71c114 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -107,6 +107,7 @@ class Constants: self.ignore_updates = False # Ignore OCLP updates self.wxpython_variant = False # Determine if using wxPython variant self.unpack_thread = None # Determine if unpack thread finished + self.cli_mode = False # Determine if running in CLI mode ## Hardware self.computer: device_probe.Computer = None # type: ignore diff --git a/resources/main.py b/resources/main.py index 47ac4ac4d..ca79a5911 100644 --- a/resources/main.py +++ b/resources/main.py @@ -53,6 +53,7 @@ class OpenCoreLegacyPatcher: ignore_args = ["--auto_patch", "--gui_patch", "--gui_unpatch"] if not any(x in sys.argv for x in ignore_args): self.constants.current_path = Path.cwd() + self.constants.cli_mode = True if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): print("- Rerouting payloads location") self.constants.payload_path = sys._MEIPASS / Path("payloads") diff --git a/resources/sys_patch.py b/resources/sys_patch.py index 1225ee949..c08989839 100644 --- a/resources/sys_patch.py +++ b/resources/sys_patch.py @@ -309,7 +309,7 @@ class PatchSysVolume: return output def download_files(self): - if self.constants.gui_mode is False or "Library/InstallerSandboxes/" in str(self.constants.payload_path): + if self.constants.cli_mode is True: download_result, link = sys_patch_download.grab_patcher_support_pkg(self.constants).download_files() else: download_result = True