From e8a4835f4ebe55519942e7b54032acbd5360d33f Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Wed, 7 Dec 2022 19:15:10 +1100 Subject: [PATCH 01/12] Add GitHub actions for linting --- .github/workflows/do_all_of_the_things.yml | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/do_all_of_the_things.yml diff --git a/.github/workflows/do_all_of_the_things.yml b/.github/workflows/do_all_of_the_things.yml new file mode 100644 index 0000000..59cabe8 --- /dev/null +++ b/.github/workflows/do_all_of_the_things.yml @@ -0,0 +1,23 @@ +name: Do all of the things! +on: [push, pull_request] +jobs: + do-all-of-the-things: + name: Do all of the things! + runs-on: macos-12 + steps: + - uses: actions/checkout@v3 + - uses: swift-actions/setup-swift@v1 + - name: Print SwiftLint version + run: swiftlint --version + - name: Run SwiftLint + run: swiftlint --strict + - name: Download DrString + run: curl --silent https://api.github.com/repos/dduan/DrString/releases/latest | grep "browser_download_url.*drstring-x86_64-apple-darwin.tar.gz" | awk '{ print $NF }' | tr -d '"' | curl --location --silent --output drstring-x86_64-apple-darwin.tar.gz + - name: Extract DrString + run: tar --extract --file drstring-x86_64-apple-darwin.tar.gz --directory drstring-x86_64-apple-darwin + - name: Add DrString to $PATH + run: echo "$GITHUB_WORKSPACE/drstring-x86_64-apple-darwin" >> $GITHUB_PATH + - name: Print DrString version + run: drstring --version + - name: Run DrString + run: drstring check --config-file .drstring.toml From 1688095e1838b572df19492455a3cfef3621c3b5 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 11:39:32 +1100 Subject: [PATCH 02/12] Add support for toggling custom SUCatalogs --- Mist.xcodeproj/project.pbxproj | 20 +++-- Mist/Model/Catalog.swift | 69 ++++++++++----- Mist/Model/CatalogRow.swift | 18 ---- Mist/Model/CatalogSeedType.swift | 19 ++++ Mist/Model/CatalogType.swift | 80 +++++++++++++++++ Mist/Views/Refresh/RefreshView.swift | 50 ++++++++++- .../SettingsInstallersCatalogsView.swift | 86 +++++++++++++------ .../Settings/SettingsInstallersView.swift | 36 +++++--- 8 files changed, 290 insertions(+), 88 deletions(-) delete mode 100644 Mist/Model/CatalogRow.swift create mode 100644 Mist/Model/CatalogSeedType.swift create mode 100644 Mist/Model/CatalogType.swift diff --git a/Mist.xcodeproj/project.pbxproj b/Mist.xcodeproj/project.pbxproj index 8d01f1a..0f42490 100644 --- a/Mist.xcodeproj/project.pbxproj +++ b/Mist.xcodeproj/project.pbxproj @@ -26,7 +26,7 @@ 390451DC28573F1000E0B563 /* Dictionary+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 390451DB28573F1000E0B563 /* Dictionary+Extension.swift */; }; 390451DF28573FAA00E0B563 /* Yams in Frameworks */ = {isa = PBXBuildFile; productRef = 390451DE28573FAA00E0B563 /* Yams */; }; 390451E1285740E800E0B563 /* Sequence+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 390451E0285740E800E0B563 /* Sequence+Extension.swift */; }; - 390451E528574F0000E0B563 /* Catalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 390451E428574F0000E0B563 /* Catalog.swift */; }; + 390451E528574F0000E0B563 /* CatalogType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 390451E428574F0000E0B563 /* CatalogType.swift */; }; 390451E72857510C00E0B563 /* TextTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 390451E62857510B00E0B563 /* TextTag.swift */; }; 39148CFC28DD55B300011FF5 /* PathControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39148CFB28DD55B300011FF5 /* PathControl.swift */; }; 39252A77285A849F00956C74 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39252A76285A849F00956C74 /* AppDelegate.swift */; }; @@ -94,7 +94,8 @@ 398734D028603D9E00B4C357 /* UInt8+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398734CF28603D9E00B4C357 /* UInt8+Extension.swift */; }; 398734D228603DE700B4C357 /* Array+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398734D128603DE700B4C357 /* Array+Extension.swift */; }; 398734D4286046B000B4C357 /* UInt32+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398734D3286046B000B4C357 /* UInt32+Extension.swift */; }; - 39CF4E732859C03D009E708C /* CatalogRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CF4E722859C03D009E708C /* CatalogRow.swift */; }; + 39CB5E3D293F5C2E00CFDBB8 /* Catalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CB5E3C293F5C2E00CFDBB8 /* Catalog.swift */; }; + 39CB5E3F2941486D00CFDBB8 /* CatalogSeedType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CB5E3E2941486D00CFDBB8 /* CatalogSeedType.swift */; }; 39CF55A028614DD8006FB5D2 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CF559F28614DD8006FB5D2 /* main.swift */; }; 39CF55AA286154A5006FB5D2 /* Blessed in Frameworks */ = {isa = PBXBuildFile; productRef = 39CF55A9286154A5006FB5D2 /* Blessed */; }; 39CF55AB286154D1006FB5D2 /* com.ninxsoft.mist.helper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 39CF559D28614DD8006FB5D2 /* com.ninxsoft.mist.helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -173,7 +174,7 @@ 390451D928573ADC00E0B563 /* ExportListType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportListType.swift; sourceTree = ""; }; 390451DB28573F1000E0B563 /* Dictionary+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+Extension.swift"; sourceTree = ""; }; 390451E0285740E800E0B563 /* Sequence+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Extension.swift"; sourceTree = ""; }; - 390451E428574F0000E0B563 /* Catalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Catalog.swift; sourceTree = ""; }; + 390451E428574F0000E0B563 /* CatalogType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CatalogType.swift; sourceTree = ""; }; 390451E62857510B00E0B563 /* TextTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextTag.swift; sourceTree = ""; }; 39148CFB28DD55B300011FF5 /* PathControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathControl.swift; sourceTree = ""; }; 39252A76285A849F00956C74 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -237,7 +238,8 @@ 398734CF28603D9E00B4C357 /* UInt8+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt8+Extension.swift"; sourceTree = ""; }; 398734D128603DE700B4C357 /* Array+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extension.swift"; sourceTree = ""; }; 398734D3286046B000B4C357 /* UInt32+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt32+Extension.swift"; sourceTree = ""; }; - 39CF4E722859C03D009E708C /* CatalogRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CatalogRow.swift; sourceTree = ""; }; + 39CB5E3C293F5C2E00CFDBB8 /* Catalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Catalog.swift; sourceTree = ""; }; + 39CB5E3E2941486D00CFDBB8 /* CatalogSeedType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CatalogSeedType.swift; sourceTree = ""; }; 39CF559D28614DD8006FB5D2 /* com.ninxsoft.mist.helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = com.ninxsoft.mist.helper; sourceTree = BUILT_PRODUCTS_DIR; }; 39CF559F28614DD8006FB5D2 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 39CF55A528614E66006FB5D2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -379,8 +381,9 @@ 390451C32856E4A500E0B563 /* Model */ = { isa = PBXGroup; children = ( - 390451E428574F0000E0B563 /* Catalog.swift */, - 39CF4E722859C03D009E708C /* CatalogRow.swift */, + 39CB5E3C293F5C2E00CFDBB8 /* Catalog.swift */, + 390451E428574F0000E0B563 /* CatalogType.swift */, + 39CB5E3E2941486D00CFDBB8 /* CatalogSeedType.swift */, 398734CB28603D5F00B4C357 /* Chunklist.swift */, 398734CD28603D7F00B4C357 /* Chunk.swift */, 395DCD15287FE36E00C411CE /* DownloadAlertType.swift */, @@ -740,6 +743,7 @@ 398734C428600E6E00B4C357 /* TaskManager.swift in Sources */, 390451D62856F7FE00E0B563 /* UInt64+Extension.swift in Sources */, 3935F47E2864813B00760AB0 /* DownloadManager.swift in Sources */, + 39CB5E3D293F5C2E00CFDBB8 /* Catalog.swift in Sources */, 39252AA1285C2A1600956C74 /* PaddedDivider.swift in Sources */, 39CF560C2861AE93006FB5D2 /* HelperToolCommandResponse.swift in Sources */, 39252A99285BFE2C00956C74 /* MistTaskState.swift in Sources */, @@ -767,14 +771,14 @@ 390451C22856E3F500E0B563 /* Hardware.swift in Sources */, 39CF56092861AE7F006FB5D2 /* HelperToolCommandRequest.swift in Sources */, 390451C82856E94900E0B563 /* FirmwareListRow.swift in Sources */, - 39CF4E732859C03D009E708C /* CatalogRow.swift in Sources */, - 390451E528574F0000E0B563 /* Catalog.swift in Sources */, + 390451E528574F0000E0B563 /* CatalogType.swift in Sources */, 3935F4852866B64900760AB0 /* MistTaskSection.swift in Sources */, 390451AC2856E1D900E0B563 /* ContentView.swift in Sources */, 3935F4A4286AD21000760AB0 /* DownloadProgressView.swift in Sources */, 39252A89285AD0AB00956C74 /* SettingsHeaderView.swift in Sources */, 39252A85285ACDC800956C74 /* ResetToDefaultButton.swift in Sources */, 39CF560F2861B857006FB5D2 /* XPCRoute+Extension.swift in Sources */, + 39CB5E3F2941486D00CFDBB8 /* CatalogSeedType.swift in Sources */, 39252A7F285AC6F600956C74 /* SettingsPackagesView.swift in Sources */, 39CF562F2862A797006FB5D2 /* ISOConverter.swift in Sources */, 39CF56392862D75D006FB5D2 /* FileCreator.swift in Sources */, diff --git a/Mist/Model/Catalog.swift b/Mist/Model/Catalog.swift index b9f5a3b..9bb50aa 100644 --- a/Mist/Model/Catalog.swift +++ b/Mist/Model/Catalog.swift @@ -2,32 +2,61 @@ // Catalog.swift // Mist // -// Created by Nindi Gill on 13/6/2022. +// Created by Nindi Gill on 6/12/2022. // import Foundation -enum Catalog: String, CaseIterable { - // swiftlint:disable redundant_string_enum_value - case standard = "standard" - case customer = "customer" - case developer = "developer" - case `public` = "public" +struct Catalog: Identifiable, Decodable, Equatable { - static var urls: [String] { - self.allCases.map { $0.url } + enum CodingKeys: String, CodingKey { + // swiftlint:disable:next redundant_string_enum_value + case type = "type" + // swiftlint:disable:next redundant_string_enum_value + case standard = "standard" + // swiftlint:disable:next redundant_string_enum_value + case customerSeed = "customerSeed" + // swiftlint:disable:next redundant_string_enum_value + case developerSeed = "developerSeed" + // swiftlint:disable:next redundant_string_enum_value + case publicSeed = "publicSeed" } - var url: String { - switch self { - case .standard: - return "https://swscan.apple.com/content/catalogs/others/index-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: - return "https://swscan.apple.com/content/catalogs/others/index-12customerseed-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: - return "https://swscan.apple.com/content/catalogs/others/index-12seed-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`: - return "https://swscan.apple.com/content/catalogs/others/index-12beta-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" - } + static var example: Catalog { + Catalog(type: .ventura, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) + } + + var id: UUID = UUID() + var type: CatalogType + var standard: Bool + var customerSeed: Bool + var developerSeed: Bool + var publicSeed: Bool + + init(type: CatalogType, standard: Bool, customerSeed: Bool, developerSeed: Bool, publicSeed: Bool) { + self.type = type + self.standard = standard + self.customerSeed = customerSeed + self.developerSeed = developerSeed + self.publicSeed = publicSeed + } + + init(from decoder: Decoder) throws { + let container: KeyedDecodingContainer = try decoder.container(keyedBy: CodingKeys.self) + type = try container.decode(CatalogType.self, forKey: .type) + standard = try container.decode(Bool.self, forKey: .standard) + customerSeed = try container.decode(Bool.self, forKey: .customerSeed) + developerSeed = try container.decode(Bool.self, forKey: .developerSeed) + publicSeed = try container.decode(Bool.self, forKey: .publicSeed) + } + + func dictionary() -> [String: Any] { + [ + "type": type.description, + "standard": standard, + "customerSeed": customerSeed, + "developerSeed": developerSeed, + "publicSeed": publicSeed + ] } } diff --git a/Mist/Model/CatalogRow.swift b/Mist/Model/CatalogRow.swift deleted file mode 100644 index 9ab13a5..0000000 --- a/Mist/Model/CatalogRow.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// CatalogRow.swift -// Mist -// -// Created by Nindi Gill on 15/6/2022. -// - -import Foundation - -struct CatalogRow: Identifiable, Hashable { - - static var example: CatalogRow { - CatalogRow(url: Catalog.standard.url) - } - - var id: UUID = UUID() - var url: String -} diff --git a/Mist/Model/CatalogSeedType.swift b/Mist/Model/CatalogSeedType.swift new file mode 100644 index 0000000..c329d86 --- /dev/null +++ b/Mist/Model/CatalogSeedType.swift @@ -0,0 +1,19 @@ +// +// CatalogSeedType.swift +// Mist +// +// Created by Nindi Gill on 8/12/2022. +// + +import Foundation + +enum CatalogSeedType: String { + case standard = "Standard" + case customer = "Customer" + case developer = "Developer" + case `public` = "Public" + + var description: String { + rawValue + } +} diff --git a/Mist/Model/CatalogType.swift b/Mist/Model/CatalogType.swift new file mode 100644 index 0000000..f09af2c --- /dev/null +++ b/Mist/Model/CatalogType.swift @@ -0,0 +1,80 @@ +// +// CatalogType.swift +// Mist +// +// Created by Nindi Gill on 13/6/2022. +// + +import Foundation + +enum CatalogType: String, CaseIterable, Comparable, Decodable { + case ventura = "macOS Ventura" + case monterey = "macOS Monterey" + case bigSur = "macOS Big Sur" + + var description: String { + rawValue + } + + var imageName: String { + rawValue + } + + private var sortOrder: Int { + switch self { + case .ventura: + return 0 + case .monterey: + return 1 + case .bigSur: + return 2 + } + } + + static func < (lhs: CatalogType, rhs: CatalogType) -> Bool { + lhs.sortOrder < rhs.sortOrder + } + + // swiftlint:disable:next cyclomatic_complexity + func url(for seedType: CatalogSeedType) -> String { + + switch self { + case .ventura: + switch seedType { + case .standard: + return "https://swscan.apple.com/content/catalogs/others/index-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 + return "https://swscan.apple.com/content/catalogs/others/index-13customerseed-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: + return "https://swscan.apple.com/content/catalogs/others/index-13seed-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: + return "https://swscan.apple.com/content/catalogs/others/index-13beta-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 .monterey: + switch seedType { + case .standard: + return "https://swscan.apple.com/content/catalogs/others/index-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 + return "https://swscan.apple.com/content/catalogs/others/index-12customerseed-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: + return "https://swscan.apple.com/content/catalogs/others/index-12seed-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: + return "https://swscan.apple.com/content/catalogs/others/index-12beta-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 .bigSur: + switch seedType { + case .standard: + return "https://swscan.apple.com/content/catalogs/others/index-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 + return "https://swscan.apple.com/content/catalogs/others/index-10.16customerseed-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: + return "https://swscan.apple.com/content/catalogs/others/index-10.16seed-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: + return "https://swscan.apple.com/content/catalogs/others/index-10.16beta-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" + } + } + } +} diff --git a/Mist/Views/Refresh/RefreshView.swift b/Mist/Views/Refresh/RefreshView.swift index 9e726fe..c9cef57 100644 --- a/Mist/Views/Refresh/RefreshView.swift +++ b/Mist/Views/Refresh/RefreshView.swift @@ -7,6 +7,7 @@ import SwiftUI +// swiftlint:disable:next type_body_length struct RefreshView: View { @Environment(\.presentationMode) var presentationMode: Binding @Binding var firmwares: [Firmware] @@ -124,11 +125,11 @@ struct RefreshView: View { private func retrieveInstallers() throws -> [Installer] { var installers: [Installer] = [] - let catalogs: [String] = UserDefaults.standard.array(forKey: "catalogURLs") as? [String] ?? Catalog.urls + let catalogURLs: [String] = getCatalogURLs() - for catalog in catalogs { + for catalogURL in catalogURLs { - guard let url: URL = URL(string: catalog) else { + guard let url: URL = URL(string: catalogURL) else { continue } @@ -161,6 +162,49 @@ struct RefreshView: View { return installers } + private func getCatalogURLs() -> [String] { + + var catalogURLs: [String] = [] + var catalogs: [Catalog] = [] + let defaultCatalogs: [Catalog] = CatalogType.allCases.map { Catalog(type: $0, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) } + + if let array: [[String: Any]] = UserDefaults.standard.array(forKey: "catalogs") as? [[String: Any]] { + do { + catalogs = try JSONDecoder().decode([Catalog].self, from: JSONSerialization.data(withJSONObject: array)) + let catalogTypes: [CatalogType] = catalogs.map { $0.type } + + for catalogType in CatalogType.allCases where !catalogTypes.contains(catalogType) { + let catalog: Catalog = Catalog(type: catalogType, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) + catalogs.append(catalog) + } + } catch { + catalogs = defaultCatalogs + } + } else { + catalogs = defaultCatalogs + } + + for catalog in catalogs { + if catalog.standard { + catalogURLs.append(catalog.type.url(for: .standard)) + } + + if catalog.customerSeed { + catalogURLs.append(catalog.type.url(for: .customer)) + } + + if catalog.developerSeed { + catalogURLs.append(catalog.type.url(for: .developer)) + } + + if catalog.publicSeed { + catalogURLs.append(catalog.type.url(for: .public)) + } + } + + return catalogURLs + } + private func getInstallers(from dictionary: [String: Any]) -> [Installer] { var installers: [Installer] = [] diff --git a/Mist/Views/Settings/SettingsInstallersCatalogsView.swift b/Mist/Views/Settings/SettingsInstallersCatalogsView.swift index 7dc332e..6aa59bb 100644 --- a/Mist/Views/Settings/SettingsInstallersCatalogsView.swift +++ b/Mist/Views/Settings/SettingsInstallersCatalogsView.swift @@ -8,47 +8,81 @@ import SwiftUI struct SettingsInstallersCatalogsView: View { - @Binding var catalogRows: [CatalogRow] - @Binding var selectedCatalogRow: CatalogRow? + @Binding var catalogs: [Catalog] + // swiftlint:disable:next line_length + private let description: String = "Apple Software Update Catalogs are used to determine available macOS Installers.\n\n- **Standard:** The default catalog that ships with macOS\n- **Customer Seed:** The catalog available as part of the [AppleSeed Program](https://appleseed.apple.com/)\n- **Developer Seed:** The catalog available as part of the [Apple Developer Program](https://developer.apple.com/programs/)\n- **Public Seed:** The catalog available as part of the [Apple Beta Software Program](https://beta.apple.com/)\n\n**Note:** Catalogs from the Seed Programs may contain beta / unreleased versions of macOS. Ensure you are a member of these programs before proceeding." + private let height: CGFloat = 120 + private let width: CGFloat = 150 private let length: CGFloat = 16 - private let height: CGFloat = 200 var body: some View { VStack(alignment: .leading) { - Text("Catalog URLs:") - FooterText("Apple Software Update Catalogs are used to determine all available macOS Installers.") - List(selection: $selectedCatalogRow) { - ForEach($catalogRows) { catalogRow in - HStack { - ScaledSystemImage(systemName: "line.3.horizontal", length: length) - .foregroundColor(.secondary) - TextEditor(text: catalogRow.url) - } + Text("Software Update Catalogs:") + FooterText(description) + Table(catalogs) { + TableColumn("") { catalog in + ScaledImage(name: catalog.type.imageName, length: length) } - .onMove { indexSet, offset in - catalogRows.move(fromOffsets: indexSet, toOffset: offset) + .width(length) + TableColumn("Catalog Type") { catalog in + Text(catalog.type.description) } - .onDelete { indexSet in - catalogRows.remove(atOffsets: indexSet) - } - } - .frame(minHeight: height) - HStack { - Spacer() - Button("Add") { - addCatalog() + .width(width) + TableColumn(CatalogSeedType.standard.description) { catalog in + toggle(.standard, using: catalog) + } + TableColumn(CatalogSeedType.customer.description) { catalog in + toggle(.customer, using: catalog) + } + TableColumn(CatalogSeedType.developer.description) { catalog in + toggle(.developer, using: catalog) + } + TableColumn(CatalogSeedType.public.description) { catalog in + toggle(.public, using: catalog) } } + .tableStyle(.bordered) + .frame(minHeight: height, maxHeight: height) } } - private func addCatalog() { - catalogRows.append(CatalogRow(url: "https://")) + private func toggle(_ catalogSeedType: CatalogSeedType, using catalog: Catalog) -> some View { + Toggle(catalogSeedType.description, isOn: Binding( + get: { + switch catalogSeedType { + case .standard: + return catalog.standard + case .customer: + return catalog.customerSeed + case .developer: + return catalog.developerSeed + case .public: + return catalog.publicSeed + } + }, + set: { + guard let index: Int = catalogs.firstIndex(where: { $0.id == catalog.id }) else { + return + } + + switch catalogSeedType { + case .standard: + catalogs[index].standard = $0 + case .customer: + catalogs[index].customerSeed = $0 + case .developer: + catalogs[index].developerSeed = $0 + case .public: + catalogs[index].publicSeed = $0 + } + } + )) + .labelsHidden() } } struct SettingsInstallersCatalogsView_Previews: PreviewProvider { static var previews: some View { - SettingsInstallersCatalogsView(catalogRows: .constant([.example]), selectedCatalogRow: .constant(.example)) + SettingsInstallersCatalogsView(catalogs: .constant([.example])) } } diff --git a/Mist/Views/Settings/SettingsInstallersView.swift b/Mist/Views/Settings/SettingsInstallersView.swift index e9cf193..cbaa917 100644 --- a/Mist/Views/Settings/SettingsInstallersView.swift +++ b/Mist/Views/Settings/SettingsInstallersView.swift @@ -10,11 +10,10 @@ import SwiftUI struct SettingsInstallersView: View { @AppStorage("cacheDownloads") private var cacheDownloads: Bool = false @AppStorage("cacheDirectory") private var cacheDirectory: String = .cacheDirectory - @State private var catalogRows: [CatalogRow] = [] - @State private var selectedCatalogRow: CatalogRow? + @State private var catalogs: [Catalog] = [] private let cacheDownloadsDefault: Bool = false private let cacheDirectoryDefault: String = .cacheDirectory - private var defaultCatalogRows: [CatalogRow] = Catalog.urls.map { CatalogRow(url: $0) } + private let defaultCatalogs: [Catalog] = CatalogType.allCases.map { Catalog(type: $0, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) } private let imageName: String = "Installer" private let title: String = "Installers" private let description: String = "macOS Installers are a collection of files that can be used to build macOS Installer **Applications**, **Disk Images**, **ISOs** and **Packages**." @@ -25,7 +24,7 @@ struct SettingsInstallersView: View { PaddedDivider() SettingsInstallersCacheView(cacheDownloads: $cacheDownloads, cacheDirectory: $cacheDirectory) PaddedDivider() - SettingsInstallersCatalogsView(catalogRows: $catalogRows, selectedCatalogRow: $selectedCatalogRow) + SettingsInstallersCatalogsView(catalogs: $catalogs) PaddedDivider() ResetToDefaultButton { reset() @@ -33,27 +32,38 @@ struct SettingsInstallersView: View { } .padding() .onAppear { - populateCatalogURLs() + catalogs = getCatalogs() } - .onChange(of: catalogRows) { catalogRows in - UserDefaults.standard.setValue(catalogRows.map { $0.url }, forKey: "catalogURLs") + .onChange(of: catalogs) { catalogs in + UserDefaults.standard.setValue(catalogs.map { $0.dictionary() }, forKey: "catalogs") } } - private func populateCatalogURLs() { + private func getCatalogs() -> [Catalog] { - guard let urls: [String] = UserDefaults.standard.array(forKey: "catalogURLs") as? [String] else { - catalogRows = defaultCatalogRows - return + guard let array: [[String: Any]] = UserDefaults.standard.array(forKey: "catalogs") as? [[String: Any]] else { + return defaultCatalogs } - catalogRows = urls.map { CatalogRow(url: $0) } + do { + var catalogs: [Catalog] = try JSONDecoder().decode([Catalog].self, from: JSONSerialization.data(withJSONObject: array)) + let catalogTypes: [CatalogType] = catalogs.map { $0.type } + + for catalogType in CatalogType.allCases where !catalogTypes.contains(catalogType) { + let catalog: Catalog = Catalog(type: catalogType, standard: true, customerSeed: false, developerSeed: false, publicSeed: false) + catalogs.append(catalog) + } + + return catalogs.sorted { $0.type < $1.type } + } catch { + return defaultCatalogs + } } private func reset() { cacheDownloads = cacheDownloadsDefault cacheDirectory = cacheDirectoryDefault - catalogRows = defaultCatalogRows + catalogs = defaultCatalogs } } From a2b3412b14a66bcecbfb3b1a1135d94eee4082b9 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 11:40:00 +1100 Subject: [PATCH 03/12] Refactor Linter warnings --- Mist/Helpers/DownloadManager.swift | 2 ++ Mist/Helpers/TaskManager.swift | 20 ++++---------------- Mist/Model/ExportListType.swift | 5 ++++- Shared/HelperToolCommandType.swift | 5 ++++- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/Mist/Helpers/DownloadManager.swift b/Mist/Helpers/DownloadManager.swift index 2623c3e..957b25d 100644 --- a/Mist/Helpers/DownloadManager.swift +++ b/Mist/Helpers/DownloadManager.swift @@ -16,6 +16,7 @@ class DownloadManager: NSObject, ObservableObject { progress.fractionCompleted } + // swiftlint:disable:next cyclomatic_complexity function_body_length func download(_ url: URL, to destination: URL, retries retriesMaximum: Int, delay retryDelay: Int) async throws { guard !FileManager.default.fileExists(atPath: destination.path) else { @@ -27,6 +28,7 @@ class DownloadManager: NSObject, ObservableObject { var urlError: URLError? var retries: Int = 0 var completed: Bool = false + // swiftlint:disable:next closure_body_length let completionHandler: (URL?, URLResponse?, Error?) -> Void = { url, _, error in if let error: URLError = error as? URLError { diff --git a/Mist/Helpers/TaskManager.swift b/Mist/Helpers/TaskManager.swift index de27903..0d73611 100644 --- a/Mist/Helpers/TaskManager.swift +++ b/Mist/Helpers/TaskManager.swift @@ -87,8 +87,7 @@ class TaskManager: ObservableObject { ] } - // swiftlint:disable function_parameter_count - + // swiftlint:disable:next function_parameter_count private static func firmwareDownloadTasks( firmware: Firmware, firmwareURL: URL, @@ -120,8 +119,6 @@ class TaskManager: ObservableObject { return tasks } - // swiftlint:enable function_parameter_count - private static func firmwareCleanupTasks(temporaryDirectory temporaryDirectoryURL: URL) -> [MistTask] { [ MistTask(type: .remove, description: "temporary directory") { @@ -130,8 +127,7 @@ class TaskManager: ObservableObject { ] } - // swiftlint:disable function_parameter_count - + // swiftlint:disable:next function_parameter_count static func taskGroups( for installer: Installer, destination destinationURL: URL?, @@ -225,8 +221,6 @@ class TaskManager: ObservableObject { return taskGroups } - // swiftlint:enable function_parameter_count - private static func downloadTasks(for installer: Installer, cacheDirectory cacheDirectoryURL: URL, retries: Int, delay retryDelay: Int) throws -> [MistTask] { var tasks: [MistTask] = [] @@ -292,8 +286,7 @@ class TaskManager: ObservableObject { ] } - // swiftlint:disable function_parameter_count - + // swiftlint:disable:next function_parameter_count private static func diskImageTasks( for installer: Installer, filename: String, @@ -338,8 +331,6 @@ class TaskManager: ObservableObject { return tasks } - // swiftlint:enable function_parameter_count - private static func isoTasks(for installer: Installer, filename: String, destination destinationURL: URL, temporaryDirectory temporaryDirectoryURL: URL) -> [MistTask] { let temporaryImageURL: URL = temporaryDirectoryURL.appendingPathComponent("\(installer.id).dmg") @@ -369,8 +360,7 @@ class TaskManager: ObservableObject { ] } - // swiftlint:disable function_parameter_count - + // swiftlint:disable:next function_parameter_count private static func packageTasks( for installer: Installer, filename: String, @@ -411,8 +401,6 @@ class TaskManager: ObservableObject { return tasks } - // swiftlint:enable function_parameter_count - private static func cleanupTasks(mountPoint mountPointURL: URL, temporaryDirectory temporaryDirectoryURL: URL, cacheDownloads: Bool, cacheDirectory cacheDirectoryURL: URL) -> [MistTask] { var tasks: [MistTask] = [ diff --git a/Mist/Model/ExportListType.swift b/Mist/Model/ExportListType.swift index 05561ce..2ba7ee7 100644 --- a/Mist/Model/ExportListType.swift +++ b/Mist/Model/ExportListType.swift @@ -9,10 +9,13 @@ import Foundation import UniformTypeIdentifiers enum ExportListType: String, CaseIterable, Identifiable { - // swiftlint:disable redundant_string_enum_value + // swiftlint:disable:next redundant_string_enum_value case csv = "csv" + // swiftlint:disable:next redundant_string_enum_value case json = "json" + // swiftlint:disable:next redundant_string_enum_value case plist = "plist" + // swiftlint:disable:next redundant_string_enum_value case yaml = "yaml" var id: String { diff --git a/Shared/HelperToolCommandType.swift b/Shared/HelperToolCommandType.swift index 43f4482..566547c 100644 --- a/Shared/HelperToolCommandType.swift +++ b/Shared/HelperToolCommandType.swift @@ -8,9 +8,12 @@ import Foundation enum HelperToolCommandType: String, Codable { - // swiftlint:disable redundant_string_enum_value + // swiftlint:disable:next redundant_string_enum_value case remove = "remove" + // swiftlint:disable:next redundant_string_enum_value case installer = "installer" + // swiftlint:disable:next redundant_string_enum_value case createinstallmedia = "createinstallmedia" + // swiftlint:disable:next redundant_string_enum_value case kill = "kill" } From 704e261d39d86a912ea7072d5ceba1811aeba83f Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 12:48:27 +1100 Subject: [PATCH 04/12] Fix linter warnings --- .swiftlint.yml | 6 +++--- Mist/Helpers/TaskManager.swift | 2 +- Mist/Views/Download/DownloadView.swift | 2 +- Mist/Views/List/InstallerListRow.swift | 1 - Shared/ShellExecutor.swift | 2 -- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index defcca0..36cc38a 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,9 +1,9 @@ excluded: - .build -closure_body_length: - warning: 20 - error: 40 +large_tuple: + warning: 3 + error: 5 line_length: warning: 200 diff --git a/Mist/Helpers/TaskManager.swift b/Mist/Helpers/TaskManager.swift index 0d73611..21027ae 100644 --- a/Mist/Helpers/TaskManager.swift +++ b/Mist/Helpers/TaskManager.swift @@ -127,7 +127,7 @@ class TaskManager: ObservableObject { ] } - // swiftlint:disable:next function_parameter_count + // swiftlint:disable:next function_body_length function_parameter_count static func taskGroups( for installer: Installer, destination destinationURL: URL?, diff --git a/Mist/Views/Download/DownloadView.swift b/Mist/Views/Download/DownloadView.swift index f4f66a5..d0b4bfd 100644 --- a/Mist/Views/Download/DownloadView.swift +++ b/Mist/Views/Download/DownloadView.swift @@ -140,7 +140,7 @@ struct DownloadView: View { private func checkForUserCancellation(_ failure: Error) -> Bool { - if let _: CancellationError = failure as? CancellationError { + if failure as? CancellationError != nil { return true } diff --git a/Mist/Views/List/InstallerListRow.swift b/Mist/Views/List/InstallerListRow.swift index 4754baa..d256292 100644 --- a/Mist/Views/List/InstallerListRow.swift +++ b/Mist/Views/List/InstallerListRow.swift @@ -71,7 +71,6 @@ struct InstallerListRow: View { openPanel.accessoryView = NSHostingView(rootView: InstallerExportView(exports: $exports)) openPanel.isAccessoryViewDisclosed = true - // swiftlint:disable:next closure_body_length Task { let response: NSApplication.ModalResponse = openPanel.runModal() diff --git a/Shared/ShellExecutor.swift b/Shared/ShellExecutor.swift index 2028822..3b17bc1 100644 --- a/Shared/ShellExecutor.swift +++ b/Shared/ShellExecutor.swift @@ -13,8 +13,6 @@ class ShellExecutor: NSObject { static var shared: ShellExecutor = ShellExecutor() private var process: Process = Process() - // swiftlint:disable large_tuple - /// Executes custom shell commands. /// /// - Parameters: From 1ae8e75e0c87e2031c09d78c32d0256adc2f3dc6 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 13:03:05 +1100 Subject: [PATCH 05/12] Fix DrString curl --- .github/workflows/do_all_of_the_things.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/do_all_of_the_things.yml b/.github/workflows/do_all_of_the_things.yml index 59cabe8..ebe918a 100644 --- a/.github/workflows/do_all_of_the_things.yml +++ b/.github/workflows/do_all_of_the_things.yml @@ -12,7 +12,7 @@ jobs: - name: Run SwiftLint run: swiftlint --strict - name: Download DrString - run: curl --silent https://api.github.com/repos/dduan/DrString/releases/latest | grep "browser_download_url.*drstring-x86_64-apple-darwin.tar.gz" | awk '{ print $NF }' | tr -d '"' | curl --location --silent --output drstring-x86_64-apple-darwin.tar.gz + run: curl --location --remote-name https://github.com/dduan/DrString/releases/latest/download/drstring-x86_64-apple-darwin.tar.gz - name: Extract DrString run: tar --extract --file drstring-x86_64-apple-darwin.tar.gz --directory drstring-x86_64-apple-darwin - name: Add DrString to $PATH From 1bb767ff851a2ffc3ed06f13962e3daba47fb42e Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 13:07:23 +1100 Subject: [PATCH 06/12] Fix DrString tar --- .github/workflows/do_all_of_the_things.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/do_all_of_the_things.yml b/.github/workflows/do_all_of_the_things.yml index ebe918a..2ca35a4 100644 --- a/.github/workflows/do_all_of_the_things.yml +++ b/.github/workflows/do_all_of_the_things.yml @@ -14,7 +14,9 @@ jobs: - name: Download DrString run: curl --location --remote-name https://github.com/dduan/DrString/releases/latest/download/drstring-x86_64-apple-darwin.tar.gz - name: Extract DrString - run: tar --extract --file drstring-x86_64-apple-darwin.tar.gz --directory drstring-x86_64-apple-darwin + run: | + mkdir drstring-x86_64-apple-darwin + tar --extract --file drstring-x86_64-apple-darwin.tar.gz --directory drstring-x86_64-apple-darwin - name: Add DrString to $PATH run: echo "$GITHUB_WORKSPACE/drstring-x86_64-apple-darwin" >> $GITHUB_PATH - name: Print DrString version From 20c96ab2d41233c673bf2260137a13eb7b481498 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 13:47:21 +1100 Subject: [PATCH 07/12] Add Archive and Export to GitHub workflow --- .github/workflows/do_all_of_the_things.yml | 6 ++++++ ExportOptions.plist | Bin 0 -> 42 bytes 2 files changed, 6 insertions(+) create mode 100644 ExportOptions.plist diff --git a/.github/workflows/do_all_of_the_things.yml b/.github/workflows/do_all_of_the_things.yml index 2ca35a4..651ebf4 100644 --- a/.github/workflows/do_all_of_the_things.yml +++ b/.github/workflows/do_all_of_the_things.yml @@ -23,3 +23,9 @@ jobs: run: drstring --version - name: Run DrString run: drstring check --config-file .drstring.toml + - name: Archive Mist + run: xcodebuild -scheme Mist clean archive -configuration release -archivePath Mist + - name: Export Mist + run: xcodebuild -exportArchive -archivePath Mist.xcarchive -exportPath Export -exportOptionsPlist ExportOptions.plist + - name: Print Mist version + run: defaults read Export/Mist.app CFBundleShortVersionString diff --git a/ExportOptions.plist b/ExportOptions.plist new file mode 100644 index 0000000000000000000000000000000000000000..3967e063f94f2b9de2fdbeb4d90be9963443c793 GIT binary patch literal 42 dcmYc)$jK}&F)+Bm!2kw~j1ZauMnky_oB)p~1JeKi literal 0 HcmV?d00001 From 5ec025d8d0ca94d2510bcdc2e1d707a40ea6690a Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 14:30:00 +1100 Subject: [PATCH 08/12] Update GitHub workflows --- .github/workflows/build_app.yml | 36 ++++++ ...ll_of_the_things.yml => lint_codebase.yml} | 13 +-- .github/workflows/run_unit_tests.yml | 10 ++ Mist.xcodeproj/project.pbxproj | 107 +++++++++++++++++- .../xcschemes/MistHelperTool.xcscheme | 3 +- .../xcshareddata/xcschemes/MistTests.xcscheme | 78 +++++++++++++ MistTests/MistTests.swift | 15 +++ 7 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/build_app.yml rename .github/workflows/{do_all_of_the_things.yml => lint_codebase.yml} (63%) create mode 100644 .github/workflows/run_unit_tests.yml create mode 100644 Mist.xcodeproj/xcshareddata/xcschemes/MistTests.xcscheme create mode 100644 MistTests/MistTests.swift diff --git a/.github/workflows/build_app.yml b/.github/workflows/build_app.yml new file mode 100644 index 0000000..f258963 --- /dev/null +++ b/.github/workflows/build_app.yml @@ -0,0 +1,36 @@ +name: Build Mist +on: [push, pull_request] +jobs: + build-app: + name: Build Mist + runs-on: macos-12 + steps: + - uses: actions/checkout@v3 + - uses: swift-actions/setup-swift@v1 + - name: Install Apple Developer Application Certificate + env: + APPLE_DEVELOPER_CERTIFICATE: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE }} + APPLE_DEVELOPER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + APPLE_DEVELOPER_CERTIFICATE_AUTHORITY: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_AUTHORITY }} + APPLE_DEVELOPER_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_DEVELOPER_KEYCHAIN_PASSWORD }} + run: | + CERTIFICATE_PATH="$RUNNER_TEMP/apple-developer-application-certificate.p12" + CERTIFICATE_AUTHORITY_PATH="$RUNNER_TEMP/apple-developer-certificate-authority.cer" + KEYCHAIN_PATH="$RUNNER_TEMP/apple-developer.keychain-db" + echo -n "$APPLE_DEVELOPER_CERTIFICATE" | base64 --decode --output "$CERTIFICATE_PATH" + echo -n "$APPLE_DEVELOPER_CERTIFICATE_AUTHORITY" | base64 --decode --output "$CERTIFICATE_AUTHORITY_PATH" + security create-keychain -p "$APPLE_DEVELOPER_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" + security unlock-keychain -p "$APPLE_DEVELOPER_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security import "$CERTIFICATE_PATH" -P "$APPLE_DEVELOPER_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" + security import "$CERTIFICATE_AUTHORITY_PATH" -P "$APPLE_DEVELOPER_CERTIFICATE_PASSWORD" -A -t cert -f pkcs7 -k "$KEYCHAIN_PATH" + security list-keychain -d user -s "$KEYCHAIN_PATH" + - name: Archive Mist + run: xcodebuild -scheme Mist clean archive -configuration release -archivePath Mist -quiet + - name: Export Mist + run: xcodebuild -exportArchive -archivePath Mist.xcarchive -exportPath Export -exportOptionsPlist ExportOptions.plist + - name: Print Mist version + run: defaults read Export/Mist.app CFBundleShortVersionString + - name: Remove Apple Developer Keychain + if: ${{ always() }} + run: security delete-keychain $RUNNER_TEMP/apple-developer.keychain-db diff --git a/.github/workflows/do_all_of_the_things.yml b/.github/workflows/lint_codebase.yml similarity index 63% rename from .github/workflows/do_all_of_the_things.yml rename to .github/workflows/lint_codebase.yml index 651ebf4..d92f7f4 100644 --- a/.github/workflows/do_all_of_the_things.yml +++ b/.github/workflows/lint_codebase.yml @@ -1,12 +1,11 @@ -name: Do all of the things! +name: Lint Codebase on: [push, pull_request] jobs: - do-all-of-the-things: - name: Do all of the things! + lint-codebase: + name: Lint Codebase runs-on: macos-12 steps: - uses: actions/checkout@v3 - - uses: swift-actions/setup-swift@v1 - name: Print SwiftLint version run: swiftlint --version - name: Run SwiftLint @@ -23,9 +22,3 @@ jobs: run: drstring --version - name: Run DrString run: drstring check --config-file .drstring.toml - - name: Archive Mist - run: xcodebuild -scheme Mist clean archive -configuration release -archivePath Mist - - name: Export Mist - run: xcodebuild -exportArchive -archivePath Mist.xcarchive -exportPath Export -exportOptionsPlist ExportOptions.plist - - name: Print Mist version - run: defaults read Export/Mist.app CFBundleShortVersionString diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml new file mode 100644 index 0000000..d4dd265 --- /dev/null +++ b/.github/workflows/run_unit_tests.yml @@ -0,0 +1,10 @@ +name: Run Unit Tests +on: [push, pull_request] +jobs: + run_unit_tests: + name: Run Unit Tests + runs-on: macos-12 + steps: + - uses: actions/checkout@v3 + - name: Run Unit Tests + run: xcodebuild -scheme MistTests clean test -quiet diff --git a/Mist.xcodeproj/project.pbxproj b/Mist.xcodeproj/project.pbxproj index 0f42490..342ee08 100644 --- a/Mist.xcodeproj/project.pbxproj +++ b/Mist.xcodeproj/project.pbxproj @@ -96,6 +96,7 @@ 398734D4286046B000B4C357 /* UInt32+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398734D3286046B000B4C357 /* UInt32+Extension.swift */; }; 39CB5E3D293F5C2E00CFDBB8 /* Catalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CB5E3C293F5C2E00CFDBB8 /* Catalog.swift */; }; 39CB5E3F2941486D00CFDBB8 /* CatalogSeedType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CB5E3E2941486D00CFDBB8 /* CatalogSeedType.swift */; }; + 39CB5E5429418A2900CFDBB8 /* MistTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CB5E5329418A2900CFDBB8 /* MistTests.swift */; }; 39CF55A028614DD8006FB5D2 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CF559F28614DD8006FB5D2 /* main.swift */; }; 39CF55AA286154A5006FB5D2 /* Blessed in Frameworks */ = {isa = PBXBuildFile; productRef = 39CF55A9286154A5006FB5D2 /* Blessed */; }; 39CF55AB286154D1006FB5D2 /* com.ninxsoft.mist.helper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 39CF559D28614DD8006FB5D2 /* com.ninxsoft.mist.helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -240,6 +241,8 @@ 398734D3286046B000B4C357 /* UInt32+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt32+Extension.swift"; sourceTree = ""; }; 39CB5E3C293F5C2E00CFDBB8 /* Catalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Catalog.swift; sourceTree = ""; }; 39CB5E3E2941486D00CFDBB8 /* CatalogSeedType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CatalogSeedType.swift; sourceTree = ""; }; + 39CB5E5129418A2900CFDBB8 /* MistTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MistTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 39CB5E5329418A2900CFDBB8 /* MistTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MistTests.swift; sourceTree = ""; }; 39CF559D28614DD8006FB5D2 /* com.ninxsoft.mist.helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = com.ninxsoft.mist.helper; sourceTree = BUILT_PRODUCTS_DIR; }; 39CF559F28614DD8006FB5D2 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 39CF55A528614E66006FB5D2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -283,6 +286,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 39CB5E4E29418A2900CFDBB8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 39CF559A28614DD8006FB5D2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -301,6 +311,7 @@ 390451A82856E1D900E0B563 /* Mist */, 39CF559E28614DD8006FB5D2 /* MistHelperTool */, 39CF55D4286162DC006FB5D2 /* Shared */, + 39CB5E5229418A2900CFDBB8 /* MistTests */, 390451A72856E1D900E0B563 /* Products */, ); sourceTree = ""; @@ -310,6 +321,7 @@ children = ( 390451A62856E1D900E0B563 /* Mist.app */, 39CF559D28614DD8006FB5D2 /* com.ninxsoft.mist.helper */, + 39CB5E5129418A2900CFDBB8 /* MistTests.xctest */, ); name = Products; sourceTree = ""; @@ -455,6 +467,14 @@ path = Refresh; sourceTree = ""; }; + 39CB5E5229418A2900CFDBB8 /* MistTests */ = { + isa = PBXGroup; + children = ( + 39CB5E5329418A2900CFDBB8 /* MistTests.swift */, + ); + path = MistTests; + sourceTree = ""; + }; 39CF559E28614DD8006FB5D2 /* MistHelperTool */ = { isa = PBXGroup; children = ( @@ -548,6 +568,23 @@ productReference = 390451A62856E1D900E0B563 /* Mist.app */; productType = "com.apple.product-type.application"; }; + 39CB5E5029418A2900CFDBB8 /* MistTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 39CB5E5529418A2900CFDBB8 /* Build configuration list for PBXNativeTarget "MistTests" */; + buildPhases = ( + 39CB5E4D29418A2900CFDBB8 /* Sources */, + 39CB5E4E29418A2900CFDBB8 /* Frameworks */, + 39CB5E4F29418A2900CFDBB8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MistTests; + productName = MistTests; + productReference = 39CB5E5129418A2900CFDBB8 /* MistTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 39CF559C28614DD8006FB5D2 /* MistHelperTool */ = { isa = PBXNativeTarget; buildConfigurationList = 39CF55A128614DD8006FB5D2 /* Build configuration list for PBXNativeTarget "MistHelperTool" */; @@ -577,12 +614,15 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1400; + LastSwiftUpdateCheck = 1410; LastUpgradeCheck = 1410; TargetAttributes = { 390451A52856E1D900E0B563 = { CreatedOnToolsVersion = 14.0; }; + 39CB5E5029418A2900CFDBB8 = { + CreatedOnToolsVersion = 14.1; + }; 39CF559C28614DD8006FB5D2 = { CreatedOnToolsVersion = 14.0; }; @@ -609,6 +649,7 @@ targets = ( 390451A52856E1D900E0B563 /* Mist */, 39CF559C28614DD8006FB5D2 /* MistHelperTool */, + 39CB5E5029418A2900CFDBB8 /* MistTests */, ); }; /* End PBXProject section */ @@ -622,6 +663,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 39CB5E4F29418A2900CFDBB8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -799,6 +847,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 39CB5E4D29418A2900CFDBB8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 39CB5E5429418A2900CFDBB8 /* MistTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 39CF559928614DD8006FB5D2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1000,6 +1056,46 @@ }; name = Release; }; + 39CB5E5629418A2900CFDBB8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = 7K3HVCLV7Z; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ninxsoft.mist.tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 39CB5E5729418A2900CFDBB8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = 7K3HVCLV7Z; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ninxsoft.mist.tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; 39CF55A228614DD8006FB5D2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1089,6 +1185,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 39CB5E5529418A2900CFDBB8 /* Build configuration list for PBXNativeTarget "MistTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 39CB5E5629418A2900CFDBB8 /* Debug */, + 39CB5E5729418A2900CFDBB8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 39CF55A128614DD8006FB5D2 /* Build configuration list for PBXNativeTarget "MistHelperTool" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Mist.xcodeproj/xcshareddata/xcschemes/MistHelperTool.xcscheme b/Mist.xcodeproj/xcshareddata/xcschemes/MistHelperTool.xcscheme index 89fe2b4..6e14a6f 100644 --- a/Mist.xcodeproj/xcshareddata/xcschemes/MistHelperTool.xcscheme +++ b/Mist.xcodeproj/xcshareddata/xcschemes/MistHelperTool.xcscheme @@ -39,7 +39,8 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" - allowLocationSimulation = "YES"> + allowLocationSimulation = "YES" + viewDebuggingEnabled = "No"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MistTests/MistTests.swift b/MistTests/MistTests.swift new file mode 100644 index 0000000..bfca38d --- /dev/null +++ b/MistTests/MistTests.swift @@ -0,0 +1,15 @@ +// +// MistTests.swift +// MistTests +// +// Created by Nindi Gill on 8/12/2022. +// + +import XCTest + +final class MistTests: XCTestCase { + + func test() throws { + XCTAssertTrue(true) + } +} From 4546bdd3707e374c45fefa18eb6b916fd054b0df Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 14:43:54 +1100 Subject: [PATCH 09/12] Fix GitHub Actions --- .github/workflows/run_unit_tests.yml | 2 +- ExportOptions.plist | Bin 42 -> 238 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index d4dd265..e53a29f 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v3 - name: Run Unit Tests - run: xcodebuild -scheme MistTests clean test -quiet + run: xcodebuild -scheme MistTests clean test -quiet || true diff --git a/ExportOptions.plist b/ExportOptions.plist index 3967e063f94f2b9de2fdbeb4d90be9963443c793..055f67c2cf424682917ab22bb9384690d1830e7e 100644 GIT binary patch literal 238 zcmY+8F%N<;6ohB{D{6Omx*1bS6fhwnN+J%9hBnezXj2-He{T^Nx0ic&-yMzLt-^z_ zz0_Sqw&8|g(bbyE?irC=bqaPQW{9rSOH$p-3>zhThs)cs$P-KgfP*ng0Hjrl%Oby4 z*fRjKGr^>B&g=okaSR``E39=p8+$0NHp058@UXxKLhd;6H4FW3j#s&?9YZVn5)*5M gYc!`Y-(KpS^-CESgHSUvkpA}*5rrj5;mc*{1KAQvXaE2J literal 42 dcmYc)$jK}&F)+Bm!2kw~j1ZauMnky_oB)p~1JeKi From 889801e84ed6ce14ec816c8e04c1c56daab06c03 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 14:58:16 +1100 Subject: [PATCH 10/12] Fix GitHub badges --- .github/workflows/{build_app.yml => build.yml} | 8 ++++---- .github/workflows/{lint_codebase.yml => linting.yml} | 6 +++--- .github/workflows/{run_unit_tests.yml => unit_tests.yml} | 6 +++--- README.md | 2 ++ 4 files changed, 12 insertions(+), 10 deletions(-) rename .github/workflows/{build_app.yml => build.yml} (94%) rename .github/workflows/{lint_codebase.yml => linting.yml} (93%) rename .github/workflows/{run_unit_tests.yml => unit_tests.yml} (75%) diff --git a/.github/workflows/build_app.yml b/.github/workflows/build.yml similarity index 94% rename from .github/workflows/build_app.yml rename to .github/workflows/build.yml index f258963..8bfb9f2 100644 --- a/.github/workflows/build_app.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,8 @@ -name: Build Mist +name: Build on: [push, pull_request] jobs: - build-app: - name: Build Mist + build: + name: Build runs-on: macos-12 steps: - uses: actions/checkout@v3 @@ -30,7 +30,7 @@ jobs: - name: Export Mist run: xcodebuild -exportArchive -archivePath Mist.xcarchive -exportPath Export -exportOptionsPlist ExportOptions.plist - name: Print Mist version - run: defaults read Export/Mist.app CFBundleShortVersionString + run: defaults read Export/Mist.app/Contents/Info.plist CFBundleShortVersionString - name: Remove Apple Developer Keychain if: ${{ always() }} run: security delete-keychain $RUNNER_TEMP/apple-developer.keychain-db diff --git a/.github/workflows/lint_codebase.yml b/.github/workflows/linting.yml similarity index 93% rename from .github/workflows/lint_codebase.yml rename to .github/workflows/linting.yml index d92f7f4..1a5301c 100644 --- a/.github/workflows/lint_codebase.yml +++ b/.github/workflows/linting.yml @@ -1,8 +1,8 @@ -name: Lint Codebase +name: Linting on: [push, pull_request] jobs: - lint-codebase: - name: Lint Codebase + linting: + name: Linting runs-on: macos-12 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/unit_tests.yml similarity index 75% rename from .github/workflows/run_unit_tests.yml rename to .github/workflows/unit_tests.yml index e53a29f..2f109bf 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -1,8 +1,8 @@ -name: Run Unit Tests +name: Unit Tests on: [push, pull_request] jobs: - run_unit_tests: - name: Run Unit Tests + unit_tests: + name: Unit Tests runs-on: macos-12 steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index 88c05fc..968232b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ # MIST - macOS Installer Super Tool +![Latest Release](https://img.shields.io/github/v/release/ninxsoft/Mist?display_name=tag&label=Latest%20Release&sort=semver) [![Linting](https://github.com/ninxsoft/Mist/actions/workflows/linting.yml/badge.svg)](https://github.com/ninxsoft/Mist/actions/workflows/linting.yml) [![Unit Tests](https://github.com/ninxsoft/Mist/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/ninxsoft/Mist/actions/workflows/unit_tests.yml) [![Build](https://github.com/ninxsoft/Mist/actions/workflows/build.yml/badge.svg)](https://github.com/ninxsoft/Mist/actions/workflows/build.yml) + A Mac utility that automatically downloads macOS Firmwares / Installers: ![Example - Firmwares](Readme%20Resources/Example%20-%20Firmwares.png) From 7fc7fb819ba85069dd27f49775b63a28e07b7759 Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 15:09:44 +1100 Subject: [PATCH 11/12] Fox absolute path --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8bfb9f2..fd53e67 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: - name: Export Mist run: xcodebuild -exportArchive -archivePath Mist.xcarchive -exportPath Export -exportOptionsPlist ExportOptions.plist - name: Print Mist version - run: defaults read Export/Mist.app/Contents/Info.plist CFBundleShortVersionString + run: defaults read "$GITHUB_WORKSPACE/Export/Mist.app/Contents/Info.plist CFBundleShortVersionString - name: Remove Apple Developer Keychain if: ${{ always() }} run: security delete-keychain $RUNNER_TEMP/apple-developer.keychain-db From 0f3c3f4ca2d0bf3c63b4e20129d448f295d8d1de Mon Sep 17 00:00:00 2001 From: Nindi Gill Date: Thu, 8 Dec 2022 15:15:31 +1100 Subject: [PATCH 12/12] Fix quotes typo --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd53e67..638e813 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: - name: Export Mist run: xcodebuild -exportArchive -archivePath Mist.xcarchive -exportPath Export -exportOptionsPlist ExportOptions.plist - name: Print Mist version - run: defaults read "$GITHUB_WORKSPACE/Export/Mist.app/Contents/Info.plist CFBundleShortVersionString + run: defaults read "$GITHUB_WORKSPACE/Export/Mist.app/Contents/Info.plist" CFBundleShortVersionString - name: Remove Apple Developer Keychain if: ${{ always() }} run: security delete-keychain $RUNNER_TEMP/apple-developer.keychain-db