From a5fcffd71fb5352bfc0e6ba9a2fcf8f5fdc4a927 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Sun, 29 Oct 2023 23:36:09 +1100 Subject: [PATCH] Add support for legacy ISOs on Apple Silicon --- Mist/Helpers/Codesigner.swift | 15 +++++++++++++++ Mist/Helpers/TaskManager.swift | 13 +++++++++++++ Mist/Views/List/InstallerExportView.swift | 21 +-------------------- Mist/Views/List/ListRowInstaller.swift | 3 +-- Mist/Views/Settings/SettingsISOsView.swift | 2 +- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Mist/Helpers/Codesigner.swift b/Mist/Helpers/Codesigner.swift index f6b3227..880a025 100644 --- a/Mist/Helpers/Codesigner.swift +++ b/Mist/Helpers/Codesigner.swift @@ -25,4 +25,19 @@ struct Codesigner { throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError) } } + + /// Ad-hoc sign all files within a directory (or app bundle). + /// + /// - Parameters: + /// - url: The URL of the directory to ad-hoc sign. + /// + /// - Throws: A `MistError` if the command failed to execute. + static func adhocSign(_ url: URL) async throws { + let arguments: [String] = ["find", url.path, "-type", "f", "-exec", "codesign", "--sign", "-", "--force", "{}", ";"] + let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments) + + guard response.terminationStatus == 0 else { + throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError) + } + } } diff --git a/Mist/Helpers/TaskManager.swift b/Mist/Helpers/TaskManager.swift index 2d2ad9b..e287f84 100644 --- a/Mist/Helpers/TaskManager.swift +++ b/Mist/Helpers/TaskManager.swift @@ -426,6 +426,7 @@ class TaskManager: ObservableObject { return tasks } + // swiftlint:disable:next function_body_length private static func isoTasks(for installer: Installer, filename: String, destination destinationURL: URL, temporaryDirectory temporaryDirectoryURL: URL) -> [MistTask] { let temporaryImageURL: URL = temporaryDirectoryURL.appendingPathComponent("\(installer.id).dmg") @@ -443,6 +444,12 @@ class TaskManager: ObservableObject { }, MistTask(type: .create, description: "macOS Installer in temporary Disk Image") { + // Workaround to make OS X Yosemite 10.10 to macOS Catalina 10.15 createinstallmedia work on Apple Silicon + if let architecture: Architecture = Hardware.architecture, + architecture == .appleSilicon && !installer.bigSurOrNewer { + try await Codesigner.adhocSign(installer.temporaryInstallerURL) + } + // Workaround to make macOS Sierra 10.12 createinstallmedia work if installer.version.hasPrefix("10.12") { let infoPlistURL: URL = installer.temporaryInstallerURL.appendingPathComponent("Contents/Info.plist") @@ -533,6 +540,12 @@ class TaskManager: ObservableObject { let tasks: [MistTask] = [ MistTask(type: .create, description: "Bootable Installer") { + // Workaround to make OS X Yosemite 10.10 to macOS Catalina 10.15 createinstallmedia work on Apple Silicon + if let architecture: Architecture = Hardware.architecture, + architecture == .appleSilicon && !installer.bigSurOrNewer { + try await Codesigner.adhocSign(installer.temporaryInstallerURL) + } + // Workaround to make macOS Sierra 10.12 createinstallmedia work if installer.version.hasPrefix("10.12") { let infoPlistURL: URL = installer.temporaryInstallerURL.appendingPathComponent("Contents/Info.plist") diff --git a/Mist/Views/List/InstallerExportView.swift b/Mist/Views/List/InstallerExportView.swift index aa32c11..15b0a9f 100644 --- a/Mist/Views/List/InstallerExportView.swift +++ b/Mist/Views/List/InstallerExportView.swift @@ -18,16 +18,6 @@ struct InstallerExportView: View { private var exportPackage: Bool = false var installer: Installer @Binding var exports: [InstallerExportType] - private var isoCompatible: Bool { - guard let architecture: Architecture = Hardware.architecture else { - return false - } - - return architecture == .intel || (architecture == .appleSilicon && installer.bigSurOrNewer) - } - private var compatibilityMessage: String { - "**Note:** ISOs are unavailable for building **macOS Catalina 10.15 and older** on [Apple Silicon Macs](https://support.apple.com/en-us/HT211814)." - } var body: some View { VStack { @@ -40,16 +30,11 @@ struct InstallerExportView: View { InstallerExportViewItem(exportType: .diskImage, selected: $exportDiskImage) .disabled(exports.count == 1 && exportDiskImage) InstallerExportViewItem(exportType: .iso, selected: $exportISO) - .disabled(isoCompatible ? exports.count == 1 && exportISO : true) - .opacity(isoCompatible ? 1 : 0.5) + .disabled(exports.count == 1 && exportISO) InstallerExportViewItem(exportType: .package, selected: $exportPackage) .disabled(exports.count == 1 && exportPackage) Spacer() } - if !isoCompatible { - Text(.init(compatibilityMessage)) - .padding(.top) - } } .padding() .onChange(of: exportApplication) { _ in @@ -73,10 +58,6 @@ struct InstallerExportView: View { var exports: [InstallerExportType] = [] - if !isoCompatible && exportISO { - exportISO = false - } - if !exportApplication && !exportDiskImage && !exportISO && !exportPackage { exportApplication = true } diff --git a/Mist/Views/List/ListRowInstaller.swift b/Mist/Views/List/ListRowInstaller.swift index 9be0694..24e9074 100644 --- a/Mist/Views/List/ListRowInstaller.swift +++ b/Mist/Views/List/ListRowInstaller.swift @@ -91,8 +91,7 @@ struct ListRowInstaller: View { } .help("Download and export macOS Installer") .buttonStyle(.mistAction) - if let architecture: Architecture = Hardware.architecture, - (architecture == .appleSilicon && installer.bigSurOrNewer) || (architecture == .intel && installer.mavericksOrNewer) { + if installer.mavericksOrNewer { Button { pressButton(.volumeSelection) } label: { diff --git a/Mist/Views/Settings/SettingsISOsView.swift b/Mist/Views/Settings/SettingsISOsView.swift index b05209a..4efebb2 100644 --- a/Mist/Views/Settings/SettingsISOsView.swift +++ b/Mist/Views/Settings/SettingsISOsView.swift @@ -13,7 +13,7 @@ struct SettingsISOsView: View { private let imageName: String = "ISO" private let title: String = "ISOs" // swiftlint:disable:next line_length - private let description: String = "ISOs are Bootable macOS Installer Disk Images that can be restored on external USB drives, or used with virtualization software (ie. [Parallels Desktop](https://www.parallels.com/au/products/desktop/), [UTM](https://mac.getutm.app), [VMware Fusion](https://www.vmware.com/au/products/fusion.html), [VirtualBox](https://www.virtualbox.org)).\n\n**Note:** ISOs are unavailable for building **macOS Catalina 10.15 and older** on [Apple Silicon Macs](https://support.apple.com/en-us/HT211814)." + private let description: String = "ISOs are Bootable macOS Installer Disk Images that can be restored on external USB drives, or used with virtualization software (ie. [Parallels Desktop](https://www.parallels.com/au/products/desktop/), [UTM](https://mac.getutm.app), [VMware Fusion](https://www.vmware.com/au/products/fusion.html), [VirtualBox](https://www.virtualbox.org))." var body: some View { VStack(alignment: .leading) {