mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-11 16:27:19 +10:00
177 lines
5.7 KiB
Python
177 lines
5.7 KiB
Python
import sys
|
|
import time
|
|
import plistlib
|
|
import subprocess
|
|
|
|
from pathlib import Path
|
|
|
|
from opencore_legacy_patcher import constants
|
|
from opencore_legacy_patcher.support import subprocess_wrapper
|
|
|
|
|
|
class GenerateApplication:
|
|
"""
|
|
Generate OpenCore-Patcher.app
|
|
"""
|
|
|
|
def __init__(self, reset_pyinstaller_cache: bool = False, git_branch: str = None, git_commit_url: str = None, git_commit_date: str = None, analytics_key: str = None, analytics_endpoint: str = None) -> None:
|
|
"""
|
|
Initialize
|
|
"""
|
|
self._pyinstaller = [sys.executable, "-m", "PyInstaller"]
|
|
self._application_output = Path("./dist/OpenCore-Patcher.app")
|
|
|
|
self._reset_pyinstaller_cache = reset_pyinstaller_cache
|
|
|
|
self._git_branch = git_branch
|
|
self._git_commit_url = git_commit_url
|
|
self._git_commit_date = git_commit_date
|
|
|
|
self._analytics_key = analytics_key
|
|
self._analytics_endpoint = analytics_endpoint
|
|
|
|
|
|
def _generate_application(self) -> None:
|
|
"""
|
|
Generate PyInstaller Application
|
|
"""
|
|
if self._application_output.exists():
|
|
subprocess_wrapper.run_and_verify(["/bin/rm", "-rf", self._application_output], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
print("Generating OpenCore-Patcher.app")
|
|
_args = self._pyinstaller + ["./OpenCore-Patcher-GUI.spec", "--noconfirm"]
|
|
if self._reset_pyinstaller_cache:
|
|
_args.append("--clean")
|
|
|
|
subprocess_wrapper.run_and_verify(_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
|
|
def _embed_analytics_key(self) -> None:
|
|
"""
|
|
Embed analytics key
|
|
"""
|
|
_file = Path("./opencore_legacy_patcher/support/analytics_handler.py")
|
|
|
|
if not all([self._analytics_key, self._analytics_endpoint]):
|
|
print("Analytics key or endpoint not provided, skipping embedding")
|
|
return
|
|
|
|
print("Embedding analytics data")
|
|
if not Path(_file).exists():
|
|
raise FileNotFoundError("analytics_handler.py not found")
|
|
|
|
lines = []
|
|
with open(_file, "r") as f:
|
|
lines = f.readlines()
|
|
|
|
for i, line in enumerate(lines):
|
|
if line.startswith("SITE_KEY: str = "):
|
|
lines[i] = f"SITE_KEY: str = \"{self._analytics_key}\"\n"
|
|
elif line.startswith("ANALYTICS_SERVER: str = "):
|
|
lines[i] = f"ANALYTICS_SERVER: str = \"{self._analytics_endpoint}\"\n"
|
|
|
|
with open(_file, "w") as f:
|
|
f.writelines(lines)
|
|
|
|
|
|
def _remove_analytics_key(self) -> None:
|
|
"""
|
|
Remove analytics key
|
|
"""
|
|
_file = Path("./opencore_legacy_patcher/support/analytics_handler.py")
|
|
|
|
if not all([self._analytics_key, self._analytics_endpoint]):
|
|
return
|
|
|
|
print("Removing analytics data")
|
|
if not _file.exists():
|
|
raise FileNotFoundError("analytics_handler.py not found")
|
|
|
|
lines = []
|
|
with open(_file, "r") as f:
|
|
lines = f.readlines()
|
|
|
|
for i, line in enumerate(lines):
|
|
if line.startswith("SITE_KEY: str = "):
|
|
lines[i] = "SITE_KEY: str = \"\"\n"
|
|
elif line.startswith("ANALYTICS_SERVER: str = "):
|
|
lines[i] = "ANALYTICS_SERVER: str = \"\"\n"
|
|
|
|
with open(_file, "w") as f:
|
|
f.writelines(lines)
|
|
|
|
|
|
def _patch_load_command(self):
|
|
"""
|
|
Patch LC_VERSION_MIN_MACOSX in Load Command to report 10.10
|
|
|
|
By default Pyinstaller will create binaries supporting 10.13+
|
|
However this limitation is entirely arbitrary for our libraries
|
|
and instead we're able to support 10.10 without issues.
|
|
|
|
To verify set version:
|
|
otool -l ./dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher
|
|
|
|
cmd LC_VERSION_MIN_MACOSX
|
|
cmdsize 16
|
|
version 10.13
|
|
sdk 10.9
|
|
"""
|
|
_file = self._application_output / "Contents" / "MacOS" / "OpenCore-Patcher"
|
|
|
|
_find = b'\x00\x0D\x0A\x00' # 10.13 (0xA0D)
|
|
_replace = b'\x00\x0A\x0A\x00' # 10.10 (0xA0A)
|
|
|
|
print("Patching LC_VERSION_MIN_MACOSX")
|
|
with open(_file, "rb") as f:
|
|
data = f.read()
|
|
data = data.replace(_find, _replace, 1)
|
|
|
|
with open(_file, "wb") as f:
|
|
f.write(data)
|
|
|
|
|
|
def _embed_git_data(self) -> None:
|
|
"""
|
|
Embed git data
|
|
"""
|
|
_file = self._application_output / "Contents" / "Info.plist"
|
|
|
|
_git_branch = self._git_branch or "Built from source"
|
|
_git_commit = self._git_commit_url or ""
|
|
_git_commit_date = self._git_commit_date or time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
|
|
|
print("Embedding git data")
|
|
_plist = plistlib.load(_file.open("rb"))
|
|
_plist["Github"] = {
|
|
"Branch": _git_branch,
|
|
"Commit URL": _git_commit,
|
|
"Commit Date": _git_commit_date
|
|
}
|
|
plistlib.dump(_plist, _file.open("wb"), sort_keys=True)
|
|
|
|
|
|
def _embed_resources(self) -> None:
|
|
"""
|
|
Embed resources
|
|
"""
|
|
print("Embedding resources")
|
|
for file in Path("payloads/Icon/AppIcons").glob("*.icns"):
|
|
subprocess_wrapper.run_and_verify(
|
|
["/bin/cp", str(file), self._application_output / "Contents" / "Resources/"],
|
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
)
|
|
|
|
|
|
def generate(self) -> None:
|
|
"""
|
|
Generate OpenCore-Patcher.app
|
|
"""
|
|
self._embed_analytics_key()
|
|
self._generate_application()
|
|
self._remove_analytics_key()
|
|
|
|
self._patch_load_command()
|
|
self._embed_git_data()
|
|
self._embed_resources()
|