Reformat logging system

This commit is contained in:
Mykola Grymalyuk
2023-05-24 12:24:09 -06:00
parent 80ea0cd217
commit d8a79cf67e
30 changed files with 311 additions and 240 deletions
+42 -42
View File
@@ -30,7 +30,7 @@ class CreateBinary:
def __init__(self):
start = time.time()
print("- Starting build script")
print("Starting build script")
self.args = self._parse_arguments()
@@ -39,7 +39,7 @@ class CreateBinary:
self._preflight_processes()
self._build_binary()
self._postflight_processes()
print(f"- Build script completed in {str(round(time.time() - start, 2))} seconds")
print(f"Build script completed in {str(round(time.time() - start, 2))} seconds")
def _set_cwd(self):
@@ -48,7 +48,7 @@ class CreateBinary:
"""
os.chdir(Path(__file__).resolve().parent)
print(f"- Current Working Directory: \n\t{os.getcwd()}")
print(f"Current Working Directory: \n\t{os.getcwd()}")
def _parse_arguments(self):
@@ -88,7 +88,7 @@ class CreateBinary:
pyinstaller_path = f"{python_bin_dir}pyinstaller"
if not Path(pyinstaller_path).exists():
print(f" - pyinstaller not found:\n\t{pyinstaller_path}")
print(f"- pyinstaller not found:\n\t{pyinstaller_path}")
raise Exception("pyinstaller not found")
self.pyinstaller_path = pyinstaller_path
@@ -99,7 +99,7 @@ class CreateBinary:
Start preflight processes
"""
print("- Starting preflight processes")
print("Starting preflight processes")
self._setup_pathing()
self._delete_extra_binaries()
self._download_resources()
@@ -111,7 +111,7 @@ class CreateBinary:
Start postflight processes
"""
print("- Starting postflight processes")
print("Starting postflight processes")
self._patch_load_command()
self._add_commit_data()
self._post_flight_cleanup()
@@ -124,19 +124,19 @@ class CreateBinary:
"""
if Path(f"./dist/OpenCore-Patcher.app").exists():
print("- Found OpenCore-Patcher.app, removing...")
print("Found OpenCore-Patcher.app, removing...")
rm_output = subprocess.run(
["rm", "-rf", "./dist/OpenCore-Patcher.app"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print("- Remove failed")
print("Remove failed")
print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed")
self._embed_key()
print("- Building GUI binary...")
print("Building GUI binary...")
build_args = [self.pyinstaller_path, "./OpenCore-Patcher-GUI.spec", "--noconfirm"]
build_result = subprocess.run(build_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -144,12 +144,12 @@ class CreateBinary:
self._strip_key()
if build_result.returncode != 0:
print("- Build failed")
print("Build failed")
print(build_result.stderr.decode('utf-8'))
raise Exception("Build failed")
# Next embed support icns into ./Resources
print("- Embedding icns...")
print("Embedding icns...")
for file in Path("payloads/Icon/AppIcons").glob("*.icns"):
subprocess.run(
["cp", str(file), "./dist/OpenCore-Patcher.app/Contents/Resources/"],
@@ -165,15 +165,15 @@ class CreateBinary:
"""
if not self.args.key:
print("- No developer key provided, skipping...")
print("No developer key provided, skipping...")
return
if not self.args.site:
print("- No site provided, skipping...")
print("No site provided, skipping...")
return
print("- Embedding developer key...")
print("Embedding developer key...")
if not Path("./resources/analytics_handler.py").exists():
print("- analytics_handler.py not found")
print("analytics_handler.py not found")
return
lines = []
@@ -196,15 +196,15 @@ class CreateBinary:
"""
if not self.args.key:
print("- No developer key provided, skipping...")
print("No developer key provided, skipping...")
return
if not self.args.site:
print("- No site provided, skipping...")
print("No site provided, skipping...")
return
print("- Stripping developer key...")
print("Stripping developer key...")
if not Path("./resources/analytics_handler.py").exists():
print("- analytics_handler.py not found")
print("analytics_handler.py not found")
return
lines = []
@@ -247,17 +247,17 @@ class CreateBinary:
]
print("- Deleting extra binaries...")
print("Deleting extra binaries...")
for file in Path("payloads").glob(pattern="*"):
if file.is_dir():
if file.name in whitelist_folders:
continue
print(f" - Deleting {file.name}")
print(f"- Deleting {file.name}")
subprocess.run(["rm", "-rf", file])
else:
if file.name in whitelist_files:
continue
print(f" - Deleting {file.name}")
print(f"- Deleting {file.name}")
subprocess.run(["rm", "-f", file])
@@ -271,23 +271,23 @@ class CreateBinary:
"Universal-Binaries.dmg"
]
print("- Downloading required resources...")
print("Downloading required resources...")
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}")
rm_output = subprocess.run(
["rm", "-rf", f"./{resource}"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print("- Remove failed")
print("Remove failed")
print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed")
else:
print(f" - {resource} already exists, skipping download")
print(f"- {resource} already exists, skipping download")
continue
print(f" - Downloading {resource}...")
print(f"- Downloading {resource}...")
download_result = subprocess.run(
[
@@ -298,11 +298,11 @@ class CreateBinary:
)
if download_result.returncode != 0:
print(" - Download failed")
print("- Download failed")
print(download_result.stderr.decode('utf-8'))
raise Exception("Download failed")
if not Path(f"./{resource}").exists():
print(f" - {resource} not found")
print(f"- {resource} not found")
raise Exception(f"{resource} not found")
@@ -315,20 +315,20 @@ class CreateBinary:
if Path("./payloads.dmg").exists():
if not self.args.reset_binaries:
print(" - payloads.dmg already exists, skipping creation")
print("- payloads.dmg already exists, skipping creation")
return
print(" - Removing old payloads.dmg")
print("- Removing old payloads.dmg")
rm_output = subprocess.run(
["rm", "-rf", "./payloads.dmg"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print("- Remove failed")
print("Remove failed")
print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed")
print(" - Generating DMG...")
print("- Generating DMG...")
dmg_output = subprocess.run([
'hdiutil', 'create', './payloads.dmg',
'-megabytes', '32000', # Overlays can only be as large as the disk image allows
@@ -339,11 +339,11 @@ class CreateBinary:
'-passphrase', 'password', '-encryption'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if dmg_output.returncode != 0:
print(" - DMG generation failed")
print("- DMG generation failed")
print(dmg_output.stderr.decode('utf-8'))
raise Exception("DMG generation failed")
print(" - DMG generation complete")
print("- DMG generation complete")
def _add_commit_data(self):
@@ -352,7 +352,7 @@ class CreateBinary:
"""
if not self.args.branch and not self.args.commit and not self.args.commit_date:
print(" - No commit data provided, adding source info")
print("- No commit data provided, adding source info")
branch = "Built from source"
commit_url = ""
commit_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
@@ -360,7 +360,7 @@ class CreateBinary:
branch = self.args.branch
commit_url = self.args.commit
commit_date = self.args.commit_date
print(" - Adding commit data to Info.plist")
print("- Adding commit data to Info.plist")
plist_path = Path("./dist/OpenCore-Patcher.app/Contents/Info.plist")
plist = plistlib.load(Path(plist_path).open("rb"))
plist["Github"] = {
@@ -389,7 +389,7 @@ class CreateBinary:
"""
print(" - Patching LC_VERSION_MIN_MACOSX")
print("- Patching LC_VERSION_MIN_MACOSX")
path = './dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher'
find = b'\x00\x0D\x0A\x00' # 10.13 (0xA0D)
replace = b'\x00\x0A\x0A\x00' # 10.10 (0xA0A)
@@ -406,13 +406,13 @@ class CreateBinary:
"""
path = "./dist/OpenCore-Patcher"
print(f" - Removing {path}")
print(f"- Removing {path}")
rm_output = subprocess.run(
["rm", "-rf", path],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print(f" - Remove failed: {path}")
print(f"- Remove failed: {path}")
print(rm_output.stderr.decode('utf-8'))
raise Exception(f"Remove failed: {path}")
@@ -422,13 +422,13 @@ class CreateBinary:
Validate generated binary
"""
print(" - Validating binary")
print("- Validating binary")
validate_output = subprocess.run(
["./dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher", "--build", "--model", "MacPro3,1"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if validate_output.returncode != 0:
print(" - Validation failed")
print("- Validation failed")
print(validate_output.stderr.decode('utf-8'))
raise Exception("Validation failed")
+5 -4
View File
@@ -59,9 +59,9 @@ class arguments:
Start root volume patching
"""
logging.info("- Set System Volume patching")
logging.info("Set System Volume patching")
if "Library/InstallerSandboxes/" in str(self.constants.payload_path):
logging.info("- Running from Installer Sandbox")
logging.info("- Running from Installer Sandbox, blocking OS updaters")
thread = threading.Thread(target=sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants, None).start_patch)
thread.start()
while thread.is_alive():
@@ -75,7 +75,7 @@ class arguments:
"""
Start root volume unpatching
"""
logging.info("- Set System Volume unpatching")
logging.info("Set System Volume unpatching")
sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants, None).start_unpatch()
@@ -84,7 +84,7 @@ class arguments:
Start root volume auto patching
"""
logging.info("- Set Auto patching")
logging.info("Set Auto patching")
sys_patch_auto.AutomaticSysPatch(self.constants).start_auto_patch()
@@ -92,6 +92,7 @@ class arguments:
"""
Start config building process
"""
logging.info("Set OpenCore Build")
if self.args.model:
if self.args.model:
+4 -4
View File
@@ -136,7 +136,7 @@ class BuildSupport:
for acpi in config_plist["ACPI"]["Add"]:
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/ACPI") / Path(acpi["Path"])).exists():
logging.info(f" - Missing ACPI Table: {acpi['Path']}")
logging.info(f"- Missing ACPI Table: {acpi['Path']}")
raise Exception(f"Missing ACPI Table: {acpi['Path']}")
for kext in config_plist["Kernel"]["Add"]:
@@ -155,19 +155,19 @@ class BuildSupport:
for tool in config_plist["Misc"]["Tools"]:
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools") / Path(tool["Path"])).exists():
logging.info(f" - Missing tool: {tool['Path']}")
logging.info(f"- Missing tool: {tool['Path']}")
raise Exception(f"Missing tool: {tool['Path']}")
for driver in config_plist["UEFI"]["Drivers"]:
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers") / Path(driver["Path"])).exists():
logging.info(f" - Missing driver: {driver['Path']}")
logging.info(f"- Missing driver: {driver['Path']}")
raise Exception(f"Missing driver: {driver['Path']}")
# Validating local files
# Report if they have no associated config.plist entry (i.e. they're not being used)
for tool_files in Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools")).glob("*"):
if tool_files.name not in [x["Path"] for x in config_plist["Misc"]["Tools"]]:
logging.info(f" - Missing tool from config: {tool_files.name}")
logging.info(f"- Missing tool from config: {tool_files.name}")
raise Exception(f"Missing tool from config: {tool_files.name}")
for driver_file in Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers")).glob("*"):
+5 -5
View File
@@ -48,7 +48,7 @@ class GlobalEnviromentSettings:
try:
plistlib.dump(plist, Path(self.global_settings_plist).open("wb"))
except PermissionError:
logging.info("- Failed to write to global settings file")
logging.info("Failed to write to global settings file")
def _generate_settings_file(self) -> None:
@@ -57,7 +57,7 @@ class GlobalEnviromentSettings:
try:
plistlib.dump({"Developed by Dortania": True,}, Path(self.global_settings_plist).open("wb"))
except PermissionError:
logging.info("- Permission error: Unable to write to global settings file")
logging.info("Permission error: Unable to write to global settings file")
def _convert_defaults_to_global_settings(self) -> None:
@@ -76,14 +76,14 @@ class GlobalEnviromentSettings:
try:
plistlib.dump(global_settings_plist, Path(self.global_settings_plist).open("wb"))
except PermissionError:
logging.info("- Permission error: Unable to write to global settings file")
logging.info("Permission error: Unable to write to global settings file")
return
# delete defaults plist
try:
Path(defaults_path).unlink()
except PermissionError:
logging.info("- Permission error: Unable to delete defaults plist")
logging.info("Permission error: Unable to delete defaults plist")
def _fix_file_permission(self) -> None:
@@ -100,6 +100,6 @@ class GlobalEnviromentSettings:
# Set file permission to allow any user to write to log file
result = subprocess.run(["chmod", "777", self.global_settings_plist], capture_output=True)
if result.returncode != 0:
logging.warning("- Failed to fix settings file permissions:")
logging.warning("Failed to fix settings file permissions:")
if result.stderr:
logging.warning(result.stderr.decode("utf-8"))
+15 -15
View File
@@ -88,13 +88,13 @@ class tui_disk_installation:
def install_opencore(self, full_disk_identifier: str):
# TODO: Apple Script fails in Yosemite(?) and older
logging.info(f"- Mounting partition: {full_disk_identifier}")
logging.info(f"Mounting partition: {full_disk_identifier}")
if self.constants.detected_os >= os_data.os_data.el_capitan and not self.constants.recovery_status:
try:
applescript.AppleScript(f'''do shell script "diskutil mount {full_disk_identifier}" with prompt "OpenCore Legacy Patcher needs administrator privileges to mount this volume." with administrator privileges without altering line endings''').run()
except applescript.ScriptError as e:
if "User canceled" in str(e):
logging.info("- Mount cancelled by user")
logging.info("Mount cancelled by user")
return
logging.info(f"An error occurred: {e}")
if utilities.check_boot_mode() == "safe_boot":
@@ -104,7 +104,7 @@ class tui_disk_installation:
else:
result = subprocess.run(f"diskutil mount {full_disk_identifier}".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
logging.info("- Mount failed")
logging.info("Mount failed")
logging.info(result.stderr.decode())
return
@@ -124,18 +124,18 @@ class tui_disk_installation:
return False
if (mount_path / Path("EFI/OC")).exists():
logging.info("- Removing preexisting EFI/OC folder")
logging.info("Removing preexisting EFI/OC folder")
subprocess.run(["rm", "-rf", mount_path / Path("EFI/OC")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if (mount_path / Path("System")).exists():
logging.info("- Removing preexisting System folder")
logging.info("Removing preexisting System folder")
subprocess.run(["rm", "-rf", mount_path / Path("System")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if (mount_path / Path("boot.efi")).exists():
logging.info("- Removing preexisting boot.efi")
logging.info("Removing preexisting boot.efi")
subprocess.run(["rm", mount_path / Path("boot.efi")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
logging.info("- Copying OpenCore onto EFI partition")
logging.info("Copying OpenCore onto EFI partition")
subprocess.run(["mkdir", "-p", mount_path / Path("EFI")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
subprocess.run(["cp", "-r", self.constants.opencore_release_folder / Path("EFI/OC"), mount_path / Path("EFI/OC")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
subprocess.run(["cp", "-r", self.constants.opencore_release_folder / Path("System"), mount_path / Path("System")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -144,7 +144,7 @@ class tui_disk_installation:
subprocess.run(["cp", self.constants.opencore_release_folder / Path("boot.efi"), mount_path / Path("boot.efi")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if self.constants.boot_efi is True:
logging.info("- Converting Bootstrap to BOOTx64.efi")
logging.info("Converting Bootstrap to BOOTx64.efi")
if (mount_path / Path("EFI/BOOT")).exists():
subprocess.run(["rm", "-rf", mount_path / Path("EFI/BOOT")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Path(mount_path / Path("EFI/BOOT")).mkdir()
@@ -152,23 +152,23 @@ class tui_disk_installation:
subprocess.run(["rm", "-rf", mount_path / Path("System")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if self._determine_sd_card(sd_type) is True:
logging.info("- Adding SD Card icon")
logging.info("Adding SD Card icon")
subprocess.run(["cp", self.constants.icon_path_sd, mount_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
elif ssd_type is True:
logging.info("- Adding SSD icon")
logging.info("Adding SSD icon")
subprocess.run(["cp", self.constants.icon_path_ssd, mount_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
elif disk_type == "USB":
logging.info("- Adding External USB Drive icon")
logging.info("Adding External USB Drive icon")
subprocess.run(["cp", self.constants.icon_path_external, mount_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
else:
logging.info("- Adding Internal Drive icon")
logging.info("Adding Internal Drive icon")
subprocess.run(["cp", self.constants.icon_path_internal, mount_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
logging.info("- Cleaning install location")
logging.info("Cleaning install location")
if not self.constants.recovery_status:
logging.info("- Unmounting EFI partition")
logging.info("Unmounting EFI partition")
subprocess.run(["diskutil", "umount", mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
logging.info("- OpenCore transfer complete")
logging.info("OpenCore transfer complete")
return True
+58 -58
View File
@@ -94,7 +94,7 @@ class KernelDebugKitObject:
global KDK_ASSET_LIST
logging.info("- Pulling KDK list from KdkSupportPkg API")
logging.info("Pulling KDK list from KdkSupportPkg API")
if KDK_ASSET_LIST:
return KDK_ASSET_LIST
@@ -107,11 +107,11 @@ class KernelDebugKitObject:
timeout=5
)
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError):
logging.info("- Could not contact KDK API")
logging.info("Could not contact KDK API")
return None
if results.status_code != 200:
logging.info("- Could not fetch KDK list")
logging.info("Could not fetch KDK list")
return None
KDK_ASSET_LIST = sorted(results.json(), key=lambda x: (packaging.version.parse(x["version"]), datetime.datetime.fromisoformat(x["date"])), reverse=True)
@@ -138,12 +138,12 @@ class KernelDebugKitObject:
if os_data.os_conversion.os_to_kernel(str(parsed_version.major)) < os_data.os_data.ventura:
self.error_msg = "KDKs are not required for macOS Monterey or older"
logging.warning(f"- {self.error_msg}")
logging.warning(f"{self.error_msg}")
return
self.kdk_installed_path = self._local_kdk_installed()
if self.kdk_installed_path:
logging.info(f"- KDK already installed ({Path(self.kdk_installed_path).name}), skipping")
logging.info(f"KDK already installed ({Path(self.kdk_installed_path).name}), skipping")
self.kdk_already_installed = True
self.success = True
return
@@ -151,29 +151,29 @@ class KernelDebugKitObject:
remote_kdk_version = self._get_remote_kdks()
if remote_kdk_version is None:
logging.warning("- Failed to fetch KDK list, falling back to local KDK matching")
logging.warning("Failed to fetch KDK list, falling back to local KDK matching")
# First check if a KDK matching the current macOS version is installed
# ex. 13.0.1 vs 13.0
loose_version = f"{parsed_version.major}.{parsed_version.minor}"
logging.info(f"- Checking for KDKs loosely matching {loose_version}")
logging.info(f"Checking for KDKs loosely matching {loose_version}")
self.kdk_installed_path = self._local_kdk_installed(match=loose_version, check_version=True)
if self.kdk_installed_path:
logging.info(f"- Found matching KDK: {Path(self.kdk_installed_path).name}")
logging.info(f"Found matching KDK: {Path(self.kdk_installed_path).name}")
self.kdk_already_installed = True
self.success = True
return
older_version = f"{parsed_version.major}.{parsed_version.minor - 1 if parsed_version.minor > 0 else 0}"
logging.info(f"- Checking for KDKs matching {older_version}")
logging.info(f"Checking for KDKs matching {older_version}")
self.kdk_installed_path = self._local_kdk_installed(match=older_version, check_version=True)
if self.kdk_installed_path:
logging.info(f"- Found matching KDK: {Path(self.kdk_installed_path).name}")
logging.info(f"Found matching KDK: {Path(self.kdk_installed_path).name}")
self.kdk_already_installed = True
self.success = True
return
logging.warning(f"- Couldn't find KDK matching {host_version} or {older_version}, please install one manually")
logging.warning(f"Couldn't find KDK matching {host_version} or {older_version}, please install one manually")
self.error_msg = f"Could not contact KdkSupportPkg API, and no KDK matching {host_version} ({host_build}) or {older_version} was installed.\nPlease ensure you have a network connection or manually install a KDK."
@@ -211,32 +211,32 @@ class KernelDebugKitObject:
if self.kdk_url == "":
if self.kdk_closest_match_url == "":
logging.warning(f"- No KDKs found for {host_build} ({host_version})")
logging.warning(f"No KDKs found for {host_build} ({host_version})")
self.error_msg = f"No KDKs found for {host_build} ({host_version})"
return
logging.info(f"- No direct match found for {host_build}, falling back to closest match")
logging.info(f"- Closest Match: {self.kdk_closest_match_url_build} ({self.kdk_closest_match_url_version})")
logging.info(f"No direct match found for {host_build}, falling back to closest match")
logging.info(f"Closest Match: {self.kdk_closest_match_url_build} ({self.kdk_closest_match_url_version})")
self.kdk_url = self.kdk_closest_match_url
self.kdk_url_build = self.kdk_closest_match_url_build
self.kdk_url_version = self.kdk_closest_match_url_version
self.kdk_url_expected_size = self.kdk_closest_match_url_expected_size
else:
logging.info(f"- Direct match found for {host_build} ({host_version})")
logging.info(f"Direct match found for {host_build} ({host_version})")
# Check if this KDK is already installed
self.kdk_installed_path = self._local_kdk_installed(match=self.kdk_url_build)
if self.kdk_installed_path:
logging.info(f"- KDK already installed ({Path(self.kdk_installed_path).name}), skipping")
logging.info(f"KDK already installed ({Path(self.kdk_installed_path).name}), skipping")
self.kdk_already_installed = True
self.success = True
return
logging.info("- Following KDK is recommended:")
logging.info(f"- KDK Build: {self.kdk_url_build}")
logging.info(f"- KDK Version: {self.kdk_url_version}")
logging.info(f"- KDK URL: {self.kdk_url}")
logging.info("Following KDK is recommended:")
logging.info(f"- KDK Build: {self.kdk_url_build}")
logging.info(f"- KDK Version: {self.kdk_url_version}")
logging.info(f"- KDK URL: {self.kdk_url}")
self.success = True
@@ -256,7 +256,7 @@ class KernelDebugKitObject:
self.error_msg = ""
if self.kdk_already_installed:
logging.info("- No download required, KDK already installed")
logging.info("No download required, KDK already installed")
self.success = True
return None
@@ -265,7 +265,7 @@ class KernelDebugKitObject:
logging.error(self.error_msg)
return None
logging.info(f"- Returning DownloadObject for KDK: {Path(self.kdk_url).name}")
logging.info(f"Returning DownloadObject for KDK: {Path(self.kdk_url).name}")
self.success = True
kdk_download_path = self.constants.kdk_download_path if override_path == "" else Path(override_path)
@@ -294,7 +294,7 @@ class KernelDebugKitObject:
plist_path.touch()
plistlib.dump(kdk_dict, plist_path.open("wb"), sort_keys=False)
except Exception as e:
logging.error(f"- Failed to generate KDK Info.plist: {e}")
logging.error(f"Failed to generate KDK Info.plist: {e}")
def _local_kdk_valid(self, kdk_path: Path) -> bool:
@@ -314,14 +314,14 @@ class KernelDebugKitObject:
"""
if not Path(f"{kdk_path}/System/Library/CoreServices/SystemVersion.plist").exists():
logging.info(f"- Corrupted KDK found ({kdk_path.name}), removing due to missing SystemVersion.plist")
logging.info(f"Corrupted KDK found ({kdk_path.name}), removing due to missing SystemVersion.plist")
self._remove_kdk(kdk_path)
return False
# Get build from KDK
kdk_plist_data = plistlib.load(Path(f"{kdk_path}/System/Library/CoreServices/SystemVersion.plist").open("rb"))
if "ProductBuildVersion" not in kdk_plist_data:
logging.info(f"- Corrupted KDK found ({kdk_path.name}), removing due to missing ProductBuildVersion")
logging.info(f"Corrupted KDK found ({kdk_path.name}), removing due to missing ProductBuildVersion")
self._remove_kdk(kdk_path)
return False
@@ -331,7 +331,7 @@ class KernelDebugKitObject:
result = subprocess.run(["pkgutil", "--files", f"com.apple.pkg.KDK.{kdk_build}"], capture_output=True)
if result.returncode != 0:
# If pkg receipt is missing, we'll fallback to legacy validation
logging.info(f"- pkg receipt missing for {kdk_path.name}, falling back to legacy validation")
logging.info(f"pkg receipt missing for {kdk_path.name}, falling back to legacy validation")
return self._local_kdk_valid_legacy(kdk_path)
# Go through each line of the pkg receipt and ensure it exists
@@ -339,7 +339,7 @@ class KernelDebugKitObject:
if not line.startswith("System/Library/Extensions"):
continue
if not Path(f"{kdk_path}/{line}").exists():
logging.info(f"- Corrupted KDK found ({kdk_path.name}), removing due to missing file: {line}")
logging.info(f"Corrupted KDK found ({kdk_path.name}), removing due to missing file: {line}")
self._remove_kdk(kdk_path)
return False
@@ -368,7 +368,7 @@ class KernelDebugKitObject:
for kext in KEXT_CATALOG:
if not Path(f"{kdk_path}/System/Library/Extensions/{kext}").exists():
logging.info(f"- Corrupted KDK found, removing due to missing: {kdk_path}/System/Library/Extensions/{kext}")
logging.info(f"Corrupted KDK found, removing due to missing: {kdk_path}/System/Library/Extensions/{kext}")
self._remove_kdk(kdk_path)
return False
@@ -427,15 +427,15 @@ class KernelDebugKitObject:
if not kdk_pkg.name.endswith(f"{match}.pkg"):
continue
logging.info(f"- Found KDK backup: {kdk_pkg.name}")
logging.info(f"Found KDK backup: {kdk_pkg.name}")
if self.passive is False:
logging.info("- Attempting KDK restoration")
logging.info("Attempting KDK restoration")
if KernelDebugKitUtilities().install_kdk_pkg(kdk_pkg):
logging.info("- Successfully restored KDK")
logging.info("Successfully restored KDK")
return self._local_kdk_installed(match=match, check_version=check_version)
else:
# When in passive mode, we're just checking if a KDK could be restored
logging.info("- KDK restoration skipped, running in passive mode")
logging.info("KDK restoration skipped, running in passive mode")
return kdk_pkg
return None
@@ -453,22 +453,22 @@ class KernelDebugKitObject:
return
if os.getuid() != 0:
logging.warning("- Cannot remove KDK, not running as root")
logging.warning("Cannot remove KDK, not running as root")
return
if not Path(kdk_path).exists():
logging.warning(f"- KDK does not exist: {kdk_path}")
logging.warning(f"KDK does not exist: {kdk_path}")
return
rm_args = ["rm", "-rf" if Path(kdk_path).is_dir() else "-f", kdk_path]
result = utilities.elevated(rm_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.warning(f"- Failed to remove KDK: {kdk_path}")
logging.warning(f"- {result.stdout.decode('utf-8')}")
logging.warning(f"Failed to remove KDK: {kdk_path}")
logging.warning(f"{result.stdout.decode('utf-8')}")
return
logging.info(f"- Successfully removed KDK: {kdk_path}")
logging.info(f"Successfully removed KDK: {kdk_path}")
def _remove_unused_kdks(self, exclude_builds: list = None) -> None:
@@ -495,7 +495,7 @@ class KernelDebugKitObject:
if not Path(KDK_INSTALL_PATH).exists():
return
logging.info("- Cleaning unused KDKs")
logging.info("Cleaning unused KDKs")
for kdk_folder in Path(KDK_INSTALL_PATH).iterdir():
if kdk_folder.name.endswith(".kdk") or kdk_folder.name.endswith(".pkg"):
should_remove = True
@@ -532,17 +532,17 @@ class KernelDebugKitObject:
# TODO: should we use the checksum from the API?
result = subprocess.run(["hdiutil", "verify", self.constants.kdk_download_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
logging.info("- Error: Kernel Debug Kit checksum verification failed!")
logging.info(f"- Output: {result.stderr.decode('utf-8')}")
logging.info("Error: Kernel Debug Kit checksum verification failed!")
logging.info(f"Output: {result.stderr.decode('utf-8')}")
msg = "Kernel Debug Kit checksum verification failed, please try again.\n\nIf this continues to fail, ensure you're downloading on a stable network connection (ie. Ethernet)"
logging.info(f"- {msg}")
logging.info(f"{msg}")
self.error_msg = msg
return False
self._remove_unused_kdks()
self.success = True
logging.info("- Kernel Debug Kit checksum verified")
logging.info("Kernel Debug Kit checksum verified")
return True
@@ -568,17 +568,17 @@ class KernelDebugKitUtilities:
"""
if os.getuid() != 0:
logging.warning("- Cannot install KDK, not running as root")
logging.warning("Cannot install KDK, not running as root")
return False
logging.info(f"- Installing KDK package: {kdk_path.name}")
logging.info(f" - This may take a while...")
logging.info(f"Installing KDK package: {kdk_path.name}")
logging.info(f"- This may take a while...")
# TODO: Check whether enough disk space is available
result = utilities.elevated(["installer", "-pkg", kdk_path, "-target", "/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to install KDK:")
logging.info("Failed to install KDK:")
logging.info(result.stdout.decode('utf-8'))
if result.stderr:
logging.info(result.stderr.decode('utf-8'))
@@ -599,21 +599,21 @@ class KernelDebugKitUtilities:
"""
if os.getuid() != 0:
logging.warning("- Cannot install KDK, not running as root")
logging.warning("Cannot install KDK, not running as root")
return False
logging.info(f"- Extracting downloaded KDK disk image")
logging.info(f"Extracting downloaded KDK disk image")
with tempfile.TemporaryDirectory() as mount_point:
result = subprocess.run(["hdiutil", "attach", kdk_path, "-mountpoint", mount_point, "-nobrowse"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to mount KDK:")
logging.info("Failed to mount KDK:")
logging.info(result.stdout.decode('utf-8'))
return False
kdk_pkg_path = Path(f"{mount_point}/KernelDebugKit.pkg")
if not kdk_pkg_path.exists():
logging.warning("- Failed to find KDK package in DMG, likely corrupted!!!")
logging.warning("Failed to find KDK package in DMG, likely corrupted!!!")
self._unmount_disk_image(mount_point)
return False
@@ -624,7 +624,7 @@ class KernelDebugKitUtilities:
self._create_backup(kdk_pkg_path, Path(f"{kdk_path.parent}/{KDK_INFO_PLIST}"))
self._unmount_disk_image(mount_point)
logging.info("- Successfully installed KDK")
logging.info("Successfully installed KDK")
return True
def _unmount_disk_image(self, mount_point) -> None:
@@ -647,31 +647,31 @@ class KernelDebugKitUtilities:
"""
if not kdk_path.exists():
logging.warning("- KDK does not exist, cannot create backup")
logging.warning("KDK does not exist, cannot create backup")
return
if not kdk_info_plist.exists():
logging.warning("- KDK Info.plist does not exist, cannot create backup")
logging.warning("KDK Info.plist does not exist, cannot create backup")
return
kdk_info_dict = plistlib.load(kdk_info_plist.open("rb"))
if 'version' not in kdk_info_dict or 'build' not in kdk_info_dict:
logging.warning("- Malformed KDK Info.plist provided, cannot create backup")
logging.warning("Malformed KDK Info.plist provided, cannot create backup")
return
if os.getuid() != 0:
logging.warning("- Cannot create KDK backup, not running as root")
logging.warning("Cannot create KDK backup, not running as root")
return
kdk_dst_name = f"KDK_{kdk_info_dict['version']}_{kdk_info_dict['build']}.pkg"
kdk_dst_path = Path(f"{KDK_INSTALL_PATH}/{kdk_dst_name}")
logging.info(f"- Creating backup: {kdk_dst_name}")
logging.info(f"Creating backup: {kdk_dst_name}")
if kdk_dst_path.exists():
logging.info("- Backup already exists, skipping")
logging.info("Backup already exists, skipping")
return
result = utilities.elevated(["cp", "-R", kdk_path, kdk_dst_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to create KDK backup:")
logging.info("Failed to create KDK backup:")
logging.info(result.stdout.decode('utf-8'))
+60 -14
View File
@@ -1,5 +1,7 @@
import wx
import os
import sys
import time
import logging
import threading
import traceback
@@ -32,22 +34,24 @@ class InitializeLoggingSupport:
"""
def __init__(self, global_constants: constants.Constants) -> None:
self.log_filename: str = "OpenCore-Patcher.log"
self.log_filepath: Path = None
self.constants: constants.Constants = global_constants
self.log_filename: str = f"OpenCore-Patcher-{self.constants.patcher_version}.log"
self.log_filepath: Path = None
self.original_excepthook: sys = sys.excepthook
self.original_thread_excepthook: threading = threading.excepthook
self.max_file_size: int = 1024 * 1024 * 10 # 10 MB
self.file_size_redline: int = 1024 * 1024 * 9 # 9 MB, when to start cleaning log file
self.max_file_size: int = 1024 * 1024 # 1 MB
self.file_size_redline: int = 1024 * 1024 - 1024 * 100 # 900 KB, when to start cleaning log file
self._initialize_logging_path()
self._clean_log_file()
self._attempt_initialize_logging_configuration()
self._start_logging()
self._implement_custom_traceback_handler()
self._fix_file_permission()
self._clean_prior_version_logs()
def _initialize_logging_path(self) -> None:
@@ -61,9 +65,6 @@ class InitializeLoggingSupport:
# Likely in an installer environment, store in /Users/Shared
self.log_filepath = Path("/Users/Shared") / self.log_filename
print("- Initializing logging framework...")
print(f" - Log file: {self.log_filepath}")
def _clean_log_file(self) -> None:
"""
@@ -87,7 +88,33 @@ class InitializeLoggingSupport:
# Rename current log file to backup log file
self.log_filepath.rename(backup_log_filepath)
except Exception as e:
print(f"- Failed to clean log file: {e}")
print(f"Failed to clean log file: {e}")
def _clean_prior_version_logs(self) -> None:
"""
Clean logs from old Patcher versions
If file is more than a week old, assume it's unused and delete it
"""
time_threshold = time.time() - 60 * 60 * 24 * 7
for file in self.log_filepath.parent.glob("OpenCore-Patcher*"):
if not file.is_file():
continue
if not file.name.endswith(".log"):
continue
if file.name == self.log_filename:
continue
if file.stat().st_mtime < time_threshold:
try:
file.unlink()
except Exception as e:
print(f"Failed to clean prior version log file: {e}")
def _fix_file_permission(self) -> None:
@@ -103,9 +130,13 @@ class InitializeLoggingSupport:
result = subprocess.run(["chmod", "777", self.log_filepath], capture_output=True)
if result.returncode != 0:
print(f"- Failed to fix log file permissions")
logging.error(f"Failed to fix log file permissions")
if result.stdout:
logging.error("STDOUT:")
logging.error(result.stdout.decode("utf-8"))
if result.stderr:
print(result.stderr.decode("utf-8"))
logging.error("STDERR:")
logging.error(result.stderr.decode("utf-8"))
def _initialize_logging_configuration(self, log_to_file: bool = True) -> None:
@@ -122,7 +153,7 @@ class InitializeLoggingSupport:
logging.basicConfig(
level=logging.NOTSET,
format="%(asctime)s - %(filename)s (%(lineno)d): %(message)s",
format="[%(asctime)s] [%(filename)-32s] [%(lineno)-4d]: %(message)s",
handlers=[
logging.StreamHandler(stream = sys.stdout),
logging.FileHandler(self.log_filepath) if log_to_file is True else logging.NullHandler()
@@ -143,11 +174,26 @@ class InitializeLoggingSupport:
try:
self._initialize_logging_configuration()
except Exception as e:
print(f"- Failed to initialize logging framework: {e}")
print("- Retrying without logging to file...")
print(f"Failed to initialize logging framework: {e}")
print("Retrying without logging to file...")
self._initialize_logging_configuration(log_to_file=False)
def _start_logging(self):
"""
Start logging, used as easily identifiable start point in logs
"""
str_msg = f"# OpenCore Legacy Patcher ({self.constants.patcher_version}) #"
str_len = len(str_msg)
logging.info('#' * str_len)
logging.info(str_msg)
logging.info('#' * str_len)
logging.info(f"Log file set to: {self.log_filepath}")
def _implement_custom_traceback_handler(self) -> None:
"""
Reroute traceback to logging module
+3 -3
View File
@@ -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\n This may take some time")
try:
applescript.AppleScript(
f'''do shell script "installer -pkg {Path(download_path)}/InstallAssistant.pkg -target /"'''
@@ -62,11 +62,11 @@ class InstallerCreation():
" without altering line endings",
).run()
except Exception as e:
logging.info("- Failed to install InstallAssistant")
logging.info("Failed to install InstallAssistant")
logging.info(f" Error Code: {e}")
return False
logging.info("- InstallAssistant installed")
logging.info("InstallAssistant installed")
return True
+2 -5
View File
@@ -32,8 +32,6 @@ class OpenCoreLegacyPatcher:
logging_handler.InitializeLoggingSupport(self.constants)
logging.info(f"- Loading OpenCore Legacy Patcher v{self.constants.patcher_version}...")
self._generate_base_data()
if utilities.check_cli_args() is None:
@@ -98,18 +96,17 @@ class OpenCoreLegacyPatcher:
if utilities.check_cli_args() is None:
self.constants.cli_mode = False
logging.info(f"- No arguments present, loading {'GUI' if self.constants.wxpython_variant is True else 'TUI'} mode")
return
logging.info("- Detected arguments, switching to CLI mode")
logging.info("Detected arguments, switching to CLI mode")
self.constants.gui_mode = True # Assumes no user interaction is required
ignore_args = ["--auto_patch", "--gui_patch", "--gui_unpatch", "--update_installed"]
if not any(x in sys.argv for x in ignore_args):
self.constants.current_path = Path.cwd()
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
logging.info("- Rerouting payloads location")
self.constants.payload_path = sys._MEIPASS / Path("payloads")
logging.info("Rerouting payloads location")
ignore_args = ignore_args.pop(0)
if not any(x in sys.argv for x in ignore_args):
+17 -17
View File
@@ -204,10 +204,10 @@ class DownloadObject:
"""
self.status = DownloadStatus.DOWNLOADING
logging.info(f"- Starting download: {self.filename}")
logging.info(f"Starting download: {self.filename}")
if spawn_thread:
if self.active_thread:
logging.error("- Download already in progress")
logging.error("Download already in progress")
return
self.should_checksum = verify_checksum
self.active_thread = threading.Thread(target=self._download, args=(display_progress,))
@@ -267,8 +267,8 @@ class DownloadObject:
else:
raise Exception("Content-Length missing from headers")
except Exception as e:
logging.error(f"- Error determining file size {self.url}: {str(e)}")
logging.error("- Assuming file size is 0")
logging.error(f"Error determining file size {self.url}: {str(e)}")
logging.error("Assuming file size is 0")
self.total_file_size = 0.0
@@ -295,17 +295,17 @@ class DownloadObject:
try:
if Path(path).exists():
logging.info(f"- Deleting existing file: {path}")
logging.info(f"Deleting existing file: {path}")
Path(path).unlink()
return True
if not Path(path).parent.exists():
logging.info(f"- Creating directory: {Path(path).parent}")
logging.info(f"Creating directory: {Path(path).parent}")
Path(path).parent.mkdir(parents=True, exist_ok=True)
available_space = utilities.get_free_space(Path(path).parent)
if self.total_file_size > available_space:
msg = f"- Not enough free space to download {self.filename}, need {utilities.human_fmt(self.total_file_size)}, have {utilities.human_fmt(available_space)}"
msg = f"Not enough free space to download {self.filename}, need {utilities.human_fmt(self.total_file_size)}, have {utilities.human_fmt(available_space)}"
logging.error(msg)
raise Exception(msg)
@@ -313,7 +313,7 @@ class DownloadObject:
self.error = True
self.error_msg = str(e)
self.status = DownloadStatus.ERROR
logging.error(f"- Error preparing working directory {path}: {self.error_msg}")
logging.error(f"Error preparing working directory {path}: {self.error_msg}")
return False
return True
@@ -353,21 +353,21 @@ class DownloadObject:
if display_progress and i % 100:
# Don't use logging here, as we'll be spamming the log file
if self.total_file_size == 0.0:
print(f"- Downloaded {utilities.human_fmt(self.downloaded_file_size)} of {self.filename}")
print(f"Downloaded {utilities.human_fmt(self.downloaded_file_size)} of {self.filename}")
else:
print(f"- Downloaded {self.get_percent():.2f}% of {self.filename} ({utilities.human_fmt(self.get_speed())}/s) ({self.get_time_remaining():.2f} seconds remaining)")
print(f"Downloaded {self.get_percent():.2f}% of {self.filename} ({utilities.human_fmt(self.get_speed())}/s) ({self.get_time_remaining():.2f} seconds remaining)")
self.download_complete = True
logging.info(f"- Download complete: {self.filename}")
logging.info("- Stats:")
logging.info(f"- Downloaded size: {utilities.human_fmt(self.downloaded_file_size)}")
logging.info(f"- Time elapsed: {(time.time() - self.start_time):.2f} seconds")
logging.info(f"- Speed: {utilities.human_fmt(self.downloaded_file_size / (time.time() - self.start_time))}/s")
logging.info(f"- Location: {self.filepath}")
logging.info(f"Download complete: {self.filename}")
logging.info("Stats:")
logging.info(f"- Downloaded size: {utilities.human_fmt(self.downloaded_file_size)}")
logging.info(f"- Time elapsed: {(time.time() - self.start_time):.2f} seconds")
logging.info(f"- Speed: {utilities.human_fmt(self.downloaded_file_size / (time.time() - self.start_time))}/s")
logging.info(f"- Location: {self.filepath}")
except Exception as e:
self.error = True
self.error_msg = str(e)
self.status = DownloadStatus.ERROR
logging.error(f"- Error downloading {self.url}: {self.error_msg}")
logging.error(f"Error downloading {self.url}: {self.error_msg}")
self.status = DownloadStatus.COMPLETE
utilities.enable_sleep_after_running()
+7 -7
View File
@@ -28,10 +28,10 @@ class RoutePayloadDiskImage:
"""
if self.constants.wxpython_variant is True and not self.constants.launcher_script:
logging.info("- Running in Binary GUI mode, switching to tmp directory")
logging.info("Running in Binary GUI mode, switching to tmp directory")
self.temp_dir = tempfile.TemporaryDirectory()
logging.info(f"- New payloads location: {self.temp_dir.name}")
logging.info("- Creating payloads directory")
logging.info(f"New payloads location: {self.temp_dir.name}")
logging.info("Creating payloads directory")
Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True)
self._unmount_active_dmgs(unmount_all_active=False)
output = subprocess.run(
@@ -45,12 +45,12 @@ class RoutePayloadDiskImage:
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
if output.returncode == 0:
logging.info("- Mounted payloads.dmg")
logging.info("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, unmount_all_active=False)
else:
logging.info("- Failed to mount payloads.dmg")
logging.info("Failed to mount payloads.dmg")
logging.info(f"Output: {output.stdout.decode()}")
logging.info(f"Return Code: {output.returncode}")
@@ -78,13 +78,13 @@ class RoutePayloadDiskImage:
# Check that only our personal payloads.dmg is unmounted
if "shadow-path" in image:
if self.temp_dir.name in image["shadow-path"]:
logging.info(f"- Unmounting personal {variant}")
logging.info(f"Unmounting personal {variant}")
subprocess.run(
["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
else:
logging.info(f"- Unmounting {variant} at: {image['system-entities'][0]['dev-entry']}")
logging.info(f"Unmounting {variant} at: {image['system-entities'][0]['dev-entry']}")
subprocess.run(
["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
+1 -1
View File
@@ -92,7 +92,7 @@ class DetectRootPatch:
non_metal_os = os_data.os_data.catalina
for i, gpu in enumerate(gpus):
if gpu.class_code and gpu.class_code != 0xFFFFFFFF:
logging.info(f"- Found GPU ({i}): {utilities.friendly_hex(gpu.vendor_id)}:{utilities.friendly_hex(gpu.device_id)}")
logging.info(f"Found GPU ({i}): {utilities.friendly_hex(gpu.vendor_id)}:{utilities.friendly_hex(gpu.device_id)}")
if gpu.arch in [device_probe.NVIDIA.Archs.Tesla] and self.constants.force_nv_web is False:
if self.constants.detected_os > non_metal_os:
self.nvidia_tesla = True
+3 -3
View File
@@ -40,7 +40,7 @@ class GenerateRootPatchSets:
utilities.cls()
logging.info("- The following patches will be applied:")
logging.info("The following patches will be applied:")
if self.hardware_details["Graphics: Intel Ironlake"] is True:
required_patches.update({"Non-Metal Common": all_hardware_patchset["Graphics"]["Non-Metal Common"]})
@@ -184,8 +184,8 @@ class GenerateRootPatchSets:
del(required_patches[patch_name])
else:
if required_patches[patch_name]["Display Name"]:
logging.info(f" - {required_patches[patch_name]['Display Name']}")
logging.info(f"- {required_patches[patch_name]['Display Name']}")
else:
logging.info(" - No patch sets found for booted model")
logging.info("- No patch sets found for booted model")
return required_patches
+11 -11
View File
@@ -42,10 +42,10 @@ class SysPatchHelpers:
if self.constants.computer.reported_board_id in self.constants.sandy_board_id_stock:
return
logging.info(f"- Found unsupported Board ID {self.constants.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching")
logging.info(f"Found unsupported Board ID {self.constants.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching")
board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.constants.computer.reported_board_id, self.constants.computer.gpus)
logging.info(f"- Replacing {board_to_patch} with {self.constants.computer.reported_board_id}")
logging.info(f"Replacing {board_to_patch} with {self.constants.computer.reported_board_id}")
board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex())
reported_board_hex = bytes.fromhex(self.constants.computer.reported_board_id.encode('utf-8').hex())
@@ -54,12 +54,12 @@ class SysPatchHelpers:
# Pad the reported Board ID with zeros to match the length of the board to patch
reported_board_hex = reported_board_hex + bytes(len(board_to_patch_hex) - len(reported_board_hex))
elif len(board_to_patch_hex) < len(reported_board_hex):
logging.info(f"- Error: Board ID {self.constants.computer.reported_board_id} is longer than {board_to_patch}")
logging.info(f"Error: Board ID {self.constants.computer.reported_board_id} is longer than {board_to_patch}")
raise Exception("Host's Board ID is longer than the kext's Board ID, cannot patch!!!")
path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB"
if not Path(path).exists():
logging.info(f"- Error: Could not find {path}")
logging.info(f"Error: Could not find {path}")
raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!")
with open(path, 'rb') as f:
@@ -128,7 +128,7 @@ class SysPatchHelpers:
if self.constants.detected_os < os_data.os_data.ventura:
return
logging.info("- Disabling WindowServer Caching")
logging.info("Disabling WindowServer Caching")
# Invoke via 'bash -c' to resolve pathing
utilities.elevated(["bash", "-c", "rm -rf /private/var/folders/*/*/*/WindowServer/com.apple.WindowServer"])
# Disable writing to WindowServer folder
@@ -150,12 +150,12 @@ class SysPatchHelpers:
if self.constants.detected_os < os_data.os_data.ventura:
return
logging.info("- Parsing Notification Centre Widgets")
logging.info("Parsing Notification Centre Widgets")
file_path = "~/Library/Containers/com.apple.notificationcenterui/Data/Library/Preferences/com.apple.notificationcenterui.plist"
file_path = Path(file_path).expanduser()
if not file_path.exists():
logging.info(" - Defaults file not found, skipping")
logging.info("- Defaults file not found, skipping")
return
did_find = False
@@ -178,7 +178,7 @@ class SysPatchHelpers:
continue
if not b'com.apple.news' in sub_data[sub_entry][2]:
continue
logging.info(f" - Found News Widget to remove: {sub_data[sub_entry][2].decode('ascii')}")
logging.info(f"- Found News Widget to remove: {sub_data[sub_entry][2].decode('ascii')}")
data["widgets"]["instances"].remove(widget)
did_find = True
@@ -210,10 +210,10 @@ class SysPatchHelpers:
if self.constants.detected_os < os_data.os_data.big_sur:
return
logging.info("- Installing Kernel Collection syncing utility")
logging.info("Installing Kernel Collection syncing utility")
result = utilities.elevated([self.constants.rsrrepair_userspace_path, "--install"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info(f" - Failed to install RSRRepair: {result.stdout.decode()}")
logging.info(f"- Failed to install RSRRepair: {result.stdout.decode()}")
def patch_gpu_compiler_libraries(self, mount_point: Union[str, Path]):
@@ -262,7 +262,7 @@ class SysPatchHelpers:
if not file.name.startswith("31001."):
continue
logging.info(f"- Merging GPUCompiler.framework libraries to match binary")
logging.info(f"Merging GPUCompiler.framework libraries to match binary")
src_dir = f"{LIBRARY_DIR}/{file.name}"
if not Path(f"{DEST_DIR}/lib").exists():
+1 -1
View File
@@ -116,7 +116,7 @@ class CheckBinaryUpdates:
return None
for asset in data_set["assets"]:
logging.info(f"- Found asset: {asset['name']}")
logging.info(f"Found asset: {asset['name']}")
if self._determine_remote_type(asset["name"]) == self._determine_local_build_type():
available_binaries.update({
asset['name']: {
+3 -3
View File
@@ -158,7 +158,7 @@ sleep_process = None
def disable_sleep_while_running():
global sleep_process
logging.info("- Disabling Idle Sleep")
logging.info("Disabling Idle Sleep")
if sleep_process is None:
# If sleep_process is active, we'll just keep it running
sleep_process = subprocess.Popen(["caffeinate", "-d", "-i", "-s"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -168,7 +168,7 @@ def disable_sleep_while_running():
def enable_sleep_after_running():
global sleep_process
if sleep_process:
logging.info("- Re-enabling Idle Sleep")
logging.info("Re-enabling Idle Sleep")
sleep_process.kill()
sleep_process = None
@@ -516,7 +516,7 @@ def block_os_updaters():
for bad_process in bad_processes:
if bad_process in current_process:
if pid != "":
logging.info(f"- Killing Process: {pid} - {current_process.split('/')[-1]}")
logging.info(f"Killing Process: {pid} - {current_process.split('/')[-1]}")
subprocess.run(["kill", "-9", pid])
break
+4 -4
View File
@@ -120,7 +120,7 @@ class PatcherValidation:
logging.info(f"File not found: {source_file}")
raise Exception(f"Failed to find {source_file}")
logging.info(f"- Validating against Darwin {major_kernel}.{minor_kernel}")
logging.info(f"Validating against Darwin {major_kernel}.{minor_kernel}")
if not sys_patch_helpers.SysPatchHelpers(self.constants).generate_patchset_plist(patchset, f"OpenCore-Legacy-Patcher-{major_kernel}.{minor_kernel}.plist", None):
raise Exception("Failed to generate patchset plist")
@@ -153,13 +153,13 @@ class PatcherValidation:
)
if output.returncode != 0:
logging.info("- Failed to mount Universal-Binaries.dmg")
logging.info("Failed to mount Universal-Binaries.dmg")
logging.info(f"Output: {output.stdout.decode()}")
logging.info(f"Return Code: {output.returncode}")
raise Exception("Failed to mount Universal-Binaries.dmg")
logging.info("- Mounted Universal-Binaries.dmg")
logging.info("Mounted Universal-Binaries.dmg")
for supported_os in [os_data.os_data.big_sur, os_data.os_data.monterey, os_data.os_data.ventura]:
@@ -179,7 +179,7 @@ class PatcherValidation:
)
if output.returncode != 0:
logging.info("- Failed to unmount Universal-Binaries.dmg")
logging.info("Failed to unmount Universal-Binaries.dmg")
logging.info(f"Output: {output.stdout.decode()}")
logging.info(f"Return Code: {output.returncode}")
+2
View File
@@ -2,6 +2,7 @@
import wx
import wx.adv
import logging
from resources import constants
@@ -12,6 +13,7 @@ class AboutFrame(wx.Frame):
if wx.FindWindowByName("About"):
return
logging.info("Generating About frame")
super(AboutFrame, self).__init__(None, title="About", size=(350, 350), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
self.constants: constants.Constants = global_constants
self.Centre()
+2 -1
View File
@@ -19,6 +19,7 @@ class BuildFrame(wx.Frame):
Uses a Modal Dialog for smoother transition from other frames
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None) -> None:
logging.info("Initializing Build Frame")
super(BuildFrame, self).__init__(parent, title=title, size=(350, 200), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
gui_support.GenerateMenubar(self, global_constants).generate()
@@ -121,7 +122,7 @@ class BuildFrame(wx.Frame):
try:
build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants)
except:
logging.error("- An internal error occurred while building:\n")
logging.error("An internal error occurred while building:\n")
logging.error(traceback.format_exc())
logger.removeHandler(logger.handlers[2])
+3
View File
@@ -1,5 +1,6 @@
# Generate UI for downloading files
import wx
import logging
from resources import (
constants,
@@ -13,6 +14,7 @@ class DownloadFrame(wx.Frame):
Update provided frame with download stats
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, download_obj: network_handler.DownloadObject, item_name: str) -> None:
logging.info("Initializing Download Frame")
self.constants: constants.Constants = global_constants
self.title: str = title
self.parent: wx.Frame = parent
@@ -91,6 +93,7 @@ class DownloadFrame(wx.Frame):
Terminate download
"""
if wx.MessageBox("Are you sure you want to cancel the download?", "Cancel Download", wx.YES_NO | wx.ICON_QUESTION | wx.NO_DEFAULT) == wx.YES:
logging.info("User cancelled download")
self.user_cancelled = True
self.download_obj.stop()
+2 -2
View File
@@ -52,7 +52,7 @@ class EntryPoint:
entry = gui_sys_patch.SysPatchFrame
patches = sys_patch_detect.DetectRootPatch(self.constants.computer.real_model, self.constants).detect_patch_set()
logging.info(f"- Loading wxPython GUI: {entry.__name__}")
logging.info(f"Entry point set: {entry.__name__}")
self.frame: wx.Frame = entry(
None,
title=f"{self.constants.patcher_name} ({self.constants.patcher_version})",
@@ -79,7 +79,7 @@ class EntryPoint:
if not self.frame:
return
logging.info("- Cleaning up wxPython GUI")
logging.info("Cleaning up wxPython GUI")
self.frame.SetTransparent(0)
wx.Yield()
+2 -1
View File
@@ -1,5 +1,6 @@
# Generate UI for help menu
import wx
import logging
import webbrowser
from resources import constants
@@ -10,7 +11,7 @@ class HelpFrame(wx.Frame):
Append to main menu through a modal dialog
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None) -> None:
logging.info("Initializing Help Frame")
self.dialog = wx.Dialog(parent, title=title, size=(300, 200))
self.constants: constants.Constants = global_constants
+6 -3
View File
@@ -13,6 +13,7 @@ class InstallOCFrame(wx.Frame):
Create a frame for installing OpenCore to disk
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None):
logging.info("Initializing Install OpenCore Frame")
super(InstallOCFrame, self).__init__(parent, title=title, size=(300, 120), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
gui_support.GenerateMenubar(self, global_constants).generate()
@@ -124,13 +125,14 @@ class InstallOCFrame(wx.Frame):
# disk6s1 -> disk6
disk_root = self.constants.booted_oc_disk.strip("disk")
disk_root = "disk" + disk_root.split("s")[0]
logging.info(f"- Checking if booted disk is present: {disk_root}")
logging.info(f"Checking if booted disk is present: {disk_root}")
# Add buttons for each disk
items = len(self.available_disks)
longest_label = max((len(self.available_disks[disk]['disk']) + len(self.available_disks[disk]['name']) + len(str(self.available_disks[disk]['size']))) for disk in self.available_disks)
longest_label = longest_label * 9
spacer = 0
logging.info("Available disks:")
for disk in self.available_disks:
# Create a button for each disk
logging.info(f"- {self.available_disks[disk]['disk']} - {self.available_disks[disk]['name']} - {self.available_disks[disk]['size']}")
@@ -195,6 +197,7 @@ class InstallOCFrame(wx.Frame):
items = len(partitions)
longest_label = max((len(partitions[partition]['partition']) + len(partitions[partition]['name']) + len(str(partitions[partition]['size']))) for partition in partitions)
longest_label = longest_label * 10
logging.info(f"Available partitions for {disk}:")
for partition in partitions:
logging.info(f"- {partitions[partition]['partition']} - {partitions[partition]['name']} - {partitions[partition]['size']}")
disk_button = wx.Button(dialog, label=f"{partitions[partition]['partition']} - {partitions[partition]['name']} - {partitions[partition]['size']}", size=(longest_label,30), pos=(-1, text_label.GetPosition()[1] + text_label.GetSize()[1] + 5))
@@ -306,14 +309,14 @@ class InstallOCFrame(wx.Frame):
"""
Install OpenCore to disk
"""
logging.info(f"- Installing OpenCore to {partition}")
logging.info(f"Installing OpenCore to {partition}")
logger = logging.getLogger()
logger.addHandler(gui_support.ThreadHandler(self.text_box))
try:
self.result = install.tui_disk_installation(self.constants).install_opencore(partition)
except:
logging.error("- An internal error occurred while installing:\n")
logging.error("An internal error occurred while installing:\n")
logging.error(traceback.format_exc())
logger.removeHandler(logger.handlers[2])
@@ -28,7 +28,7 @@ class macOSInstallerDownloadFrame(wx.Frame):
Note: Flashing installers is passed to gui_macos_installer_flash.py
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None):
logging.info("Initializing macOS Installer Download Frame")
self.constants: constants.Constants = global_constants
self.title: str = title
self.parent: wx.Frame = parent
+26 -25
View File
@@ -22,6 +22,7 @@ from data import os_data
class macOSInstallerFlashFrame(wx.Frame):
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None):
logging.info("Initializing macOS Installer Flash Frame")
super(macOSInstallerFlashFrame, self).__init__(parent, title=title, size=(350, 200), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
gui_support.GenerateMenubar(self, global_constants).generate()
@@ -354,14 +355,14 @@ class macOSInstallerFlashFrame(wx.Frame):
def _flash_installer(self, disk) -> bool:
utilities.disable_sleep_while_running()
logging.info("- Creating macOS installer")
logging.info("Creating macOS installer")
thread = threading.Thread(target=self._auto_package_handler)
thread.start()
# print contents of installer.sh
with open(self.constants.installer_sh_path, "r") as f:
logging.info(f"- installer.sh contents:\n{f.read()}")
logging.info(f"installer.sh contents:\n{f.read()}")
args = [self.constants.oclp_helper_path, "/bin/sh", self.constants.installer_sh_path]
result = subprocess.run(args, capture_output=True, text=True)
@@ -369,17 +370,17 @@ class macOSInstallerFlashFrame(wx.Frame):
error = result.stderr if result.stderr else ""
if "Install media now available at" not in output:
logging.info("- Failed to create macOS installer")
logging.info("Failed to create macOS installer")
popup = wx.MessageDialog(self, f"Failed to create macOS installer\n\nOutput: {output}\n\nError: {error}", "Error", wx.OK | wx.ICON_ERROR)
popup.ShowModal()
return False
logging.info("- Successfully created macOS installer")
logging.info("Successfully created macOS installer")
while thread.is_alive():
# wait for download_thread to finish
# though highly unlikely this thread is still alive (flashing an Installer will take a while)
time.sleep(0.1)
logging.info("- Installing Root Patcher to drive")
logging.info("Installing Root Patcher to drive")
self._install_installer_pkg(disk)
utilities.enable_sleep_after_running()
@@ -396,7 +397,7 @@ class macOSInstallerFlashFrame(wx.Frame):
"""
link = self.constants.installer_pkg_url
if network_handler.NetworkUtilities(link).validate_link() is False:
logging.info("- Stock Install.pkg is missing on Github, falling back to Nightly")
logging.info("Stock Install.pkg is missing on Github, falling back to Nightly")
link = self.constants.installer_pkg_url_nightly
if link.endswith(".zip"):
@@ -408,7 +409,7 @@ class macOSInstallerFlashFrame(wx.Frame):
autopkg_download.download(spawn_thread=False)
if autopkg_download.download_complete is False:
logging.warning("- Failed to download Install.pkg")
logging.warning("Failed to download Install.pkg")
logging.warning(autopkg_download.error_msg)
return
@@ -434,7 +435,7 @@ class macOSInstallerFlashFrame(wx.Frame):
os_version = plistlib.load(Path(path + "/System/Library/CoreServices/SystemVersion.plist").open("rb"))
kernel_version = os_data.os_conversion.os_to_kernel(os_version["ProductVersion"])
if int(kernel_version) < os_data.os_data.big_sur:
logging.info("- Installer unsupported, requires Big Sur or newer")
logging.info("Installer unsupported, requires Big Sur or newer")
return
subprocess.run(["mkdir", "-p", f"{path}/Library/Packages/"])
@@ -460,29 +461,29 @@ class macOSInstallerFlashFrame(wx.Frame):
if kdk_pkg_path.exists():
kdk_pkg_path.unlink()
logging.info("- Initiating KDK download")
logging.info(f" - Build: {build}")
logging.info(f" - Version: {version}")
logging.info(f" - Working Directory: {download_dir}")
logging.info("Initiating KDK download")
logging.info(f"- Build: {build}")
logging.info(f"- Version: {version}")
logging.info(f"- Working Directory: {download_dir}")
kdk_obj = kdk_handler.KernelDebugKitObject(self.constants, build, version, ignore_installed=True)
if kdk_obj.success is False:
logging.info("- Failed to retrieve KDK")
logging.info("Failed to retrieve KDK")
logging.info(kdk_obj.error_msg)
return
kdk_download_obj = kdk_obj.retrieve_download(override_path=kdk_dmg_path)
if kdk_download_obj is None:
logging.info("- Failed to retrieve KDK")
logging.info("Failed to retrieve KDK")
logging.info(kdk_obj.error_msg)
# Check remaining disk space before downloading
space = utilities.get_free_space(download_dir)
if space < (kdk_obj.kdk_url_expected_size * 2):
logging.info("- Not enough disk space to download and install KDK")
logging.info(f"- Attempting to download locally first")
logging.info("Not enough disk space to download and install KDK")
logging.info(f"Attempting to download locally first")
if space < kdk_obj.kdk_url_expected_size:
logging.info("- Not enough disk space to install KDK, skipping")
logging.info("Not enough disk space to install KDK, skipping")
return
# Ideally we'd download the KDK onto the disk to display progress in the UI
# However we'll just download to our temp directory and move it to the target disk
@@ -490,34 +491,34 @@ class macOSInstallerFlashFrame(wx.Frame):
kdk_download_obj.download(spawn_thread=False)
if kdk_download_obj.download_complete is False:
logging.info("- Failed to download KDK")
logging.info("Failed to download KDK")
logging.info(kdk_download_obj.error_msg)
return
if not kdk_dmg_path.exists():
logging.info(f"- KDK missing: {kdk_dmg_path}")
logging.info(f"KDK missing: {kdk_dmg_path}")
return
# Now that we have a KDK, extract it to get the pkg
with tempfile.TemporaryDirectory() as mount_point:
logging.info("- Mounting KDK")
logging.info("Mounting KDK")
result = subprocess.run(["hdiutil", "attach", kdk_dmg_path, "-mountpoint", mount_point, "-nobrowse"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to mount KDK")
logging.info("Failed to mount KDK")
logging.info(result.stdout.decode("utf-8"))
return
logging.info("- Copying KDK")
logging.info("Copying KDK")
subprocess.run(["cp", "-r", f"{mount_point}/KernelDebugKit.pkg", kdk_pkg_path])
logging.info("- Unmounting KDK")
logging.info("Unmounting KDK")
result = subprocess.run(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to unmount KDK")
logging.info("Failed to unmount KDK")
logging.info(result.stdout.decode("utf-8"))
return
logging.info("- Removing KDK Disk Image")
logging.info("Removing KDK Disk Image")
kdk_dmg_path.unlink()
def _validate_installer_pkg(self, disk: str) -> bool:
+3 -2
View File
@@ -24,6 +24,7 @@ from data import os_data
class MainFrame(wx.Frame):
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None):
logging.info("Initializing Main Menu Frame")
super(MainFrame, self).__init__(parent, title=title, size=(600, 400), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
gui_support.GenerateMenubar(self, global_constants).generate()
@@ -213,11 +214,11 @@ class MainFrame(wx.Frame):
pop_up.ShowModal()
if pop_up.GetReturnCode() != wx.ID_YES:
print("- Skipping OpenCore and root volume patch update...")
print("Skipping OpenCore and root volume patch update...")
return
print("- Updating OpenCore and root volume patches...")
print("Updating OpenCore and root volume patches...")
self.constants.update_stage = gui_support.AutoUpdateStages.CHECKING
self.Hide()
pos = self.GetPosition()
+3 -1
View File
@@ -32,6 +32,7 @@ class SettingsFrame(wx.Frame):
Modal-based Settings Frame
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None):
logging.info("Initializing Settings Frame")
self.constants: constants.Constants = global_constants
self.title: str = title
self.parent: wx.Frame = parent
@@ -1257,11 +1258,12 @@ Hardware Information:
def on_export_constants(self, event: wx.Event) -> None:
# Throw pop up to get save location
with wx.FileDialog(self.parent, "Save Constants File", wildcard="JSON files (*.txt)|*.txt", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:
with wx.FileDialog(self.parent, "Save Constants File", wildcard="JSON files (*.txt)|*.txt", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, defaultFile=f"constants-{self.constants.patcher_version}.txt") as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return
# Save the current contents in the file
pathname = fileDialog.GetPath()
logging.info(f"Saving constants to {pathname}")
with open(pathname, 'w') as file:
file.write(pprint.pformat(vars(self.constants), indent=4))
+1 -1
View File
@@ -289,7 +289,7 @@ class RelaunchApplicationAsRoot:
wx.Yield()
logging.info(f"- Relaunching as root with command: {program_arguments}")
logging.info(f"Relaunching as root with command: {program_arguments}")
subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
+11 -6
View File
@@ -33,6 +33,7 @@ class SysPatchFrame(wx.Frame):
Uses a Modal Dialog for smoother transition from other frames
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None, patches: dict = {}):
logging.info("Initializing Root Patching Frame")
self.frame = parent
self.initiated_with_parent = False
if not self.frame and patches == {}:
@@ -167,7 +168,7 @@ class SysPatchFrame(wx.Frame):
can_unpatch: bool = patches["Validation: Unpatching Possible"]
if not any(not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True for patch in patches):
logging.info("- No applicable patches available")
logging.info("No applicable patches available")
patches = []
# Check if OCLP has already applied the same patches
@@ -198,10 +199,11 @@ class SysPatchFrame(wx.Frame):
anchor.Centre(wx.HORIZONTAL)
anchor.Hide()
logging.info("Available patches:")
for patch in patches:
if (not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True):
i = i + 20
logging.info(f"- Adding patch: {patch} - {patches[patch]}")
logging.info(f"- {patch}")
patch_label = wx.StaticText(frame, label=f"- {patch}", pos=(anchor.GetPosition()[0], available_label.GetPosition()[1] + i))
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
@@ -346,9 +348,10 @@ class SysPatchFrame(wx.Frame):
# Labels
i = 0
logging.info("Available patches:")
for patch in patches:
if (not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True):
logging.info(f"- Adding patch: {patch} - {patches[patch]}")
logging.info(f"- {patch}")
patch_label = wx.StaticText(dialog, label=f"- {patch}", pos=(anchor.GetPosition()[0], label.GetPosition()[1] + 20 + i))
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
i = i + 20
@@ -422,7 +425,7 @@ class SysPatchFrame(wx.Frame):
try:
sys_patch.PatchSysVolume(self.constants.computer.real_model, self.constants, patches).start_patch()
except:
logging.error("- An internal error occurred while running the Root Patcher:\n")
logging.error("An internal error occurred while running the Root Patcher:\n")
logging.error(traceback.format_exc())
logger.removeHandler(logger.handlers[2])
@@ -454,7 +457,7 @@ class SysPatchFrame(wx.Frame):
try:
sys_patch.PatchSysVolume(self.constants.computer.real_model, self.constants, patches).start_unpatch()
except:
logging.error("- An internal error occurred while running the Root Patcher:\n")
logging.error("An internal error occurred while running the Root Patcher:\n")
logging.error(traceback.format_exc())
logger.removeHandler(logger.handlers[2])
@@ -525,6 +528,8 @@ class SysPatchFrame(wx.Frame):
Thus we'll need to see if the exact same OCLP build was used already
"""
logging.info("Checking if new patches are needed")
if self.constants.commit_info[0] in ["Running from source", "Built from source"]:
return True
@@ -557,5 +562,5 @@ class SysPatchFrame(wx.Frame):
logging.info(f"- Patch {patch} not installed")
return True
logging.info("- No new patches detected for system")
logging.info("No new patches detected for system")
return False
+8
View File
@@ -22,6 +22,7 @@ class UpdateFrame(wx.Frame):
Create a frame for updating the patcher
"""
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: wx.Point, url: str = "", version_label: str = "") -> None:
logging.info("Initializing Update Frame")
if parent:
self.parent: wx.Frame = parent
@@ -55,6 +56,9 @@ class UpdateFrame(wx.Frame):
self.version_label = version_label
self.url = url
logging.info(f"Update URL: {url}")
logging.info(f"Update Version: {version_label}")
self.frame: wx.Frame = wx.Frame(
parent=parent if parent else self,
title=self.title,
@@ -180,6 +184,7 @@ class UpdateFrame(wx.Frame):
["ditto", "-xk", str(self.constants.payload_path / "OpenCore-Patcher-GUI.app.zip"), str(self.constants.payload_path)], capture_output=True
)
if result.returncode != 0:
logging.error(f"Failed to extract update. Error: {result.stderr.decode('utf-8')}")
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
wx.CallAfter(wx.MessageBox, f"Failed to extract update. Error: {result.stderr.decode('utf-8')}", "Critical Error!", wx.OK | wx.ICON_ERROR)
@@ -190,6 +195,7 @@ class UpdateFrame(wx.Frame):
break
if i == 1:
logging.error("Failed to extract update. Error: Update file does not exist")
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
wx.CallAfter(wx.MessageBox, "Failed to extract update. Error: Update file does not exist", "Critical Error!", wx.OK | wx.ICON_ERROR)
@@ -251,8 +257,10 @@ EOF
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
if "User cancelled" in result.stderr.decode("utf-8"):
logging.info("User cancelled update")
wx.CallAfter(wx.MessageBox, "User cancelled update", "Update Cancelled", wx.OK | wx.ICON_INFORMATION)
else:
logging.critical(f"Failed to install update. Error: {result.stderr.decode('utf-8')}")
wx.CallAfter(wx.MessageBox, f"Failed to install update. Error: {result.stderr.decode('utf-8')}", "Critical Error!", wx.OK | wx.ICON_ERROR)
wx.CallAfter(sys.exit, 1)