Skip to content

Commit

Permalink
updates.py: Add support for PKG updates
Browse files Browse the repository at this point in the history
  • Loading branch information
khronokernel committed May 27, 2024
1 parent acbeef0 commit b0def27
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 111 deletions.
2 changes: 1 addition & 1 deletion SOURCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

OpenCore Legacy Patcher at its core is a Python-based GUI/CLI-based application. In turn, to run the project from source, you simply need to invoke the OpenCore-Patcher-GUI.command file via Python.

For developers wishing to validate mainline changes, you may use this link: [GUI (Graphical Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/main/OpenCore-Patcher.app%20%28GUI%29.zip)
For developers wishing to validate mainline changes, you may use this link: [GUI (Graphical Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/main/OpenCore-Patcher.pkg.zip)

* **Warning**: Nightly builds (untagged builds built from the latest commit) are actively developed OpenCore Legacy Patcher builds. These builds have not been tested, are not guaranteed to work, and are not guaranteed to be safe. Do not use nightlies without a good reason to do so, and do not use them on your main machine. Additionally, these binaries should not be used without first consulting the [CHANGELOG](./CHANGELOG.md).

Expand Down
30 changes: 1 addition & 29 deletions opencore_legacy_patcher/support/updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,33 +78,6 @@ def _check_if_build_newer(self, first_version: Union[str, version.Version], seco

return first_version > second_version

def _determine_local_build_type(self) -> str:
"""
Check if the local build is a GUI or TUI build
Returns:
str: "GUI" or "TUI"
"""

return "GUI" if self.constants.wxpython_variant else "TUI"

def _determine_remote_type(self, remote_name: str) -> str:
"""
Check if the remote build is a GUI or TUI build
Parameters:
remote_name (str): Name of the remote build
Returns:
str: "GUI" or "TUI"
"""

if "TUI" in remote_name:
return "TUI"
elif "GUI" in remote_name:
return "GUI"
else:
return "Unknown"

def check_binary_updates(self) -> Optional[dict]:
"""
Expand Down Expand Up @@ -143,12 +116,11 @@ def check_binary_updates(self) -> Optional[dict]:

for asset in data_set["assets"]:
logging.info(f"Found asset: {asset['name']}")
if self._determine_remote_type(asset["name"]) == self._determine_local_build_type():
if asset["name"] == "OpenCore-Patcher.pkg":
self.latest_details = {
"Name": asset["name"],
"Version": latest_remote_version,
"Link": asset["browser_download_url"],
"Type": self._determine_remote_type(asset["name"]),
"Github Link": f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{latest_remote_version}",
}
return self.latest_details
Expand Down
2 changes: 1 addition & 1 deletion opencore_legacy_patcher/wx_gui/gui_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,7 @@ def on_nightly(self, event: wx.Event) -> None:
title=self.title,
global_constants=self.constants,
screen_location=self.parent.GetPosition(),
url=f"https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/{branch}/OpenCore-Patcher.app%20%28GUI%29.zip",
url=f"https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/{branch}/OpenCore-Patcher.pkg.zip",
version_label="(Nightly)"
)

Expand Down
113 changes: 33 additions & 80 deletions opencore_legacy_patcher/wx_gui/gui_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Con

self.title: str = title
self.constants: constants.Constants = global_constants
self.application_path = self.constants.payload_path / "OpenCore-Patcher.app"
self.pkg_download_path = self.constants.payload_path / "OpenCore-Patcher.pkg"
self.screen_location: wx.Point = screen_location
if parent:
self.parent.Centre()
Expand Down Expand Up @@ -98,7 +98,8 @@ def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Con
download_obj = None
def _fetch_update() -> None:
nonlocal download_obj
download_obj = network_handler.DownloadObject(url, self.constants.payload_path / "OpenCore-Patcher-GUI.app.zip")
file_name = "OpenCore-Patcher.pkg.zip" if url.endswith(".zip") else "OpenCore-Patcher.pkg"
download_obj = network_handler.DownloadObject(url, self.constants.payload_path / file_name)

thread = threading.Thread(target=_fetch_update)
thread.start()
Expand Down Expand Up @@ -189,90 +190,37 @@ def _fetch_update() -> None:
def _extract_update(self) -> None:
"""
Extracts the update
Logic:
- Distributed through GitHub Actions: Requires extraction
- Distributed through GitHub Releases: No extraction required
"""
logging.info("Extracting update")
if Path(self.application_path).exists():
subprocess.run(["/bin/rm", "-rf", str(self.application_path)])

# Some hell spawn at Github decided to double zip our Github Actions artifacts
# So we need to unzip it twice
for i in range(2):
result = subprocess.run(
["/usr/bin/ditto", "-xk", str(self.constants.payload_path / "OpenCore-Patcher-GUI.app.zip"), str(self.constants.payload_path)], capture_output=True
)
if result.returncode != 0:
logging.error(f"Failed to extract update.")
subprocess_wrapper.log(result)
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
wx.CallAfter(wx.MessageBox, f"Failed to extract update. Error: {result.stderr.decode('utf-8')}", "Critical Error!", wx.OK | wx.ICON_ERROR)
wx.CallAfter(sys.exit, 1)
break
# GitHub Release
if not self.url.endswith(".zip"):
return

if Path(self.application_path).exists():
break
logging.info("Extracting nightly update")
if Path(self.pkg_download_path).exists():
subprocess.run(["/bin/rm", "-rf", str(self.pkg_download_path)])

if i == 1:
logging.error("Failed to extract update. Error: Update file does not exist")
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
wx.CallAfter(wx.MessageBox, "Failed to extract update. Error: Update file does not exist", "Critical Error!", wx.OK | wx.ICON_ERROR)
wx.CallAfter(sys.exit, 1)
break
result = subprocess.run(
["/usr/bin/ditto", "-xk", str(self.constants.payload_path / "OpenCore-Patcher.pkg.zip"), str(self.constants.payload_path)], capture_output=True
)
if result.returncode != 0:
logging.error(f"Failed to extract update.")
subprocess_wrapper.log(result)
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
wx.CallAfter(wx.MessageBox, f"Failed to extract update. Error: {result.stderr.decode('utf-8')}", "Critical Error!", wx.OK | wx.ICON_ERROR)
wx.CallAfter(sys.exit, 1)


def _install_update(self) -> None:
"""
Installs update to '/Library/Application Support/Dortania/OpenCore-Patcher.app'
Install PKG
"""
logging.info(f"Installing update: {self.application_path}")

# Create bash script to run as root
script = f"""#!/bin/bash
# Check if '/Library/Application Support/Dortania' exists
if [ ! -d "/Library/Application Support/Dortania" ]; then
mkdir -p "/Library/Application Support/Dortania"
fi
# Check if 'OpenCore-Patcher.app' exists
if [ -d "/Library/Application Support/Dortania/OpenCore-Patcher.app" ]; then
rm -rf "/Library/Application Support/Dortania/OpenCore-Patcher.app"
fi
if [ -d "/Applications/OpenCore-Patcher.app" ]; then
rm -rf "/Applications/OpenCore-Patcher.app"
fi
# Move '/tmp/OpenCore-Patcher.app' to '/Library/Application Support/Dortania'
mv "{str(self.application_path)}" "/Library/Application Support/Dortania/OpenCore-Patcher.app"
# Check if '/Applications/OpenCore-Patcher.app' exists
ln -s "/Library/Application Support/Dortania/OpenCore-Patcher.app" "/Applications/OpenCore-Patcher.app"
# Create update.plist with info about update
cat << EOF > "/Library/Application Support/Dortania/update.plist"
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>{self.version_label}</string>
<key>CFBundleVersion</key>
<string>{self.version_label}</string>
<key>InstallationDate</key>
<date>{datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")}</date>
<key>InstallationSource</key>
<string>{self.url}</string>
</dict>
</plist>
EOF
"""
# Write script to file
with open(self.constants.payload_path / "update.sh", "w") as f:
f.write(script)

# Execute script
args = [self.constants.oclp_helper_path, "/bin/sh", str(self.constants.payload_path / "update.sh")]
result = subprocess.run(args, capture_output=True)
logging.info(f"Installing update: {self.pkg_download_path}")
result = subprocess_wrapper.run_as_root(["/usr/sbin/installer", "-pkg", str(self.pkg_download_path), "-target", "/"], capture_output=True)
if result.returncode != 0:
wx.CallAfter(self.progress_bar_animation.stop_pulse)
wx.CallAfter(self.progress_bar.SetValue, 0)
Expand All @@ -282,7 +230,12 @@ def _install_update(self) -> None:
else:
logging.critical("Failed to install update.")
subprocess_wrapper.log(result)
wx.CallAfter(wx.MessageBox, f"Failed to install update. Error: {result.stderr.decode('utf-8')}", "Critical Error!", wx.OK | wx.ICON_ERROR)

# If it fails, fall back to opening the PKG
logging.error("Failed to install update, attempting to open PKG")
subprocess.run(["/usr/bin/open", str(self.pkg_download_path)])

wx.CallAfter(wx.MessageBox, f"Failed to install update. Please try installing the OpenCore-Patcher.pkg manually or download from GitHub", "Critical Error!", wx.OK | wx.ICON_ERROR)
wx.CallAfter(sys.exit, 1)


Expand All @@ -291,4 +244,4 @@ def _launch_update(self) -> None:
Launches newly installed update
"""
logging.info("Launching update: '/Library/Application Support/Dortania/OpenCore-Patcher.app'")
subprocess.Popen(["/Library/Application Support/Dortania/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher", "--update_installed"])
subprocess.run(["/usr/bin/open", "/Library/Application Support/Dortania/OpenCore-Patcher.app", "--args", "--update_installed"])

0 comments on commit b0def27

Please sign in to comment.