diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0c07d1..23c66ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,12 +10,12 @@ on: jobs: build: name: Build - runs-on: macos-15 + runs-on: macos-26 steps: - - uses: actions/checkout@v5 - - uses: swift-actions/setup-swift@v2 + - uses: actions/checkout@v6 + - uses: swift-actions/setup-swift@v3 with: - swift-version: 5.10.1 + swift-version: "6.3.1" - name: Install Apple Developer ID Application Certificate env: APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE }} diff --git a/.github/workflows/draft_new_release.yml b/.github/workflows/draft_new_release.yml index 073f5bd..03c935f 100644 --- a/.github/workflows/draft_new_release.yml +++ b/.github/workflows/draft_new_release.yml @@ -3,7 +3,7 @@ on: workflow_dispatch jobs: build: name: Draft New Release - runs-on: macos-15 + runs-on: macos-26 env: APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE }} APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD }} @@ -18,10 +18,10 @@ jobs: APPLE_DEVELOPER_TEAM_ID: "7K3HVCLV7Z" KEYCHAIN_FILE: "apple-developer.keychain-db" steps: - - uses: actions/checkout@v5 - - uses: swift-actions/setup-swift@v2 + - uses: actions/checkout@v6 + - uses: swift-actions/setup-swift@v3 with: - swift-version: 5.10.1 + swift-version: "6.3.1" - name: Install Apple Developer ID Certificates run: | APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_PATH="$RUNNER_TEMP/apple-developer-id-application-certificate.p12" @@ -86,7 +86,7 @@ jobs: xcrun notarytool submit "${{ env.PACKAGE_FILENAME }}" --apple-id "$APPLE_DEVELOPER_APPLE_ID" --password "$APPLE_DEVELOPER_APPLE_ID_PASSWORD" --team-id "$APPLE_DEVELOPER_TEAM_ID" --wait xcrun stapler staple "${{ env.PACKAGE_FILENAME }}" - name: Draft New Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: name: ${{ env.APP_VERSION }} tag_name: v${{ env.APP_VERSION }} diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 32649da..28756c1 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -10,15 +10,15 @@ on: jobs: linting: name: Linting - runs-on: macos-15 + runs-on: macos-26 steps: - - uses: actions/checkout@v5 - - uses: swift-actions/setup-swift@v2 + - uses: actions/checkout@v6 + - uses: swift-actions/setup-swift@v3 with: - swift-version: 5.10.1 + swift-version: "6.3.1" - uses: m-takuma/setup-swiftlint@1.0.0 with: - swiftlint-version: 0.61.0 + swiftlint-version: "0.63.2" - name: Print SwiftLint version run: swiftlint --version - name: Run SwiftLint diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index ef60c6f..5e2fa73 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -10,12 +10,12 @@ on: jobs: unit_tests: name: Unit Tests - runs-on: macos-15 + runs-on: macos-26 steps: - - uses: actions/checkout@v5 - - uses: swift-actions/setup-swift@v2 + - uses: actions/checkout@v6 + - uses: swift-actions/setup-swift@v3 with: - swift-version: 5.10.1 + swift-version: "6.3.1" - name: Install Apple Developer ID Application Certificate env: APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE }} diff --git a/.swift-version b/.swift-version index 4e32c7b..dc0208a 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -5.10.1 +6.3.1 diff --git a/LICENSE b/LICENSE index 664b582..7ac795c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 Nindi Gill +Copyright (c) 2021-2026 Nindi Gill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Mist.xcodeproj/project.pbxproj b/Mist.xcodeproj/project.pbxproj index b468841..6b6cb0d 100644 --- a/Mist.xcodeproj/project.pbxproj +++ b/Mist.xcodeproj/project.pbxproj @@ -677,7 +677,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1410; - LastUpgradeCheck = 2600; + LastUpgradeCheck = 2700; TargetAttributes = { 390451A52856E1D900E0B563 = { CreatedOnToolsVersion = 14.0; @@ -1117,7 +1117,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.30; + CURRENT_PROJECT_VERSION = 0.40; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 7K3HVCLV7Z; ENABLE_HARDENED_RUNTIME = YES; @@ -1133,7 +1133,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 0.30; + MARKETING_VERSION = 0.40; PRODUCT_BUNDLE_IDENTIFIER = com.ninxsoft.mist; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1151,7 +1151,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.30; + CURRENT_PROJECT_VERSION = 0.40; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 7K3HVCLV7Z; ENABLE_HARDENED_RUNTIME = YES; @@ -1167,7 +1167,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 0.30; + MARKETING_VERSION = 0.40; PRODUCT_BUNDLE_IDENTIFIER = com.ninxsoft.mist; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1334,7 +1334,7 @@ repositoryURL = "https://github.com/jpsim/Yams"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 6.1.0; + minimumVersion = 6.2.2; }; }; 3935F4C3286B546A00760AB0 /* XCRemoteSwiftPackageReference "Sparkle" */ = { @@ -1342,7 +1342,7 @@ repositoryURL = "https://github.com/sparkle-project/Sparkle"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 2.8.0; + minimumVersion = 2.9.4; }; }; 39CF55A8286154A5006FB5D2 /* XCRemoteSwiftPackageReference "Blessed" */ = { diff --git a/Mist.xcodeproj/xcshareddata/xcschemes/Mist.xcscheme b/Mist.xcodeproj/xcshareddata/xcschemes/Mist.xcscheme index 864e56f..c6f8761 100644 --- a/Mist.xcodeproj/xcshareddata/xcschemes/Mist.xcscheme +++ b/Mist.xcodeproj/xcshareddata/xcschemes/Mist.xcscheme @@ -1,6 +1,6 @@ Bool { lhs.localizedDescription == rhs.localizedDescription } diff --git a/Mist/Extensions/Dictionary+Extension.swift b/Mist/Extensions/Dictionary+Extension.swift index 8f31a69..a7b856c 100644 --- a/Mist/Extensions/Dictionary+Extension.swift +++ b/Mist/Extensions/Dictionary+Extension.swift @@ -33,7 +33,7 @@ extension Dictionary where Key == String { let signedString: String = "\(signed ? "YES" : "NO")" let betaString: String = "\(beta ? "YES" : "NO")" - let string: String = [ + return [ nameString, versionString, buildString, @@ -44,7 +44,6 @@ extension Dictionary where Key == String { signedString, betaString ].joined(separator: ",") + "\n" - return string } /// Provides an installer CSV string representation. @@ -72,7 +71,7 @@ extension Dictionary where Key == String { let compatibleString: String = "\(compatible ? "YES" : "NO")" let betaString: String = "\(beta ? "YES" : "NO")" - let string: String = [ + return [ identifierString, nameString, versionString, @@ -82,6 +81,5 @@ extension Dictionary where Key == String { compatibleString, betaString ].joined(separator: ",") + "\n" - return string } } diff --git a/Mist/Extensions/Scene+Extension.swift b/Mist/Extensions/Scene+Extension.swift index 49131ee..efdef46 100644 --- a/Mist/Extensions/Scene+Extension.swift +++ b/Mist/Extensions/Scene+Extension.swift @@ -14,7 +14,7 @@ extension Scene { func fixedWindow() -> some Scene { if #available(macOS 13.0, *) { // swiftformat:disable:next redundantReturn - return self.windowResizability(.contentSize) + return windowResizability(.contentSize) } else { // swiftformat:disable:next redundantReturn return self diff --git a/Mist/Helpers/TaskManager.swift b/Mist/Helpers/TaskManager.swift index 46fb6bb..b53dd86 100644 --- a/Mist/Helpers/TaskManager.swift +++ b/Mist/Helpers/TaskManager.swift @@ -239,7 +239,7 @@ class TaskManager: ObservableObject { ) throws -> [(section: MistTaskSection, tasks: [MistTask])] { let cacheDirectoryURL: URL = .init(fileURLWithPath: cacheDirectory).appendingPathComponent(installer.id) let temporaryDirectoryURL: URL = .init(fileURLWithPath: .temporaryDirectory) - let taskGroups: [(section: MistTaskSection, tasks: [MistTask])] = try [ + return try [ ( section: .download, tasks: downloadTasks(for: installer, cacheDirectory: cacheDirectoryURL, retries: retries, delay: retryDelay) @@ -262,8 +262,6 @@ class TaskManager: ObservableObject { ) ) ] - - return taskGroups } private static func downloadTasks(for installer: Installer, cacheDirectory cacheDirectoryURL: URL, retries: Int, delay retryDelay: Int) throws -> [MistTask] { @@ -561,7 +559,7 @@ class TaskManager: ObservableObject { private static func bootableInstallerTasks(for installer: Installer, volume: InstallerVolume) -> [MistTask] { let createInstallMediaURL: URL = installer.temporaryInstallerURL.appendingPathComponent("Contents/Resources/createinstallmedia") let mountPointURL: URL = .init(fileURLWithPath: volume.path) - let tasks: [MistTask] = [ + return [ MistTask(type: .create, description: "Bootable Installer") { // Workaround to make macOS Sierra 10.12 createinstallmedia work if installer.version.hasPrefix("10.12") { @@ -574,8 +572,6 @@ class TaskManager: ObservableObject { try await InstallMediaCreator.create(createInstallMediaURL, mountPoint: mountPointURL, sierraOrOlder: installer.sierraOrOlder) } ] - - return tasks } private static func cleanupTasks(mountPoint mountPointURL: URL, temporaryDirectory temporaryDirectoryURL: URL, cacheDownloads: Bool, cacheDirectory cacheDirectoryURL: URL) -> [MistTask] { diff --git a/Mist/Mist.icon/Assets/Mist.png b/Mist/Mist.icon/Assets/Mist.png index 7d2517e..2d0677e 100644 Binary files a/Mist/Mist.icon/Assets/Mist.png and b/Mist/Mist.icon/Assets/Mist.png differ diff --git a/Mist/Model/AppIcon.swift b/Mist/Model/AppIcon.swift index 9c4fef8..3e268f7 100644 --- a/Mist/Model/AppIcon.swift +++ b/Mist/Model/AppIcon.swift @@ -13,8 +13,9 @@ enum AppIcon: String, CaseIterable, Identifiable { case sonoma = "macOS Sonoma" case sequoia = "macOS Sequoia" case tahoe = "macOS Tahoe" + case goldenGate = "macOS Golden Gate" - static let `default`: AppIcon = .tahoe + static let `default`: AppIcon = .goldenGate var id: String { rawValue diff --git a/Mist/Model/Catalog.swift b/Mist/Model/Catalog.swift index 40faa02..0773bc0 100644 --- a/Mist/Model/Catalog.swift +++ b/Mist/Model/Catalog.swift @@ -17,7 +17,7 @@ struct Catalog: Identifiable, Decodable, Equatable { } static var example: Catalog { - Catalog(type: .tahoe, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) + Catalog(type: .goldenGate, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) } var id: UUID = .init() diff --git a/Mist/Model/CatalogType.swift b/Mist/Model/CatalogType.swift index c62a963..4a17932 100644 --- a/Mist/Model/CatalogType.swift +++ b/Mist/Model/CatalogType.swift @@ -6,6 +6,7 @@ // enum CatalogType: String, CaseIterable, Comparable, Decodable { + case goldenGate = "macOS Golden Gate" case tahoe = "macOS Tahoe" case sequoia = "macOS Sequoia" case sonoma = "macOS Sonoma" @@ -23,18 +24,20 @@ enum CatalogType: String, CaseIterable, Comparable, Decodable { private var sortOrder: Int { switch self { - case .tahoe: + case .goldenGate: 0 - case .sequoia: + case .tahoe: 1 - case .sonoma: + case .sequoia: 2 - case .ventura: + case .sonoma: 3 - case .monterey: + case .ventura: 4 - case .bigSur: + case .monterey: 5 + case .bigSur: + 6 } } @@ -45,6 +48,20 @@ enum CatalogType: String, CaseIterable, Comparable, Decodable { // swiftlint:disable:next cyclomatic_complexity function_body_length func url(for seedType: CatalogSeedType) -> String { switch self { + case .goldenGate: + switch seedType { + case .standard: + "https://swscan.apple.com/content/catalogs/others/index-27-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" + case .customer: + // swiftlint:disable:next line_length + "https://swscan.apple.com/content/catalogs/others/index-27customerseed-27-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" + case .developer: + // swiftlint:disable:next line_length + "https://swscan.apple.com/content/catalogs/others/index-27seed-27-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" + case .public: + // swiftlint:disable:next line_length + "https://swscan.apple.com/content/catalogs/others/index-27beta-27-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" + } case .tahoe: switch seedType { case .standard: diff --git a/Mist/Model/Firmware.swift b/Mist/Model/Firmware.swift index 3ed7d80..b5a1f11 100644 --- a/Mist/Model/Firmware.swift +++ b/Mist/Model/Firmware.swift @@ -51,7 +51,9 @@ struct Firmware: Decodable, Hashable, Identifiable { var name: String { var name: String = "" - if version.range(of: "^26", options: .regularExpression) != nil { + if version.range(of: "^27", options: .regularExpression) != nil { + name = "macOS Golden Gate" + } else if version.range(of: "^26", options: .regularExpression) != nil { name = "macOS Tahoe" } else if version.range(of: "^15", options: .regularExpression) != nil { name = "macOS Sequoia" diff --git a/Mist/Model/Installer.swift b/Mist/Model/Installer.swift index 47db309..e37cc85 100644 --- a/Mist/Model/Installer.swift +++ b/Mist/Model/Installer.swift @@ -654,7 +654,9 @@ struct Installer: Decodable, Hashable, Identifiable { var name: String { var name: String = "" - if version.range(of: "^26", options: .regularExpression) != nil { + if version.range(of: "^27", options: .regularExpression) != nil { + name = "macOS Golden Gate" + } else if version.range(of: "^26", options: .regularExpression) != nil { name = "macOS Tahoe" } else if version.range(of: "^15", options: .regularExpression) != nil { name = "macOS Sequoia" @@ -783,7 +785,7 @@ struct Installer: Decodable, Hashable, Identifiable { } var bigSurOrNewer: Bool { - version.range(of: "^(1[1-5]|26)\\.", options: .regularExpression) != nil + version.range(of: "^(1[1-5]|2[6-7])\\.", options: .regularExpression) != nil } var beta: Bool { diff --git a/Mist/Views/Activity/ActivityView.swift b/Mist/Views/Activity/ActivityView.swift index 1b469ee..32f7fc0 100644 --- a/Mist/Views/Activity/ActivityView.swift +++ b/Mist/Views/Activity/ActivityView.swift @@ -227,7 +227,7 @@ struct ActivityView: View { DownloadManager.shared.cancelTask() taskManager.cancelTask() ShellExecutor.shared.terminate() - Task { try await ProcessKiller.kill() } + _ = Task { try await ProcessKiller.kill() } presentationMode.wrappedValue.dismiss() } } diff --git a/Mist/Views/List/ListRowFirmware.swift b/Mist/Views/List/ListRowFirmware.swift index 607b33b..68d27f2 100644 --- a/Mist/Views/List/ListRowFirmware.swift +++ b/Mist/Views/List/ListRowFirmware.swift @@ -133,7 +133,7 @@ struct ListRowFirmware: View { savePanel.canSelectHiddenExtension = true savePanel.isExtensionHidden = false - Task { + _ = Task { let response: NSApplication.ModalResponse = savePanel.runModal() guard response == .OK else { diff --git a/Mist/Views/List/ListRowInstaller.swift b/Mist/Views/List/ListRowInstaller.swift index a8764a3..88a89d8 100644 --- a/Mist/Views/List/ListRowInstaller.swift +++ b/Mist/Views/List/ListRowInstaller.swift @@ -171,7 +171,7 @@ struct ListRowInstaller: View { openPanel.accessoryView = NSHostingView(rootView: InstallerExportView(installer: installer, exports: $exports)) openPanel.isAccessoryViewDisclosed = true - Task { + _ = Task { let response: NSApplication.ModalResponse = openPanel.runModal() guard response == .OK else { @@ -207,7 +207,7 @@ struct ListRowInstaller: View { return } - Task { + _ = Task { taskManager.taskGroups = try TaskManager.taskGroups( for: installer, cacheDownloads: cacheDownloads, @@ -337,7 +337,7 @@ struct ListRowInstaller: View { Alert( title: Text("Cache directory settings incorrect!"), message: Text(cacheDirectoryMessage), - primaryButton: .default(Text("Repair...")) { Task { try await repairCacheDirectoryOwnershipAndPermissions() } }, + primaryButton: .default(Text("Repair...")) { _ = Task { try await repairCacheDirectoryOwnershipAndPermissions() } }, secondaryButton: .default(Text("Cancel")) ) case .error: diff --git a/Mist/Views/Settings/SettingsApplicationsView.swift b/Mist/Views/Settings/SettingsApplicationsView.swift index c26c45a..328f356 100644 --- a/Mist/Views/Settings/SettingsApplicationsView.swift +++ b/Mist/Views/Settings/SettingsApplicationsView.swift @@ -10,6 +10,7 @@ import SwiftUI struct SettingsApplicationsView: View { private static let imageNames: [String] = [ + "Application - macOS Golden Gate", "Application - macOS Tahoe", "Application - macOS Sequoia", "Application - macOS Sonoma", diff --git a/MistHelperTool/Info.plist b/MistHelperTool/Info.plist index 5c72b56..89cca6f 100644 --- a/MistHelperTool/Info.plist +++ b/MistHelperTool/Info.plist @@ -9,9 +9,9 @@ CFBundleInfoDictionaryVersion 1.0 CFBundleShortVersionString - 0.30 + 0.40 CFBundleVersion - 0.30 + 0.40 SMAuthorizedClients anchor apple generic and identifier "com.ninxsoft.mist" and info[CFBundleVersion] >= "0.1" and certificate leaf[subject.OU] = "7K3HVCLV7Z" diff --git a/MistTests/MistTests.swift b/MistTests/MistTests.swift index a8373bb..28f56eb 100644 --- a/MistTests/MistTests.swift +++ b/MistTests/MistTests.swift @@ -8,7 +8,7 @@ import XCTest final class MistTests: XCTestCase { - func test() throws { + func test() { XCTAssertTrue(true) } } diff --git a/README.md b/README.md index 3b40463..8fbe228 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ A Mac utility that automatically downloads macOS Firmwares / Installers: ## Build Requirements -- Swift **5.10** | Xcode **15.0**. +- Swift **6.3.1** | Xcode **26.0**. - Runs on macOS Monterey **12.0** and later. ## Download @@ -76,7 +76,7 @@ A Mac utility that automatically downloads macOS Firmwares / Installers: ## License -> Copyright © 2021-2025 Nindi Gill +> Copyright © 2021-2026 Nindi Gill > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal