From 95966d65c036cb2cfaff25174f421615c4d0e339 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Wed, 24 May 2023 15:38:16 +1000 Subject: [PATCH] Add support for 10.7-10.12 installers --- Mist/Helpers/InstallerCreator.swift | 21 +++-- Mist/Helpers/TaskManager.swift | 32 ++++++-- Mist/Model/Installer.swift | 118 ++++++++++++++++++++++++++- Mist/Views/Refresh/RefreshView.swift | 1 + 4 files changed, 161 insertions(+), 11 deletions(-) diff --git a/Mist/Helpers/InstallerCreator.swift b/Mist/Helpers/InstallerCreator.swift index 7bf48d0..263f6ba 100644 --- a/Mist/Helpers/InstallerCreator.swift +++ b/Mist/Helpers/InstallerCreator.swift @@ -21,16 +21,27 @@ struct InstallerCreator { /// - Throws: A `MistError` if the downloaded macOS Installer fails to generate. static func create(_ installer: Installer, mountPoint: URL, cacheDirectory: String) async throws { - guard let url: URL = URL(string: installer.distributionURL) else { - throw MistError.invalidURL(installer.distributionURL) + let packageURL: URL + + if installer.sierraOrOlder { + + guard let package: Package = installer.packages.first else { + throw MistError.invalidData + } + + packageURL = URL(fileURLWithPath: "/Volumes/Install \(installer.name)").appendingPathComponent(package.filename.replacingOccurrences(of: ".dmg", with: ".pkg")) + } else { + guard let url: URL = URL(string: installer.distributionURL) else { + throw MistError.invalidURL(installer.distributionURL) + } + + packageURL = URL(fileURLWithPath: cacheDirectory).appendingPathComponent(installer.id).appendingPathComponent(url.lastPathComponent) } try await DirectoryRemover.remove(installer.temporaryInstallerURL) - let cacheDirectoryURL: URL = URL(fileURLWithPath: cacheDirectory) - let distributionURL: URL = cacheDirectoryURL.appendingPathComponent(installer.id).appendingPathComponent(url.lastPathComponent) var argumentsArrays: [[String]] = [ - ["installer", "-pkg", distributionURL.path, "-target", mountPoint.path] + ["installer", "-pkg", packageURL.path, "-target", mountPoint.path] ] if installer.catalinaOrNewer { diff --git a/Mist/Helpers/TaskManager.swift b/Mist/Helpers/TaskManager.swift index 12e4c79..eed24e1 100644 --- a/Mist/Helpers/TaskManager.swift +++ b/Mist/Helpers/TaskManager.swift @@ -280,8 +280,7 @@ class TaskManager: ObservableObject { private static func installTasks(for installer: Installer, temporaryDirectory temporaryDirectoryURL: URL, mountPoint mountPointURL: URL, cacheDirectory: String) -> [MistTask] { let imageURL: URL = temporaryDirectoryURL.appendingPathComponent("\(installer.id) Temp.dmg") - - return [ + var tasks: [MistTask] = [ MistTask(type: .configure, description: "temporary directory") { try await DirectoryCreator.create(temporaryDirectoryURL) }, @@ -290,11 +289,34 @@ class TaskManager: ObservableObject { }, MistTask(type: .mount, description: "Disk Image") { try await DiskImageMounter.mount(imageURL, mountPoint: mountPointURL) - }, - MistTask(type: .create, description: "macOS Installer in Disk Image") { - try await InstallerCreator.create(installer, mountPoint: mountPointURL, cacheDirectory: cacheDirectory) } ] + + if installer.sierraOrOlder, + let package: Package = installer.packages.first { + let legacyDiskImageURL: URL = URL(fileURLWithPath: "\(cacheDirectory)/\(installer.id)/\(package.filename)") + let legacyDiskImageMountPointURL: URL = URL(fileURLWithPath: "/Volumes/Install \(installer.name)") + + tasks += [ + MistTask(type: .mount, description: "macOS Installer Disk Image") { + try await DiskImageMounter.mount(legacyDiskImageURL, mountPoint: legacyDiskImageMountPointURL) + }, + MistTask(type: .create, description: "macOS Installer in Disk Image") { + try await InstallerCreator.create(installer, mountPoint: mountPointURL, cacheDirectory: cacheDirectory) + }, + MistTask(type: .unmount, description: "macOS Installer Disk Image") { + try await DiskImageUnmounter.unmount(legacyDiskImageMountPointURL) + } + ] + } else { + tasks += [ + MistTask(type: .create, description: "macOS Installer in Disk Image") { + try await InstallerCreator.create(installer, mountPoint: mountPointURL, cacheDirectory: cacheDirectory) + } + ] + } + + return tasks } private static func applicationTasks(for installer: Installer, filename: String, destination destinationURL: URL) -> [MistTask] { diff --git a/Mist/Model/Installer.swift b/Mist/Model/Installer.swift index f98ef2b..0781266 100644 --- a/Mist/Model/Installer.swift +++ b/Mist/Model/Installer.swift @@ -7,6 +7,7 @@ import Foundation +// swiftlint:disable:next type_body_length struct Installer: Decodable, Hashable, Identifiable { enum CodingKeys: String, CodingKey { @@ -137,6 +138,106 @@ struct Installer: Decodable, Hashable, Identifiable { ) } + static var legacyInstallers: [Installer] { + [ + Installer( + id: "10.12.6-16G29", + version: "10.12.6", + build: "16G29", + date: "2017-07-15", + distributionURL: "", + distributionSize: 0, + packages: [ + Package( + url: "http://updates-http.cdn-apple.com/2019/cert/061-39476-20191023-48f365f4-0015-4c41-9f44-39d3d2aca067/InstallOS.dmg", + size: 5_007_882_126, + integrityDataURL: nil, + integrityDataSize: nil + ) + ], + boardIDs: [], + deviceIDs: [], + unsupportedModelIdentifiers: [] + ), + Installer( + id: "10.11.6-15G31", + version: "10.11.6", + build: "15G31", + date: "2016-05-18", + distributionURL: "", + distributionSize: 0, + packages: [ + Package( + url: "http://updates-http.cdn-apple.com/2019/cert/061-41424-20191024-218af9ec-cf50-4516-9011-228c78eda3d2/InstallMacOSX.dmg", + size: 6_204_629_298, + integrityDataURL: nil, + integrityDataSize: nil + ) + ], + boardIDs: [], + deviceIDs: [], + unsupportedModelIdentifiers: [] + ), + Installer( + id: "10.10.5-14F27", + version: "10.10.5", + build: "14F27", + date: "2015-08-05", + distributionURL: "", + distributionSize: 0, + packages: [ + Package( + url: "http://updates-http.cdn-apple.com/2019/cert/061-41343-20191023-02465f92-3ab5-4c92-bfe2-b725447a070d/InstallMacOSX.dmg", + size: 5_718_074_248, + integrityDataURL: nil, + integrityDataSize: nil + ) + ], + boardIDs: [], + deviceIDs: [], + unsupportedModelIdentifiers: [] + ), + Installer( + id: "10.8.5-12F45", + version: "10.8.5", + build: "12F45", + date: "2013-09-27", + distributionURL: "", + distributionSize: 0, + packages: [ + Package( + url: "https://updates.cdn-apple.com/2021/macos/031-0627-20210614-90D11F33-1A65-42DD-BBEA-E1D9F43A6B3F/InstallMacOSX.dmg", + size: 4_449_317_520, + integrityDataURL: nil, + integrityDataSize: nil + ) + ], + boardIDs: [], + deviceIDs: [], + unsupportedModelIdentifiers: [] + ), + Installer( + id: "10.7.5-11G63", + version: "10.7.5", + build: "11G63", + date: "2012-09-28", + distributionURL: "", + distributionSize: 0, + packages: [ + Package( + url: "https://updates.cdn-apple.com/2021/macos/041-7683-20210614-E610947E-C7CE-46EB-8860-D26D71F0D3EA/InstallMacOSX.dmg", + size: 4_720_237_409, + integrityDataURL: nil, + integrityDataSize: nil + ) + ], + boardIDs: [], + deviceIDs: [], + unsupportedModelIdentifiers: [] + ) + ] + } + static var filenameDescription: String { """ Use the following variables to set the filename dynamically. For example: @@ -182,6 +283,18 @@ struct Installer: Decodable, Hashable, Identifiable { name = "macOS Mojave" } else if version.range(of: "^10\\.13", options: .regularExpression) != nil { name = "macOS High Sierra" + } else if version.range(of: "^10\\.12", options: .regularExpression) != nil { + name = "macOS Sierra" + } else if version.range(of: "^10\\.11", options: .regularExpression) != nil { + name = "OS X El Capitan" + } else if version.range(of: "^10\\.10", options: .regularExpression) != nil { + name = "OS X Yosemite" + } else if version.range(of: "^10\\.9", options: .regularExpression) != nil { + name = "OS X Mavericks" + } else if version.range(of: "^10\\.8", options: .regularExpression) != nil { + name = "OS X Mountain Lion" + } else if version.range(of: "^10\\.7", options: .regularExpression) != nil { + name = "Mac OS X Lion" } else { name = "macOS \(version)" } @@ -225,7 +338,7 @@ struct Installer: Decodable, Hashable, Identifiable { return true } var allDownloads: [Package] { - [Package(url: distributionURL, size: distributionSize, integrityDataURL: nil, integrityDataSize: nil)] + packages.sorted { $0.filename < $1.filename } + (sierraOrOlder ? [] : [Package(url: distributionURL, size: distributionSize, integrityDataURL: nil, integrityDataSize: nil)]) + packages.sorted { $0.filename < $1.filename } } var temporaryDiskImageMountPointURL: URL { URL(fileURLWithPath: "/Volumes/\(id)") @@ -250,6 +363,9 @@ struct Installer: Decodable, Hashable, Identifiable { "beta": beta ] } + var sierraOrOlder: Bool { + version.range(of: "^10\\.([7-9]|1[0-2])\\.", options: .regularExpression) != nil + } var catalinaOrNewer: Bool { bigSurOrNewer || version.range(of: "^10\\.15\\.", options: .regularExpression) != nil } diff --git a/Mist/Views/Refresh/RefreshView.swift b/Mist/Views/Refresh/RefreshView.swift index 2b6f46d..a00b75a 100644 --- a/Mist/Views/Refresh/RefreshView.swift +++ b/Mist/Views/Refresh/RefreshView.swift @@ -153,6 +153,7 @@ struct RefreshView: View { } } + installers.append(contentsOf: Installer.legacyInstallers) installers.sort { $0.version == $1.version ? ($0.build.count == $1.build.count ? $0.build > $1.build : $0.build.count > $1.build.count) :