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