installer.py: Parse SharedSupport.dmg

This commit is contained in:
Mykola Grymalyuk
2022-08-24 12:19:52 -06:00
parent 14528b904c
commit c1ba7cd6cb
3 changed files with 88 additions and 4 deletions

View File

@@ -6,6 +6,8 @@
- Verify host's disk space before downloading macOS Installers
- Remove duplicate OS builds in macOS downloader
- Avoids Apple's odd bug of publishing 2 different 12.5.1 products
- Implement deeper macOS installer parsing
- Provides better version detection than Apple provides in .app
## 0.4.10
- Resolve Nvidia Kepler support in macOS 12.5 Beta 3 and newer

View File

@@ -1678,7 +1678,7 @@ class wx_python_gui:
self.header.SetFont(wx.Font(18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
self.header.Centre(wx.HORIZONTAL)
# Subheader: Installers found in /Applications
self.subheader = wx.StaticText(self.frame, label="Installers found in Applications folder")
self.subheader = wx.StaticText(self.frame, label="Searching for Installers in /Applications")
self.subheader.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
self.subheader.SetPosition(
wx.Point(
@@ -1688,12 +1688,46 @@ class wx_python_gui:
)
self.subheader.Centre(wx.HORIZONTAL)
self.available_installers = None
# Spawn thread to get list of installers
def get_installers():
self.available_installers = installer.list_local_macOS_installers()
thread_get_installers = threading.Thread(target=get_installers)
thread_get_installers.start()
# Progress bar
self.progress_bar = wx.Gauge(self.frame, range=100, size=(self.WINDOW_WIDTH_MAIN - 50, -1))
self.progress_bar.SetPosition(
wx.Point(
self.header.GetPosition().x,
self.subheader.GetPosition().y + self.subheader.GetSize().height + 10
)
)
self.progress_bar.Centre(wx.HORIZONTAL)
self.progress_bar.Pulse()
# Set window size
self.frame.SetSize(-1, self.progress_bar.GetPosition().y + self.progress_bar.GetSize().height + 40)
while thread_get_installers.is_alive():
self.pulse_alternative(self.progress_bar)
wx.App.Get().Yield()
# Remove progress bar
self.progress_bar.Destroy()
self.subheader.SetLabel("Installers found in Applications folder")
self.subheader.Centre(wx.HORIZONTAL)
available_installers = self.available_installers
i = -7
available_installers = installer.list_local_macOS_installers()
if available_installers:
print("Installer found")
print("Installer(s) found:")
for app in available_installers:
print(f"{available_installers[app]['Short Name']}: {available_installers[app]['Version']} ({available_installers[app]['Build']})")
print(f"- {available_installers[app]['Short Name']}: {available_installers[app]['Version']} ({available_installers[app]['Build']})")
self.install_selection = wx.Button(self.frame, label=f"{available_installers[app]['Short Name']}: {available_installers[app]['Version']} ({available_installers[app]['Build']})", size=(320, 30))
i = i + 25
self.install_selection.SetPosition(

View File

@@ -47,6 +47,14 @@ def list_local_macOS_installers():
can_add = False
else:
can_add = True
# Check SharedSupport.dmg's data
results = parse_sharedsupport_version(Path("/Applications") / Path(application)/ Path("Contents/SharedSupport/SharedSupport.dmg"))
if results[0] is not None:
app_sdk = results[0]
if results[1] is not None:
app_version = results[1]
if can_add is True:
application_list.update({
application: {
@@ -64,6 +72,46 @@ def list_local_macOS_installers():
application_list = {k: v for k, v in sorted(application_list.items(), key=lambda item: item[1]["Version"])}
return application_list
def parse_sharedsupport_version(sharedsupport_path):
detected_build = None
detected_os = None
sharedsupport_path = Path(sharedsupport_path)
if not sharedsupport_path.exists():
return (detected_build, detected_os)
if not sharedsupport_path.name.endswith(".dmg"):
return (detected_build, detected_os)
# Create temporary directory to extract SharedSupport.dmg to
with tempfile.TemporaryDirectory() as tmpdir:
output = subprocess.run(
[
"hdiutil", "attach", "-noverify", sharedsupport_path,
"-mountpoint", tmpdir,
"-nobrowse",
],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
if output.returncode != 0:
return (detected_build, detected_os)
ss_info = Path("SFR/com_apple_MobileAsset_SFRSoftwareUpdate/com_apple_MobileAsset_SFRSoftwareUpdate.xml")
if Path(tmpdir / ss_info).exists():
plist = plistlib.load((tmpdir / ss_info).open("rb"))
if "Build" in plist["Assets"][0]:
detected_build = plist["Assets"][0]["Build"]
if "OSVersion" in plist["Assets"][0]:
detected_os = plist["Assets"][0]["OSVersion"]
# Unmount SharedSupport.dmg
output = subprocess.run(["hdiutil", "detach", tmpdir], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
return (detected_build, detected_os)
def create_installer(installer_path, volume_name):
# Creates a macOS installer
# Takes a path to the installer and the Volume