From 7ca67cfe760f440b9b423651ef286217ad21c4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Bures=CC=8C?= Date: Tue, 28 Oct 2025 20:22:15 +0100 Subject: [PATCH] Fuck off --- .../Brewfile/Brewfile Import Stage.swift | 13 -- Cork/Enums/Licensing/Licensing State.swift | 18 --- Cork/Errors/Package Loading Error.swift | 61 ------- .../Load Up Installed Packages.swift | 4 - .../Packages/Get Adoptable Packages.swift | 98 ----------- Cork/Models/Application/Application.swift | 141 ---------------- Cork/Models/Corrupted Package.swift | 14 -- Cork/Models/Terminal Output.swift | 20 --- Cork/Views/Reusables/App Icon Display.swift | 1 + .../Cork_CorkPackagesLogic-Info.plist | 22 +++ .../Cork_CorkPackagesModels-Info.plist | 22 +++ Derived/InfoPlists/Cork_CorkShared-Info.plist | 22 +++ .../TuistAssets+CorkPackagesLogic.swift | 153 ++++++++++++++++++ .../TuistAssets+CorkPackagesModels.swift | 153 ++++++++++++++++++ Derived/Sources/TuistAssets+CorkShared.swift | 153 ++++++++++++++++++ .../TuistBundle+CorkPackagesLogic.swift | 64 ++++++++ .../TuistBundle+CorkPackagesModels.swift | 64 ++++++++ Derived/Sources/TuistBundle+CorkShared.swift | 64 ++++++++ Modules/Intents/intent.swift | 0 ... Package was Installed Intentionally.swift | 8 +- .../Packages/PackagesModels}/App State.swift | 14 +- .../Enums/Alerts}/Displayable Alerts.swift | 2 +- .../Displayable Alerts - Descriptions.swift | 2 +- ...ayable Alerts - Recovery Suggestions.swift | 2 +- .../Enums/Brewfile import Stage.swift | 13 ++ .../Confirmation Dialog.swift | 10 +- .../Enums/Sheets/Displayable Sheet.swift | 10 +- .../Errors/Package Loading Error.swift | 77 +++++++++ .../Models/App Adoption/Adoptable App.swift | 65 ++++++++ .../App Adoption/Excluded Adptable App.swift | 58 +++++++ .../PackagesModels/Models/Application.swift | 8 + .../PackagesModels/Models/Brew Package.swift | 20 ++- .../PackagesModels}/Models/Brew Tap.swift | 6 +- .../Models/Corrupted Package.swift | 14 ++ .../Intents/Minimal Homebrew Package.swift | 2 +- .../Models}/Outdated Package.swift | 15 +- .../Required Logic}/Apply Pinned Status.swift | 0 .../Get Names of Pinned Packages.swift | 7 +- .../Get Package Name from URL.swift | 6 +- .../Trackers/Brew Packages Tracker.swift | 7 +- .../Logic}/Check if URL is Symlink.swift | 5 +- .../Shared/Logic/Filter Out Symlinks.swift | 6 +- .../Shared/Logic}/REGEX Match.swift | 8 +- .../Logic/Shell Commands.swift | 10 +- .../Models/Terminal Output.swift | 20 +++ Project.swift | 104 +++++++++++- Tuist/Package.resolved | 18 +++ Tuist/Package.swift | 2 + 48 files changed, 1175 insertions(+), 431 deletions(-) delete mode 100644 Cork/Enums/Brewfile/Brewfile Import Stage.swift delete mode 100644 Cork/Enums/Licensing/Licensing State.swift delete mode 100644 Cork/Models/Application/Application.swift delete mode 100644 Cork/Models/Corrupted Package.swift delete mode 100644 Cork/Models/Terminal Output.swift create mode 100644 Derived/InfoPlists/Cork_CorkPackagesLogic-Info.plist create mode 100644 Derived/InfoPlists/Cork_CorkPackagesModels-Info.plist create mode 100644 Derived/InfoPlists/Cork_CorkShared-Info.plist create mode 100644 Derived/Sources/TuistAssets+CorkPackagesLogic.swift create mode 100644 Derived/Sources/TuistAssets+CorkPackagesModels.swift create mode 100644 Derived/Sources/TuistAssets+CorkShared.swift create mode 100644 Derived/Sources/TuistBundle+CorkPackagesLogic.swift create mode 100644 Derived/Sources/TuistBundle+CorkPackagesModels.swift create mode 100644 Derived/Sources/TuistBundle+CorkShared.swift create mode 100644 Modules/Intents/intent.swift rename Cork/Logic/Package Loading/Helper Logic/Check if Package Was Installed Intentionally.swift => Modules/Packages/PackagesLogic/Logic/Check if Package was Installed Intentionally.swift (96%) rename {Cork => Modules/Packages/PackagesModels}/App State.swift (96%) rename {Cork/Enums/Alerts/Main Window => Modules/Packages/PackagesModels/Enums/Alerts}/Displayable Alerts.swift (97%) rename {Cork/Enums/Alerts/Main Window => Modules/Packages/PackagesModels/Enums/Alerts}/Error Details/Displayable Alerts - Descriptions.swift (99%) rename {Cork/Enums/Alerts/Main Window => Modules/Packages/PackagesModels/Enums/Alerts}/Error Details/Displayable Alerts - Recovery Suggestions.swift (99%) create mode 100644 Modules/Packages/PackagesModels/Enums/Brewfile import Stage.swift rename Cork/Enums/Confirmation Dialogs/Main Window/Confirmation Dialog - Main Window.swift => Modules/Packages/PackagesModels/Enums/Confirmation dialogs/Confirmation Dialog.swift (78%) rename Cork/Enums/Sheets/Main Window/Sheets - Main Window.swift => Modules/Packages/PackagesModels/Enums/Sheets/Displayable Sheet.swift (70%) create mode 100644 Modules/Packages/PackagesModels/Errors/Package Loading Error.swift create mode 100644 Modules/Packages/PackagesModels/Models/App Adoption/Adoptable App.swift create mode 100644 Modules/Packages/PackagesModels/Models/App Adoption/Excluded Adptable App.swift create mode 100644 Modules/Packages/PackagesModels/Models/Application.swift rename {Cork => Modules/Packages/PackagesModels}/Models/Brew Tap.swift (62%) create mode 100644 Modules/Packages/PackagesModels/Models/Corrupted Package.swift rename {Cork => Modules/Packages/PackagesModels}/Models/Intents/Minimal Homebrew Package.swift (96%) rename {Cork/Models/Outdated Packages => Modules/Packages/PackagesModels/Models}/Outdated Package.swift (73%) rename {Cork/Logic/Pinning => Modules/Packages/PackagesModels/Required Logic}/Apply Pinned Status.swift (100%) rename {Cork/Logic/Pinning => Modules/Packages/PackagesModels/Required Logic}/Get Names of Pinned Packages.swift (91%) rename Cork/Extensions/URL - Package Name from URL.swift => Modules/Packages/PackagesModels/Required Logic/Get Package Name from URL.swift (55%) rename {Cork/Logic/File System/File Browser/Misc => Modules/Shared/Logic}/Check if URL is Symlink.swift (86%) rename Cork/Logic/Package Loading/Helper Logic/Filter Symlinks.swift => Modules/Shared/Logic/Filter Out Symlinks.swift (85%) rename {Cork/Logic/Helpers => Modules/Shared/Logic}/REGEX Match.swift (83%) rename Cork/Logic/Shell/Shell Interface.swift => Modules/TerminalSupport/Logic/Shell Commands.swift (98%) create mode 100644 Modules/TerminalSupport/Models/Terminal Output.swift diff --git a/Cork/Enums/Brewfile/Brewfile Import Stage.swift b/Cork/Enums/Brewfile/Brewfile Import Stage.swift deleted file mode 100644 index 25ad52df..00000000 --- a/Cork/Enums/Brewfile/Brewfile Import Stage.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// Brewfile Import Stage.swift -// Cork -// -// Created by David Bureš on 11.11.2023. -// - -import Foundation - -enum BrewfileImportStage -{ - case importing, finished -} diff --git a/Cork/Enums/Licensing/Licensing State.swift b/Cork/Enums/Licensing/Licensing State.swift deleted file mode 100644 index e35144b0..00000000 --- a/Cork/Enums/Licensing/Licensing State.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// Licensing State.swift -// Cork -// -// Created by David Bureš on 18.03.2024. -// - -import Foundation - -enum LicensingState -{ - case notBoughtOrHasNotActivatedDemo - - case demo - case bought - - case selfCompiled -} diff --git a/Cork/Errors/Package Loading Error.swift b/Cork/Errors/Package Loading Error.swift index 274430be..a77fd06b 100644 --- a/Cork/Errors/Package Loading Error.swift +++ b/Cork/Errors/Package Loading Error.swift @@ -7,64 +7,3 @@ import Foundation -/// Error representing failures while loading -enum PackageLoadingError: LocalizedError, Hashable, Identifiable -{ - /// Tried to treat the folder `Cellar` or `Caskroom` itself as a package - means Homebrew itself is broken - case triedToThreatFolderContainingPackagesAsPackage(packageType: BrewPackage.PackageType) - - /// The `Cellar` and `Caskroom` folder itself couldn't be loaded - case couldNotReadContentsOfParentFolder(failureReason: String, folderURL: URL) - - /// Failed while trying to read contents of package folder - case failedWhileReadingContentsOfPackageFolder(folderURL: URL, reportedError: String) - - case failedWhileTryingToDetermineIntentionalInstallation(folderURL: URL, associatedIntentionalDiscoveryError: IntentionalInstallationDiscoveryError) - - /// The package root folder exists, but the package itself doesn't have any versions - case packageDoesNotHaveAnyVersionsInstalled(packageURL: URL) - - /// A folder that should have contained the package is not actually a folder - case packageIsNotAFolder(String, packageURL: URL) - - /// The number of loaded packages does not match the number of package parent folders - case numberOLoadedPackagesDosNotMatchNumberOfPackageFolders - - var errorDescription: String? - { - switch self - { - case .couldNotReadContentsOfParentFolder(let failureReason, _): - return String(localized: "error.package-loading.could-not-read-contents-of-parent-folder.\(failureReason)") - - case .triedToThreatFolderContainingPackagesAsPackage(let packageType): - switch packageType - { - case .formula: - return "error.package-loading.last-path-component-of-checked-package-url-is-folder-containing-packages-itself.formulae" - case .cask: - return "error.package-loading.last-path-component-of-checked-package-url-is-folder-containing-packages-itself.casks" - } - - case .failedWhileReadingContentsOfPackageFolder(let folderURL, let reportedError): - return String(localized: "error.package-loading.could-not-load-\(folderURL.packageNameFromURL())-at-\(folderURL.absoluteString)-because-\(reportedError)", comment: "Couldn't load package (package name) at (package URL) because (failure reason)") - - case .failedWhileTryingToDetermineIntentionalInstallation(_, let associatedIntentionalDiscoveryError): - return associatedIntentionalDiscoveryError.localizedDescription - - case .packageDoesNotHaveAnyVersionsInstalled(let packageURL): - return String(localized: "error.package-loading.\(packageURL.packageNameFromURL())-does-not-have-any-versions-installed") - - case .packageIsNotAFolder(let string, _): - return String(localized: "error.package-loading.\(string)-not-a-folder", comment: "Package folder in this context means a folder that encloses package versions. Every package has its own folder, and this error occurs when the provided URL does not point to a folder that encloses package versions") - - case .numberOLoadedPackagesDosNotMatchNumberOfPackageFolders: - return String(localized: "error.package-loading.number-of-loaded-poackages-does-not-match-number-of-package-folders", comment: "This error occurs when there's a mismatch between the number of loaded packages, and the number of package folders in the package folders") - } - } - - var id: UUID - { - return UUID() - } -} diff --git a/Cork/Logic/Package Loading/Load Up Installed Packages.swift b/Cork/Logic/Package Loading/Load Up Installed Packages.swift index a85e216c..c6f44ada 100644 --- a/Cork/Logic/Package Loading/Load Up Installed Packages.swift +++ b/Cork/Logic/Package Loading/Load Up Installed Packages.swift @@ -8,10 +8,6 @@ import CorkShared import Foundation -/// A representation of the loaded ``BrewPackage``s -/// Includes packages that were loaded properly, along those whose loading failed -typealias BrewPackages = Set> - extension BrewPackagesTracker { /// Parent function for loading installed packages from disk diff --git a/Cork/Logic/Packages/Get Adoptable Packages.swift b/Cork/Logic/Packages/Get Adoptable Packages.swift index 959c1e61..71ca00d0 100644 --- a/Cork/Logic/Packages/Get Adoptable Packages.swift +++ b/Cork/Logic/Packages/Get Adoptable Packages.swift @@ -119,104 +119,6 @@ extension BrewPackagesTracker throw .failedToParseJson(error: casksJsonParsingError.localizedDescription) } } - - /// A struct for holding a Cask's name and its executable - struct AdoptableApp: Identifiable, Hashable, Sendable - { - let id: UUID = .init() - - let caskName: String - let appExecutable: String - - let description: String? - - let fullAppUrl: URL - - var isMarkedForAdoption: Bool - - var app: Application? - - init(caskName: String, description: String?, appExecutable: String) - { - self.caskName = caskName - self.appExecutable = appExecutable - - self.description = description - - self.fullAppUrl = URL.applicationDirectory.appendingPathComponent(appExecutable, conformingTo: .application) - - self.isMarkedForAdoption = true - } - - mutating func changeMarkedState() - { - self.isMarkedForAdoption.toggle() - } - - func constructAppBundle() async -> Application? - { - return try? .init(from: self.fullAppUrl) - } - - func excludeSelf() async - { - let excludedAppRepresentation: BrewPackagesTracker.ExcludedAdoptableApp = .init(fromAdoptableApp: self) - - await excludedAppRepresentation.saveSelfToDatabase() - } - - func includeSelf() async - { - let excludedAppRepresentation: BrewPackagesTracker.ExcludedAdoptableApp = .init(fromAdoptableApp: self) - - await excludedAppRepresentation.deleteSelfFromDatabase() - } - } - - @Model - final class ExcludedAdoptableApp - { - @Attribute(.unique) @Attribute(.spotlight) - var appExecutable: String - - init(appExecutable: String) - { - self.appExecutable = appExecutable - } - - init(fromAdoptableApp app: BrewPackagesTracker.AdoptableApp) - { - self.appExecutable = app.appExecutable - } - - @MainActor - public func saveSelfToDatabase() - { - AppConstants.shared.modelContainer.mainContext.insert(self) - } - - @MainActor - public func deleteSelfFromDatabase() - { - let modelContext: ModelContext = AppConstants.shared.modelContainer.mainContext - - do - { - let descriptor = FetchDescriptor( - predicate: #Predicate { $0.appExecutable == appExecutable } - ) - - if let existingPackage = try modelContext.fetch(descriptor).first - { - modelContext.delete(existingPackage) - } - } - catch - { - AppConstants.shared.logger.error("Failed to fetch excluded adoptable app for deletion: \(error.localizedDescription)") - } - } - } /// Take the array that contains all Casks, and transform them into a list of Cask names, associated with their executable names for comparing with the contents of the Applications folder private nonisolated diff --git a/Cork/Models/Application/Application.swift b/Cork/Models/Application/Application.swift deleted file mode 100644 index 11cd52b2..00000000 --- a/Cork/Models/Application/Application.swift +++ /dev/null @@ -1,141 +0,0 @@ -// -// Application.swift -// Cork -// -// Created by David Bureš - P on 07.10.2025. -// - -import Foundation -import SwiftUI -import CorkShared - -// TODO: Move this over to the `ApplicationInspector` external library once we figure out how to use Tuist projects as external dependencies - -public struct Application: Identifiable, Hashable, Sendable -{ - public let id: UUID = .init() - - public let name: String - - public let url: URL - - public let iconPath: URL? - - public let iconImage: Image? - - public static func == (lhs: Application, rhs: Application) -> Bool - { - lhs.id == rhs.id - } - - public func hash(into hasher: inout Hasher) - { - hasher.combine(name) - hasher.combine(id) - } - - public enum ApplicationInitializationError: LocalizedError - { - public enum MandatoryAppInformation: String, Sendable - { - case name - - public var description: String - { - switch self { - case .name: - return "Name" - } - } - } - - case applicationExecutableNotReadable(checkedPath: String) - case couldNotAccessApplicationExecutable(error: Error) - case couldNotReadBundle(applicationPath: String) - case couldNotGetInfoDictionary - case couldNotGetMandatoryAppInformation(_ mandatoryInformation: MandatoryAppInformation) - - public var errorDescription: String? - { - switch self { - case .applicationExecutableNotReadable(let checkedPath): - return "Couldn't read application executable at \(checkedPath)" - case .couldNotAccessApplicationExecutable(let error): - return "Couldn't read application executable: \(error)" - case .couldNotReadBundle(let applicationPath): - return "Couldn't read application bundle at \(applicationPath)" - case .couldNotGetInfoDictionary: - return "Couldn't read application info.plist" - case .couldNotGetMandatoryAppInformation(let mandatoryInformation): - return "Couldn't read mandatory app information: \(mandatoryInformation.description)" - } - } - } - - public init(from appURL: URL) throws(ApplicationInitializationError) - { - do - { - guard FileManager.default.isReadableFile(atPath: appURL.path) == true else - { - throw ApplicationInitializationError.applicationExecutableNotReadable(checkedPath: appURL.path) - } - - guard let appBundle: Bundle = .init(url: appURL) - else - { - throw ApplicationInitializationError.couldNotReadBundle(applicationPath: appURL.absoluteString) - } - - AppConstants.shared.logger.debug("Will try to initialize and App object form bundle \(appBundle)") - - guard let appBundleInfoDictionary: [String: Any] = appBundle.infoDictionary - else - { - throw ApplicationInitializationError.couldNotGetInfoDictionary - } - - guard let appName: String = Application.getAppName(fromInfoDictionary: appBundleInfoDictionary) else - { - throw ApplicationInitializationError.couldNotGetMandatoryAppInformation(.name) - } - - self.name = appName - - self.url = appURL - - self.iconPath = Application.getAppIconPath(fromInfoDictionary: appBundleInfoDictionary, appBundle: appBundle) - - if let iconPath = self.iconPath - { - self.iconImage = .init( - nsImage: .init(byReferencing: iconPath) - ) - } - else - { - self.iconImage = nil - } - } - catch let applicationDirectoryAccessError - { - throw .couldNotAccessApplicationExecutable(error: applicationDirectoryAccessError) - } - } - - private static func getAppName(fromInfoDictionary infoDictionary: [String: Any]) -> String? - { - return infoDictionary["CFBundleName"] as? String - } - - private static func getAppIconPath(fromInfoDictionary infoDictionary: [String: Any], appBundle: Bundle) -> URL? - { - guard let iconFileName: String = infoDictionary["CFBundleIconFile"] as? String - else - { - return nil - } - - return appBundle.resourceURL?.appendingPathComponent(iconFileName, conformingTo: .icns) - } -} diff --git a/Cork/Models/Corrupted Package.swift b/Cork/Models/Corrupted Package.swift deleted file mode 100644 index 6b845f64..00000000 --- a/Cork/Models/Corrupted Package.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Corrupted Package.swift -// Cork -// -// Created by David Bureš on 28.03.2024. -// - -import Foundation - -struct CorruptedPackage: Identifiable, Equatable -{ - let id: UUID = .init() - let name: String -} diff --git a/Cork/Models/Terminal Output.swift b/Cork/Models/Terminal Output.swift deleted file mode 100644 index e137ba04..00000000 --- a/Cork/Models/Terminal Output.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Terminal Output.swift -// Cork -// -// Created by David Bureš on 12.02.2023. -// - -import Foundation - -struct TerminalOutput -{ - var standardOutput: String - var standardError: String -} - -enum StreamedTerminalOutput -{ - case standardOutput(String) - case standardError(String) -} diff --git a/Cork/Views/Reusables/App Icon Display.swift b/Cork/Views/Reusables/App Icon Display.swift index e7bd7a8b..cf137d62 100644 --- a/Cork/Views/Reusables/App Icon Display.swift +++ b/Cork/Views/Reusables/App Icon Display.swift @@ -6,6 +6,7 @@ // import SwiftUI +import ApplicationInspector /// Show the icon of a linked app struct AppIconDisplay: View diff --git a/Derived/InfoPlists/Cork_CorkPackagesLogic-Info.plist b/Derived/InfoPlists/Cork_CorkPackagesLogic-Info.plist new file mode 100644 index 00000000..7a90fce0 --- /dev/null +++ b/Derived/InfoPlists/Cork_CorkPackagesLogic-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright ©. All rights reserved. + + diff --git a/Derived/InfoPlists/Cork_CorkPackagesModels-Info.plist b/Derived/InfoPlists/Cork_CorkPackagesModels-Info.plist new file mode 100644 index 00000000..7a90fce0 --- /dev/null +++ b/Derived/InfoPlists/Cork_CorkPackagesModels-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright ©. All rights reserved. + + diff --git a/Derived/InfoPlists/Cork_CorkShared-Info.plist b/Derived/InfoPlists/Cork_CorkShared-Info.plist new file mode 100644 index 00000000..7a90fce0 --- /dev/null +++ b/Derived/InfoPlists/Cork_CorkShared-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright ©. All rights reserved. + + diff --git a/Derived/Sources/TuistAssets+CorkPackagesLogic.swift b/Derived/Sources/TuistAssets+CorkPackagesLogic.swift new file mode 100644 index 00000000..8baaae4a --- /dev/null +++ b/Derived/Sources/TuistAssets+CorkPackagesLogic.swift @@ -0,0 +1,153 @@ +// swiftlint:disable:this file_name +// swiftlint:disable all +// swift-format-ignore-file +// swiftformat:disable all +// Generated using tuist — https://github.com/tuist/tuist + +#if os(macOS) + import AppKit +#elseif os(iOS) + import UIKit +#elseif os(tvOS) || os(watchOS) + import UIKit +#endif +#if canImport(SwiftUI) + import SwiftUI +#endif + +// MARK: - Asset Catalogs + +public enum CorkPackagesLogicAsset: Sendable { + public enum Assets { + public static let accentColor = CorkPackagesLogicColors(name: "AccentColor") + public static let customAppleTerminalBadgeMagnifyingglass = CorkPackagesLogicImages(name: "custom.apple.terminal.badge.magnifyingglass") + public static let customBrainSlash = CorkPackagesLogicImages(name: "custom.brain.slash") + public static let customMacwindowBadgeMagnifyingglass = CorkPackagesLogicImages(name: "custom.macwindow.badge.magnifyingglass") + public static let customMacwindowBadgeXmark = CorkPackagesLogicImages(name: "custom.macwindow.badge.xmark") + public static let customPinFillQuestionmark = CorkPackagesLogicImages(name: "custom.pin.fill.questionmark") + public static let customShippingbox2BadgeArrowDown = CorkPackagesLogicImages(name: "custom.shippingbox.2.badge.arrow.down") + public static let customShippingboxBadgeMagnifyingglass = CorkPackagesLogicImages(name: "custom.shippingbox.badge.magnifyingglass") + public static let customShippingboxBadgePlus = CorkPackagesLogicImages(name: "custom.shippingbox.badge.plus") + public static let customSparklesSlash = CorkPackagesLogicImages(name: "custom.sparkles.slash") + public static let customSpigotBadgePlus = CorkPackagesLogicImages(name: "custom.spigot.badge.plus") + public static let customSpigotBadgeXmark = CorkPackagesLogicImages(name: "custom.spigot.badge.xmark") + public static let customSquareStackBadgePause = CorkPackagesLogicImages(name: "custom.square.stack.badge.pause") + public static let customSquareStackBadgePlay = CorkPackagesLogicImages(name: "custom.square.stack.badge.play") + public static let customSquareStackBadgeQuestionmark = CorkPackagesLogicImages(name: "custom.square.stack.badge.questionmark") + public static let customSquareStackTrianglebadgeExclamationmark = CorkPackagesLogicImages(name: "custom.square.stack.trianglebadge.exclamationmark") + public static let customTerminalBadgeXmark = CorkPackagesLogicImages(name: "custom.terminal.badge.xmark") + public static let customTrashTriangleFill = CorkPackagesLogicImages(name: "custom.trash.triangle.fill") + } + public enum PreviewAssets { + } +} + +// MARK: - Implementation Details + +public final class CorkPackagesLogicColors: Sendable { + public let name: String + + #if os(macOS) + public typealias Color = NSColor + #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) + public typealias Color = UIColor + #endif + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *) + public var color: Color { + guard let color = Color(asset: self) else { + fatalError("Unable to load color asset named \(name).") + } + return color + } + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) + public var swiftUIColor: SwiftUI.Color { + return SwiftUI.Color(asset: self) + } + #endif + + fileprivate init(name: String) { + self.name = name + } +} + +public extension CorkPackagesLogicColors.Color { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *) + convenience init?(asset: CorkPackagesLogicColors) { + let bundle = Bundle.module + #if os(iOS) || os(tvOS) || os(visionOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) +public extension SwiftUI.Color { + init(asset: CorkPackagesLogicColors) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle) + } +} +#endif + +public struct CorkPackagesLogicImages: Sendable { + public let name: String + + #if os(macOS) + public typealias Image = NSImage + #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) + public typealias Image = UIImage + #endif + + public var image: Image { + let bundle = Bundle.module + #if os(iOS) || os(tvOS) || os(visionOS) + let image = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + let image = bundle.image(forResource: NSImage.Name(name)) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) + public var swiftUIImage: SwiftUI.Image { + SwiftUI.Image(asset: self) + } + #endif +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) +public extension SwiftUI.Image { + init(asset: CorkPackagesLogicImages) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle) + } + + init(asset: CorkPackagesLogicImages, label: Text) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle, label: label) + } + + init(decorative asset: CorkPackagesLogicImages) { + let bundle = Bundle.module + self.init(decorative: asset.name, bundle: bundle) + } +} +#endif + +// swiftformat:enable all +// swiftlint:enable all diff --git a/Derived/Sources/TuistAssets+CorkPackagesModels.swift b/Derived/Sources/TuistAssets+CorkPackagesModels.swift new file mode 100644 index 00000000..e451682c --- /dev/null +++ b/Derived/Sources/TuistAssets+CorkPackagesModels.swift @@ -0,0 +1,153 @@ +// swiftlint:disable:this file_name +// swiftlint:disable all +// swift-format-ignore-file +// swiftformat:disable all +// Generated using tuist — https://github.com/tuist/tuist + +#if os(macOS) + import AppKit +#elseif os(iOS) + import UIKit +#elseif os(tvOS) || os(watchOS) + import UIKit +#endif +#if canImport(SwiftUI) + import SwiftUI +#endif + +// MARK: - Asset Catalogs + +public enum CorkPackagesModelsAsset: Sendable { + public enum Assets { + public static let accentColor = CorkPackagesModelsColors(name: "AccentColor") + public static let customAppleTerminalBadgeMagnifyingglass = CorkPackagesModelsImages(name: "custom.apple.terminal.badge.magnifyingglass") + public static let customBrainSlash = CorkPackagesModelsImages(name: "custom.brain.slash") + public static let customMacwindowBadgeMagnifyingglass = CorkPackagesModelsImages(name: "custom.macwindow.badge.magnifyingglass") + public static let customMacwindowBadgeXmark = CorkPackagesModelsImages(name: "custom.macwindow.badge.xmark") + public static let customPinFillQuestionmark = CorkPackagesModelsImages(name: "custom.pin.fill.questionmark") + public static let customShippingbox2BadgeArrowDown = CorkPackagesModelsImages(name: "custom.shippingbox.2.badge.arrow.down") + public static let customShippingboxBadgeMagnifyingglass = CorkPackagesModelsImages(name: "custom.shippingbox.badge.magnifyingglass") + public static let customShippingboxBadgePlus = CorkPackagesModelsImages(name: "custom.shippingbox.badge.plus") + public static let customSparklesSlash = CorkPackagesModelsImages(name: "custom.sparkles.slash") + public static let customSpigotBadgePlus = CorkPackagesModelsImages(name: "custom.spigot.badge.plus") + public static let customSpigotBadgeXmark = CorkPackagesModelsImages(name: "custom.spigot.badge.xmark") + public static let customSquareStackBadgePause = CorkPackagesModelsImages(name: "custom.square.stack.badge.pause") + public static let customSquareStackBadgePlay = CorkPackagesModelsImages(name: "custom.square.stack.badge.play") + public static let customSquareStackBadgeQuestionmark = CorkPackagesModelsImages(name: "custom.square.stack.badge.questionmark") + public static let customSquareStackTrianglebadgeExclamationmark = CorkPackagesModelsImages(name: "custom.square.stack.trianglebadge.exclamationmark") + public static let customTerminalBadgeXmark = CorkPackagesModelsImages(name: "custom.terminal.badge.xmark") + public static let customTrashTriangleFill = CorkPackagesModelsImages(name: "custom.trash.triangle.fill") + } + public enum PreviewAssets { + } +} + +// MARK: - Implementation Details + +public final class CorkPackagesModelsColors: Sendable { + public let name: String + + #if os(macOS) + public typealias Color = NSColor + #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) + public typealias Color = UIColor + #endif + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *) + public var color: Color { + guard let color = Color(asset: self) else { + fatalError("Unable to load color asset named \(name).") + } + return color + } + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) + public var swiftUIColor: SwiftUI.Color { + return SwiftUI.Color(asset: self) + } + #endif + + fileprivate init(name: String) { + self.name = name + } +} + +public extension CorkPackagesModelsColors.Color { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *) + convenience init?(asset: CorkPackagesModelsColors) { + let bundle = Bundle.module + #if os(iOS) || os(tvOS) || os(visionOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) +public extension SwiftUI.Color { + init(asset: CorkPackagesModelsColors) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle) + } +} +#endif + +public struct CorkPackagesModelsImages: Sendable { + public let name: String + + #if os(macOS) + public typealias Image = NSImage + #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) + public typealias Image = UIImage + #endif + + public var image: Image { + let bundle = Bundle.module + #if os(iOS) || os(tvOS) || os(visionOS) + let image = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + let image = bundle.image(forResource: NSImage.Name(name)) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) + public var swiftUIImage: SwiftUI.Image { + SwiftUI.Image(asset: self) + } + #endif +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) +public extension SwiftUI.Image { + init(asset: CorkPackagesModelsImages) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle) + } + + init(asset: CorkPackagesModelsImages, label: Text) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle, label: label) + } + + init(decorative asset: CorkPackagesModelsImages) { + let bundle = Bundle.module + self.init(decorative: asset.name, bundle: bundle) + } +} +#endif + +// swiftformat:enable all +// swiftlint:enable all diff --git a/Derived/Sources/TuistAssets+CorkShared.swift b/Derived/Sources/TuistAssets+CorkShared.swift new file mode 100644 index 00000000..7d398dd3 --- /dev/null +++ b/Derived/Sources/TuistAssets+CorkShared.swift @@ -0,0 +1,153 @@ +// swiftlint:disable:this file_name +// swiftlint:disable all +// swift-format-ignore-file +// swiftformat:disable all +// Generated using tuist — https://github.com/tuist/tuist + +#if os(macOS) + import AppKit +#elseif os(iOS) + import UIKit +#elseif os(tvOS) || os(watchOS) + import UIKit +#endif +#if canImport(SwiftUI) + import SwiftUI +#endif + +// MARK: - Asset Catalogs + +public enum CorkSharedAsset: Sendable { + public enum Assets { + public static let accentColor = CorkSharedColors(name: "AccentColor") + public static let customAppleTerminalBadgeMagnifyingglass = CorkSharedImages(name: "custom.apple.terminal.badge.magnifyingglass") + public static let customBrainSlash = CorkSharedImages(name: "custom.brain.slash") + public static let customMacwindowBadgeMagnifyingglass = CorkSharedImages(name: "custom.macwindow.badge.magnifyingglass") + public static let customMacwindowBadgeXmark = CorkSharedImages(name: "custom.macwindow.badge.xmark") + public static let customPinFillQuestionmark = CorkSharedImages(name: "custom.pin.fill.questionmark") + public static let customShippingbox2BadgeArrowDown = CorkSharedImages(name: "custom.shippingbox.2.badge.arrow.down") + public static let customShippingboxBadgeMagnifyingglass = CorkSharedImages(name: "custom.shippingbox.badge.magnifyingglass") + public static let customShippingboxBadgePlus = CorkSharedImages(name: "custom.shippingbox.badge.plus") + public static let customSparklesSlash = CorkSharedImages(name: "custom.sparkles.slash") + public static let customSpigotBadgePlus = CorkSharedImages(name: "custom.spigot.badge.plus") + public static let customSpigotBadgeXmark = CorkSharedImages(name: "custom.spigot.badge.xmark") + public static let customSquareStackBadgePause = CorkSharedImages(name: "custom.square.stack.badge.pause") + public static let customSquareStackBadgePlay = CorkSharedImages(name: "custom.square.stack.badge.play") + public static let customSquareStackBadgeQuestionmark = CorkSharedImages(name: "custom.square.stack.badge.questionmark") + public static let customSquareStackTrianglebadgeExclamationmark = CorkSharedImages(name: "custom.square.stack.trianglebadge.exclamationmark") + public static let customTerminalBadgeXmark = CorkSharedImages(name: "custom.terminal.badge.xmark") + public static let customTrashTriangleFill = CorkSharedImages(name: "custom.trash.triangle.fill") + } + public enum PreviewAssets { + } +} + +// MARK: - Implementation Details + +public final class CorkSharedColors: Sendable { + public let name: String + + #if os(macOS) + public typealias Color = NSColor + #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) + public typealias Color = UIColor + #endif + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *) + public var color: Color { + guard let color = Color(asset: self) else { + fatalError("Unable to load color asset named \(name).") + } + return color + } + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) + public var swiftUIColor: SwiftUI.Color { + return SwiftUI.Color(asset: self) + } + #endif + + fileprivate init(name: String) { + self.name = name + } +} + +public extension CorkSharedColors.Color { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *) + convenience init?(asset: CorkSharedColors) { + let bundle = Bundle.module + #if os(iOS) || os(tvOS) || os(visionOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) +public extension SwiftUI.Color { + init(asset: CorkSharedColors) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle) + } +} +#endif + +public struct CorkSharedImages: Sendable { + public let name: String + + #if os(macOS) + public typealias Image = NSImage + #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) + public typealias Image = UIImage + #endif + + public var image: Image { + let bundle = Bundle.module + #if os(iOS) || os(tvOS) || os(visionOS) + let image = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + let image = bundle.image(forResource: NSImage.Name(name)) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) + public var swiftUIImage: SwiftUI.Image { + SwiftUI.Image(asset: self) + } + #endif +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *) +public extension SwiftUI.Image { + init(asset: CorkSharedImages) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle) + } + + init(asset: CorkSharedImages, label: Text) { + let bundle = Bundle.module + self.init(asset.name, bundle: bundle, label: label) + } + + init(decorative asset: CorkSharedImages) { + let bundle = Bundle.module + self.init(decorative: asset.name, bundle: bundle) + } +} +#endif + +// swiftformat:enable all +// swiftlint:enable all diff --git a/Derived/Sources/TuistBundle+CorkPackagesLogic.swift b/Derived/Sources/TuistBundle+CorkPackagesLogic.swift new file mode 100644 index 00000000..52b6daef --- /dev/null +++ b/Derived/Sources/TuistBundle+CorkPackagesLogic.swift @@ -0,0 +1,64 @@ +// periphery:ignore:all +// swiftlint:disable:this file_name +// swiftlint:disable all +// swift-format-ignore-file +// swiftformat:disable all +#if hasFeature(InternalImportsByDefault) +public import Foundation +#else +import Foundation +#endif +// MARK: - Swift Bundle Accessor - for SPM +private class BundleFinder {} +extension Foundation.Bundle { +/// Since CorkPackagesLogic is a static library, the bundle containing the resources is copied into the final product. + static let module: Bundle = { + let bundleName = "Cork_CorkPackagesLogic" + let bundleFinderResourceURL = Bundle(for: BundleFinder.self).resourceURL + var candidates = [ + Bundle.main.resourceURL, + bundleFinderResourceURL, + Bundle.main.bundleURL, + ] + // This is a fix to make Previews work with bundled resources. + // Logic here is taken from SPM's generated `resource_bundle_accessors.swift` file, + // which is located under the derived data directory after building the project. + if let override = ProcessInfo.processInfo.environment["PACKAGE_RESOURCE_BUNDLE_PATH"] { + candidates.append(URL(fileURLWithPath: override)) + // Deleting derived data and not rebuilding the frameworks containing resources may result in a state + // where the bundles are only available in the framework's directory that is actively being previewed. + // Since we don't know which framework this is, we also need to look in all the framework subpaths. + if let subpaths = try? Foundation.FileManager.default.contentsOfDirectory(atPath: override) { + for subpath in subpaths { + if subpath.hasSuffix(".framework") { + candidates.append(URL(fileURLWithPath: override + "/" + subpath)) + } + } + } + } + + // This is a fix to make unit tests work with bundled resources. + // Making this change allows unit tests to search one directory up for a bundle. + // More context can be found in this PR: https://github.com/tuist/tuist/pull/6895 + #if canImport(XCTest) + candidates.append(bundleFinderResourceURL?.appendingPathComponent("..")) + #endif + + for candidate in candidates { + let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle") + if let bundle = bundlePath.flatMap(Bundle.init(url:)) { + return bundle + } + } + fatalError("unable to find bundle named Cork_CorkPackagesLogic") + }() +} +// MARK: - Objective-C Bundle Accessor +@objc +public class CorkPackagesLogicResources: NSObject { +@objc public class var bundle: Bundle { + return .module +} +} +// swiftformat:enable all +// swiftlint:enable all \ No newline at end of file diff --git a/Derived/Sources/TuistBundle+CorkPackagesModels.swift b/Derived/Sources/TuistBundle+CorkPackagesModels.swift new file mode 100644 index 00000000..f07fcbd2 --- /dev/null +++ b/Derived/Sources/TuistBundle+CorkPackagesModels.swift @@ -0,0 +1,64 @@ +// periphery:ignore:all +// swiftlint:disable:this file_name +// swiftlint:disable all +// swift-format-ignore-file +// swiftformat:disable all +#if hasFeature(InternalImportsByDefault) +public import Foundation +#else +import Foundation +#endif +// MARK: - Swift Bundle Accessor - for SPM +private class BundleFinder {} +extension Foundation.Bundle { +/// Since CorkPackagesModels is a static library, the bundle containing the resources is copied into the final product. + static let module: Bundle = { + let bundleName = "Cork_CorkPackagesModels" + let bundleFinderResourceURL = Bundle(for: BundleFinder.self).resourceURL + var candidates = [ + Bundle.main.resourceURL, + bundleFinderResourceURL, + Bundle.main.bundleURL, + ] + // This is a fix to make Previews work with bundled resources. + // Logic here is taken from SPM's generated `resource_bundle_accessors.swift` file, + // which is located under the derived data directory after building the project. + if let override = ProcessInfo.processInfo.environment["PACKAGE_RESOURCE_BUNDLE_PATH"] { + candidates.append(URL(fileURLWithPath: override)) + // Deleting derived data and not rebuilding the frameworks containing resources may result in a state + // where the bundles are only available in the framework's directory that is actively being previewed. + // Since we don't know which framework this is, we also need to look in all the framework subpaths. + if let subpaths = try? Foundation.FileManager.default.contentsOfDirectory(atPath: override) { + for subpath in subpaths { + if subpath.hasSuffix(".framework") { + candidates.append(URL(fileURLWithPath: override + "/" + subpath)) + } + } + } + } + + // This is a fix to make unit tests work with bundled resources. + // Making this change allows unit tests to search one directory up for a bundle. + // More context can be found in this PR: https://github.com/tuist/tuist/pull/6895 + #if canImport(XCTest) + candidates.append(bundleFinderResourceURL?.appendingPathComponent("..")) + #endif + + for candidate in candidates { + let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle") + if let bundle = bundlePath.flatMap(Bundle.init(url:)) { + return bundle + } + } + fatalError("unable to find bundle named Cork_CorkPackagesModels") + }() +} +// MARK: - Objective-C Bundle Accessor +@objc +public class CorkPackagesModelsResources: NSObject { +@objc public class var bundle: Bundle { + return .module +} +} +// swiftformat:enable all +// swiftlint:enable all \ No newline at end of file diff --git a/Derived/Sources/TuistBundle+CorkShared.swift b/Derived/Sources/TuistBundle+CorkShared.swift new file mode 100644 index 00000000..5e0ca8ed --- /dev/null +++ b/Derived/Sources/TuistBundle+CorkShared.swift @@ -0,0 +1,64 @@ +// periphery:ignore:all +// swiftlint:disable:this file_name +// swiftlint:disable all +// swift-format-ignore-file +// swiftformat:disable all +#if hasFeature(InternalImportsByDefault) +public import Foundation +#else +import Foundation +#endif +// MARK: - Swift Bundle Accessor - for SPM +private class BundleFinder {} +extension Foundation.Bundle { +/// Since CorkShared is a static library, the bundle containing the resources is copied into the final product. + static let module: Bundle = { + let bundleName = "Cork_CorkShared" + let bundleFinderResourceURL = Bundle(for: BundleFinder.self).resourceURL + var candidates = [ + Bundle.main.resourceURL, + bundleFinderResourceURL, + Bundle.main.bundleURL, + ] + // This is a fix to make Previews work with bundled resources. + // Logic here is taken from SPM's generated `resource_bundle_accessors.swift` file, + // which is located under the derived data directory after building the project. + if let override = ProcessInfo.processInfo.environment["PACKAGE_RESOURCE_BUNDLE_PATH"] { + candidates.append(URL(fileURLWithPath: override)) + // Deleting derived data and not rebuilding the frameworks containing resources may result in a state + // where the bundles are only available in the framework's directory that is actively being previewed. + // Since we don't know which framework this is, we also need to look in all the framework subpaths. + if let subpaths = try? Foundation.FileManager.default.contentsOfDirectory(atPath: override) { + for subpath in subpaths { + if subpath.hasSuffix(".framework") { + candidates.append(URL(fileURLWithPath: override + "/" + subpath)) + } + } + } + } + + // This is a fix to make unit tests work with bundled resources. + // Making this change allows unit tests to search one directory up for a bundle. + // More context can be found in this PR: https://github.com/tuist/tuist/pull/6895 + #if canImport(XCTest) + candidates.append(bundleFinderResourceURL?.appendingPathComponent("..")) + #endif + + for candidate in candidates { + let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle") + if let bundle = bundlePath.flatMap(Bundle.init(url:)) { + return bundle + } + } + fatalError("unable to find bundle named Cork_CorkShared") + }() +} +// MARK: - Objective-C Bundle Accessor +@objc +public class CorkSharedResources: NSObject { +@objc public class var bundle: Bundle { + return .module +} +} +// swiftformat:enable all +// swiftlint:enable all \ No newline at end of file diff --git a/Modules/Intents/intent.swift b/Modules/Intents/intent.swift new file mode 100644 index 00000000..e69de29b diff --git a/Cork/Logic/Package Loading/Helper Logic/Check if Package Was Installed Intentionally.swift b/Modules/Packages/PackagesLogic/Logic/Check if Package was Installed Intentionally.swift similarity index 96% rename from Cork/Logic/Package Loading/Helper Logic/Check if Package Was Installed Intentionally.swift rename to Modules/Packages/PackagesLogic/Logic/Check if Package was Installed Intentionally.swift index 24c36c35..e0100df4 100644 --- a/Cork/Logic/Package Loading/Helper Logic/Check if Package Was Installed Intentionally.swift +++ b/Modules/Packages/PackagesLogic/Logic/Check if Package was Installed Intentionally.swift @@ -1,14 +1,14 @@ // -// Check if Package Was Installed Intentionally.swift +// Check if Package was Installed Intentionally.swift // Cork // -// Created by David Bureš on 13.11.2024. +// Created by David Bureš - P on 28.10.2025. // import Foundation import CorkShared -enum IntentionalInstallationDiscoveryError: Error, Hashable +public enum IntentionalInstallationDiscoveryError: Error, Hashable { /// The function could not determine the most relevant version of the package to read the recepit from case failedToDetermineMostRelevantVersion(packageURL: URL) @@ -26,7 +26,7 @@ enum IntentionalInstallationDiscoveryError: Error, Hashable case unexpectedFolderName(packageURL: URL) } -extension URL +public extension URL { /// This function checks whether the package was installed intentionally. /// - For Formulae, this info gets read from the install receipt diff --git a/Cork/App State.swift b/Modules/Packages/PackagesModels/App State.swift similarity index 96% rename from Cork/App State.swift rename to Modules/Packages/PackagesModels/App State.swift index a79050c4..4bd3cf75 100644 --- a/Cork/App State.swift +++ b/Modules/Packages/PackagesModels/App State.swift @@ -2,7 +2,7 @@ // App State.swift // Cork // -// Created by David Bureš on 05.02.2023. +// Created by David Bureš - P on 28.10.2025. // import AppKit @@ -14,9 +14,19 @@ import Observation /// Class that holds the global state of the app, excluding services @Observable @MainActor -final class AppState +public final class AppState { // MARK: - Licensing + + public enum LicensingState + { + case notBoughtOrHasNotActivatedDemo + + case demo + case bought + + case selfCompiled + } var licensingState: LicensingState = .notBoughtOrHasNotActivatedDemo diff --git a/Cork/Enums/Alerts/Main Window/Displayable Alerts.swift b/Modules/Packages/PackagesModels/Enums/Alerts/Displayable Alerts.swift similarity index 97% rename from Cork/Enums/Alerts/Main Window/Displayable Alerts.swift rename to Modules/Packages/PackagesModels/Enums/Alerts/Displayable Alerts.swift index 8bcaaeee..1c37ba54 100644 --- a/Cork/Enums/Alerts/Main Window/Displayable Alerts.swift +++ b/Modules/Packages/PackagesModels/Enums/Alerts/Displayable Alerts.swift @@ -8,7 +8,7 @@ import Foundation import SwiftUI -enum DisplayableAlert: LocalizedError +public enum DisplayableAlert: LocalizedError { case couldNotGetContentsOfPackageFolder(String), couldNotLoadAnyPackages(LocalizedError), couldNotLoadCertainPackage(String, URL, failureReason: String) case licenseCheckingFailedDueToAuthorizationComplexNotBeingEncodedProperly, licenseCheckingFailedDueToNoInternet, licenseCheckingFailedDueToTimeout, licenseCheckingFailedForOtherReason(localizedDescription: String) diff --git a/Cork/Enums/Alerts/Main Window/Error Details/Displayable Alerts - Descriptions.swift b/Modules/Packages/PackagesModels/Enums/Alerts/Error Details/Displayable Alerts - Descriptions.swift similarity index 99% rename from Cork/Enums/Alerts/Main Window/Error Details/Displayable Alerts - Descriptions.swift rename to Modules/Packages/PackagesModels/Enums/Alerts/Error Details/Displayable Alerts - Descriptions.swift index 3505fc2c..12e3cc2c 100644 --- a/Cork/Enums/Alerts/Main Window/Error Details/Displayable Alerts - Descriptions.swift +++ b/Modules/Packages/PackagesModels/Enums/Alerts/Error Details/Displayable Alerts - Descriptions.swift @@ -7,7 +7,7 @@ import Foundation -extension DisplayableAlert +public extension DisplayableAlert { /// The bold text at the top of the error var errorDescription: String? diff --git a/Cork/Enums/Alerts/Main Window/Error Details/Displayable Alerts - Recovery Suggestions.swift b/Modules/Packages/PackagesModels/Enums/Alerts/Error Details/Displayable Alerts - Recovery Suggestions.swift similarity index 99% rename from Cork/Enums/Alerts/Main Window/Error Details/Displayable Alerts - Recovery Suggestions.swift rename to Modules/Packages/PackagesModels/Enums/Alerts/Error Details/Displayable Alerts - Recovery Suggestions.swift index e5093176..23b67dfe 100644 --- a/Cork/Enums/Alerts/Main Window/Error Details/Displayable Alerts - Recovery Suggestions.swift +++ b/Modules/Packages/PackagesModels/Enums/Alerts/Error Details/Displayable Alerts - Recovery Suggestions.swift @@ -7,7 +7,7 @@ import Foundation -extension DisplayableAlert +public extension DisplayableAlert { /// Message in the alert var recoverySuggestion: String? diff --git a/Modules/Packages/PackagesModels/Enums/Brewfile import Stage.swift b/Modules/Packages/PackagesModels/Enums/Brewfile import Stage.swift new file mode 100644 index 00000000..c34c2779 --- /dev/null +++ b/Modules/Packages/PackagesModels/Enums/Brewfile import Stage.swift @@ -0,0 +1,13 @@ +// +// Brewfile import Stage.swift +// Cork +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation + +public enum BrewfileImportStage +{ + case importing, finished +} diff --git a/Cork/Enums/Confirmation Dialogs/Main Window/Confirmation Dialog - Main Window.swift b/Modules/Packages/PackagesModels/Enums/Confirmation dialogs/Confirmation Dialog.swift similarity index 78% rename from Cork/Enums/Confirmation Dialogs/Main Window/Confirmation Dialog - Main Window.swift rename to Modules/Packages/PackagesModels/Enums/Confirmation dialogs/Confirmation Dialog.swift index a7e4abac..162bd544 100644 --- a/Cork/Enums/Confirmation Dialogs/Main Window/Confirmation Dialog - Main Window.swift +++ b/Modules/Packages/PackagesModels/Enums/Confirmation dialogs/Confirmation Dialog.swift @@ -1,25 +1,25 @@ // -// Confirmation Dialog - Main Window.swift +// Confirmation Dialog.swift // Cork // -// Created by David Bureš - P on 21.04.2025. +// Created by David Bureš - P on 28.10.2025. // import Foundation import SwiftUI -enum ConfirmationDialog: Identifiable, Equatable +public enum ConfirmationDialog: Identifiable, Equatable { case uninstallPackage(_ packageToUninstall: BrewPackage) case purgePackage(_ packageToPurge: BrewPackage) - var id: UUID + public var id: UUID { return .init() } - var title: LocalizedStringKey + public var title: LocalizedStringKey { switch self { diff --git a/Cork/Enums/Sheets/Main Window/Sheets - Main Window.swift b/Modules/Packages/PackagesModels/Enums/Sheets/Displayable Sheet.swift similarity index 70% rename from Cork/Enums/Sheets/Main Window/Sheets - Main Window.swift rename to Modules/Packages/PackagesModels/Enums/Sheets/Displayable Sheet.swift index 59508a41..8c870cbd 100644 --- a/Cork/Enums/Sheets/Main Window/Sheets - Main Window.swift +++ b/Modules/Packages/PackagesModels/Enums/Sheets/Displayable Sheet.swift @@ -1,13 +1,13 @@ // -// Sheets - Main Window.swift +// Displayable Sheet.swift // Cork // -// Created by David Bureš - P on 19.01.2025. +// Created by David Bureš - P on 28.10.2025. // import Foundation -enum DisplayableSheet: Identifiable, Equatable +public enum DisplayableSheet: Identifiable, Equatable { case packageInstallation @@ -20,13 +20,13 @@ enum DisplayableSheet: Identifiable, Equatable case corruptedPackageFix(corruptedPackage: CorruptedPackage) - case sudoRequiredForPackageRemoval + case sudoRequiredForPackageRemoval case maintenance(fastCacheDeletion: Bool) case brewfileExport, brewfileImport - var id: UUID + public var id: UUID { return .init() } diff --git a/Modules/Packages/PackagesModels/Errors/Package Loading Error.swift b/Modules/Packages/PackagesModels/Errors/Package Loading Error.swift new file mode 100644 index 00000000..bf2a6ed7 --- /dev/null +++ b/Modules/Packages/PackagesModels/Errors/Package Loading Error.swift @@ -0,0 +1,77 @@ +// +// Package Loading Error.swift +// CorkPackagesModels +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation +import CorkPackagesLogic + +public extension BrewPackage +{ + /// Error representing failures while loading + enum PackageLoadingError: LocalizedError, Hashable, Identifiable + { + /// Tried to treat the folder `Cellar` or `Caskroom` itself as a package - means Homebrew itself is broken + case triedToThreatFolderContainingPackagesAsPackage(packageType: BrewPackage.PackageType) + + /// The `Cellar` and `Caskroom` folder itself couldn't be loaded + case couldNotReadContentsOfParentFolder(failureReason: String, folderURL: URL) + + /// Failed while trying to read contents of package folder + case failedWhileReadingContentsOfPackageFolder(folderURL: URL, reportedError: String) + + case failedWhileTryingToDetermineIntentionalInstallation( + folderURL: URL, + associatedIntentionalDiscoveryError: IntentionalInstallationDiscoveryError + ) + + /// The package root folder exists, but the package itself doesn't have any versions + case packageDoesNotHaveAnyVersionsInstalled(packageURL: URL) + + /// A folder that should have contained the package is not actually a folder + case packageIsNotAFolder(String, packageURL: URL) + + /// The number of loaded packages does not match the number of package parent folders + case numberOLoadedPackagesDosNotMatchNumberOfPackageFolders + + public var errorDescription: String? + { + switch self + { + case .couldNotReadContentsOfParentFolder(let failureReason, _): + return String(localized: "error.package-loading.could-not-read-contents-of-parent-folder.\(failureReason)") + + case .triedToThreatFolderContainingPackagesAsPackage(let packageType): + switch packageType + { + case .formula: + return "error.package-loading.last-path-component-of-checked-package-url-is-folder-containing-packages-itself.formulae" + case .cask: + return "error.package-loading.last-path-component-of-checked-package-url-is-folder-containing-packages-itself.casks" + } + + case .failedWhileReadingContentsOfPackageFolder(let folderURL, let reportedError): + return String(localized: "error.package-loading.could-not-load-\(folderURL.packageNameFromURL())-at-\(folderURL.absoluteString)-because-\(reportedError)", comment: "Couldn't load package (package name) at (package URL) because (failure reason)") + + case .failedWhileTryingToDetermineIntentionalInstallation(_, let associatedIntentionalDiscoveryError): + return associatedIntentionalDiscoveryError.localizedDescription + + case .packageDoesNotHaveAnyVersionsInstalled(let packageURL): + return String(localized: "error.package-loading.\(packageURL.packageNameFromURL())-does-not-have-any-versions-installed") + + case .packageIsNotAFolder(let string, _): + return String(localized: "error.package-loading.\(string)-not-a-folder", comment: "Package folder in this context means a folder that encloses package versions. Every package has its own folder, and this error occurs when the provided URL does not point to a folder that encloses package versions") + + case .numberOLoadedPackagesDosNotMatchNumberOfPackageFolders: + return String(localized: "error.package-loading.number-of-loaded-poackages-does-not-match-number-of-package-folders", comment: "This error occurs when there's a mismatch between the number of loaded packages, and the number of package folders in the package folders") + } + } + + public var id: UUID + { + return UUID() + } + } +} diff --git a/Modules/Packages/PackagesModels/Models/App Adoption/Adoptable App.swift b/Modules/Packages/PackagesModels/Models/App Adoption/Adoptable App.swift new file mode 100644 index 00000000..e98e0977 --- /dev/null +++ b/Modules/Packages/PackagesModels/Models/App Adoption/Adoptable App.swift @@ -0,0 +1,65 @@ +// +// Adoptable App.swift +// Cork +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation +import ApplicationInspector + +public extension BrewPackagesTracker +{ + /// A struct for holding a Cask's name and its executable + struct AdoptableApp: Identifiable, Hashable, Sendable + { + public let id: UUID = .init() + + let caskName: String + let appExecutable: String + + let description: String? + + let fullAppUrl: URL + + var isMarkedForAdoption: Bool + + var app: Application? + + init(caskName: String, description: String?, appExecutable: String) + { + self.caskName = caskName + self.appExecutable = appExecutable + + self.description = description + + self.fullAppUrl = URL.applicationDirectory.appendingPathComponent(appExecutable, conformingTo: .application) + + self.isMarkedForAdoption = true + } + + mutating func changeMarkedState() + { + self.isMarkedForAdoption.toggle() + } + + func constructAppBundle() async -> Application? + { + return try? .init(from: self.fullAppUrl) + } + + func excludeSelf() async + { + let excludedAppRepresentation: BrewPackagesTracker.ExcludedAdoptableApp = .init(fromAdoptableApp: self) + + await excludedAppRepresentation.saveSelfToDatabase() + } + + func includeSelf() async + { + let excludedAppRepresentation: BrewPackagesTracker.ExcludedAdoptableApp = .init(fromAdoptableApp: self) + + await excludedAppRepresentation.deleteSelfFromDatabase() + } + } +} diff --git a/Modules/Packages/PackagesModels/Models/App Adoption/Excluded Adptable App.swift b/Modules/Packages/PackagesModels/Models/App Adoption/Excluded Adptable App.swift new file mode 100644 index 00000000..adf35e08 --- /dev/null +++ b/Modules/Packages/PackagesModels/Models/App Adoption/Excluded Adptable App.swift @@ -0,0 +1,58 @@ +// +// Excluded Adptable App.swift +// CorkPackagesModels +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation +import SwiftData +import CorkShared + +public extension BrewPackagesTracker +{ + @Model + final class ExcludedAdoptableApp + { + @Attribute(.unique) @Attribute(.spotlight) + var appExecutable: String + + init(appExecutable: String) + { + self.appExecutable = appExecutable + } + + init(fromAdoptableApp app: BrewPackagesTracker.AdoptableApp) + { + self.appExecutable = app.appExecutable + } + + @MainActor + public func saveSelfToDatabase() + { + AppConstants.shared.modelContainer.mainContext.insert(self) + } + + @MainActor + public func deleteSelfFromDatabase() + { + let modelContext: ModelContext = AppConstants.shared.modelContainer.mainContext + + do + { + let descriptor = FetchDescriptor( + predicate: #Predicate { $0.appExecutable == appExecutable } + ) + + if let existingPackage = try modelContext.fetch(descriptor).first + { + modelContext.delete(existingPackage) + } + } + catch + { + AppConstants.shared.logger.error("Failed to fetch excluded adoptable app for deletion: \(error.localizedDescription)") + } + } + } +} diff --git a/Modules/Packages/PackagesModels/Models/Application.swift b/Modules/Packages/PackagesModels/Models/Application.swift new file mode 100644 index 00000000..5d6230ec --- /dev/null +++ b/Modules/Packages/PackagesModels/Models/Application.swift @@ -0,0 +1,8 @@ +// +// Application.swift +// Cork +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation diff --git a/Modules/Packages/PackagesModels/Models/Brew Package.swift b/Modules/Packages/PackagesModels/Models/Brew Package.swift index b2c95013..8f2ad829 100644 --- a/Modules/Packages/PackagesModels/Models/Brew Package.swift +++ b/Modules/Packages/PackagesModels/Models/Brew Package.swift @@ -13,11 +13,17 @@ import SwiftData import Charts import AppIntents import SwiftUI +import CorkTerminalFunctions +import CorkPackagesLogic + +/// A representation of the loaded ``BrewPackage``s +/// Includes packages that were loaded properly, along those whose loading failed +typealias BrewPackages = Set> /// A representation of a Homebrew package -struct BrewPackage: Identifiable, Equatable, Hashable, Codable +public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable { - var id: UUID = .init() + public var id: UUID = .init() let name: String let type: PackageType @@ -44,13 +50,13 @@ struct BrewPackage: Identifiable, Equatable, Hashable, Codable return versions.formatted(.list(type: .and)) } - enum PackageType: String, CustomStringConvertible, Plottable, AppEntity, Codable + public enum PackageType: String, CustomStringConvertible, Plottable, AppEntity, Codable { case formula case cask /// User-readable description of the package type - var description: String + public var description: String { switch self { @@ -62,7 +68,7 @@ struct BrewPackage: Identifiable, Equatable, Hashable, Codable } /// Localization keys for description of the package type - var localizableDescription: LocalizedStringKey + public var localizableDescription: LocalizedStringKey { switch self { @@ -97,9 +103,9 @@ struct BrewPackage: Identifiable, Equatable, Hashable, Codable } } - static let typeDisplayRepresentation: TypeDisplayRepresentation = .init(name: "package-details.type") + public static let typeDisplayRepresentation: TypeDisplayRepresentation = .init(name: "package-details.type") - var displayRepresentation: DisplayRepresentation + public var displayRepresentation: DisplayRepresentation { switch self { diff --git a/Cork/Models/Brew Tap.swift b/Modules/Packages/PackagesModels/Models/Brew Tap.swift similarity index 62% rename from Cork/Models/Brew Tap.swift rename to Modules/Packages/PackagesModels/Models/Brew Tap.swift index fed0ae5d..7b909703 100644 --- a/Cork/Models/Brew Tap.swift +++ b/Modules/Packages/PackagesModels/Models/Brew Tap.swift @@ -2,14 +2,14 @@ // Brew Tap.swift // Cork // -// Created by David Bureš on 10.02.2023. +// Created by David Bureš - P on 28.10.2025. // import Foundation -struct BrewTap: Identifiable, Hashable +public struct BrewTap: Identifiable, Hashable { - let id: UUID = .init() + public let id: UUID = .init() let name: String var isBeingModified: Bool = false diff --git a/Modules/Packages/PackagesModels/Models/Corrupted Package.swift b/Modules/Packages/PackagesModels/Models/Corrupted Package.swift new file mode 100644 index 00000000..3525a36d --- /dev/null +++ b/Modules/Packages/PackagesModels/Models/Corrupted Package.swift @@ -0,0 +1,14 @@ +// +// Corrupted Package.swift +// Cork +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation + +public struct CorruptedPackage: Identifiable, Equatable +{ + public let id: UUID = .init() + let name: String +} diff --git a/Cork/Models/Intents/Minimal Homebrew Package.swift b/Modules/Packages/PackagesModels/Models/Intents/Minimal Homebrew Package.swift similarity index 96% rename from Cork/Models/Intents/Minimal Homebrew Package.swift rename to Modules/Packages/PackagesModels/Models/Intents/Minimal Homebrew Package.swift index 114c0c88..11793d64 100644 --- a/Cork/Models/Intents/Minimal Homebrew Package.swift +++ b/Modules/Packages/PackagesModels/Models/Intents/Minimal Homebrew Package.swift @@ -2,7 +2,7 @@ // Minimal Homebrew Package.swift // Cork // -// Created by David Bureš on 25.05.2024. +// Created by David Bureš - P on 28.10.2025. // import AppIntents diff --git a/Cork/Models/Outdated Packages/Outdated Package.swift b/Modules/Packages/PackagesModels/Models/Outdated Package.swift similarity index 73% rename from Cork/Models/Outdated Packages/Outdated Package.swift rename to Modules/Packages/PackagesModels/Models/Outdated Package.swift index 918d0978..bc9a3e0f 100644 --- a/Cork/Models/Outdated Packages/Outdated Package.swift +++ b/Modules/Packages/PackagesModels/Models/Outdated Package.swift @@ -2,12 +2,12 @@ // Outdated Package.swift // Cork // -// Created by David Bureš on 05.04.2023. +// Created by David Bureš - P on 28.10.2025. // import Foundation -struct OutdatedPackage: Identifiable, Equatable, Hashable +public struct OutdatedPackage: Identifiable, Equatable, Hashable { enum PackageUpdatingType { @@ -29,7 +29,7 @@ struct OutdatedPackage: Identifiable, Equatable, Hashable } } - let id: UUID = .init() + public let id: UUID = .init() let package: BrewPackage @@ -39,13 +39,14 @@ struct OutdatedPackage: Identifiable, Equatable, Hashable var isMarkedForUpdating: Bool = true var updatingManagedBy: PackageUpdatingType - - static func == (lhs: OutdatedPackage, rhs: OutdatedPackage) -> Bool + + public static func == (lhs: OutdatedPackage, rhs: OutdatedPackage) -> Bool { return lhs.package.name == rhs.package.name } - - func hash(into hasher: inout Hasher) { + + public func hash(into hasher: inout Hasher) + { hasher.combine(package.name) } } diff --git a/Cork/Logic/Pinning/Apply Pinned Status.swift b/Modules/Packages/PackagesModels/Required Logic/Apply Pinned Status.swift similarity index 100% rename from Cork/Logic/Pinning/Apply Pinned Status.swift rename to Modules/Packages/PackagesModels/Required Logic/Apply Pinned Status.swift diff --git a/Cork/Logic/Pinning/Get Names of Pinned Packages.swift b/Modules/Packages/PackagesModels/Required Logic/Get Names of Pinned Packages.swift similarity index 91% rename from Cork/Logic/Pinning/Get Names of Pinned Packages.swift rename to Modules/Packages/PackagesModels/Required Logic/Get Names of Pinned Packages.swift index ca3599c0..5b5de4c5 100644 --- a/Cork/Logic/Pinning/Get Names of Pinned Packages.swift +++ b/Modules/Packages/PackagesModels/Required Logic/Get Names of Pinned Packages.swift @@ -1,14 +1,15 @@ // // Get Names of Pinned Packages.swift -// Cork +// CorkPackagesModels // -// Created by David Bureš - P on 12.06.2025. +// Created by David Bureš - P on 28.10.2025. // import Foundation import CorkShared +import CorkTerminalFunctions -extension BrewPackagesTracker +public extension BrewPackagesTracker { /// Get the names of tagged packages as set, for fas comparing /// diff --git a/Cork/Extensions/URL - Package Name from URL.swift b/Modules/Packages/PackagesModels/Required Logic/Get Package Name from URL.swift similarity index 55% rename from Cork/Extensions/URL - Package Name from URL.swift rename to Modules/Packages/PackagesModels/Required Logic/Get Package Name from URL.swift index 9aedc47e..fa5f7328 100644 --- a/Cork/Extensions/URL - Package Name from URL.swift +++ b/Modules/Packages/PackagesModels/Required Logic/Get Package Name from URL.swift @@ -1,13 +1,13 @@ // -// URL - Package Name from URL.swift +// Get Package Name from URL.swift // Cork // -// Created by David Bureš - P on 18.01.2025. +// Created by David Bureš - P on 28.10.2025. // import Foundation -extension URL +public extension URL { func packageNameFromURL() -> String { diff --git a/Modules/Packages/PackagesModels/Trackers/Brew Packages Tracker.swift b/Modules/Packages/PackagesModels/Trackers/Brew Packages Tracker.swift index f00858f1..accb6e21 100644 --- a/Modules/Packages/PackagesModels/Trackers/Brew Packages Tracker.swift +++ b/Modules/Packages/PackagesModels/Trackers/Brew Packages Tracker.swift @@ -7,9 +7,10 @@ import Foundation import SwiftUI +import Defaults @Observable @MainActor -class BrewPackagesTracker +public class BrewPackagesTracker { var installedFormulae: BrewPackages = .init() var installedCasks: BrewPackages = .init() @@ -47,7 +48,7 @@ class BrewPackagesTracker } /// Collected errors from failed Formulae loading - var unsuccessfullyLoadedFormulaeErrors: [PackageLoadingError] + var unsuccessfullyLoadedFormulaeErrors: [BrewPackage.PackageLoadingError] { return installedFormulae.compactMap { rawResult in @@ -92,7 +93,7 @@ class BrewPackagesTracker } /// Collected errors from failed Casks loading - var unsuccessfullyLoadedCasksErrors: [PackageLoadingError] + var unsuccessfullyLoadedCasksErrors: [BrewPackage.PackageLoadingError] { return installedCasks.compactMap { rawResult in diff --git a/Cork/Logic/File System/File Browser/Misc/Check if URL is Symlink.swift b/Modules/Shared/Logic/Check if URL is Symlink.swift similarity index 86% rename from Cork/Logic/File System/File Browser/Misc/Check if URL is Symlink.swift rename to Modules/Shared/Logic/Check if URL is Symlink.swift index c4bae2d3..061df1d4 100644 --- a/Cork/Logic/File System/File Browser/Misc/Check if URL is Symlink.swift +++ b/Modules/Shared/Logic/Check if URL is Symlink.swift @@ -2,13 +2,12 @@ // Check if URL is Symlink.swift // Cork // -// Created by David Bureš on 25.02.2023. +// Created by David Bureš - P on 28.10.2025. // import Foundation -import CorkShared -extension URL +public extension URL { func isSymlink() -> Bool? { diff --git a/Cork/Logic/Package Loading/Helper Logic/Filter Symlinks.swift b/Modules/Shared/Logic/Filter Out Symlinks.swift similarity index 85% rename from Cork/Logic/Package Loading/Helper Logic/Filter Symlinks.swift rename to Modules/Shared/Logic/Filter Out Symlinks.swift index fc5ad0f2..907e3cfd 100644 --- a/Cork/Logic/Package Loading/Helper Logic/Filter Symlinks.swift +++ b/Modules/Shared/Logic/Filter Out Symlinks.swift @@ -1,13 +1,13 @@ // -// Filter Symlinks.swift +// Filter Out Symlinks.swift // Cork // -// Created by David Bureš on 13.11.2024. +// Created by David Bureš - P on 28.10.2025. // import Foundation -extension [URL] +public extension [URL] { /// Filter out all symlinks from an array of URLs var withoutSymlinks: [URL] diff --git a/Cork/Logic/Helpers/REGEX Match.swift b/Modules/Shared/Logic/REGEX Match.swift similarity index 83% rename from Cork/Logic/Helpers/REGEX Match.swift rename to Modules/Shared/Logic/REGEX Match.swift index 592a1bfc..b2a1a8e3 100644 --- a/Cork/Logic/Helpers/REGEX Match.swift +++ b/Modules/Shared/Logic/REGEX Match.swift @@ -2,16 +2,16 @@ // REGEX Match.swift // Cork // -// Created by David Bureš on 19.02.2023. +// Created by David Bureš - P on 28.10.2025. // import Foundation -enum RegexError: LocalizedError +public enum RegexError: LocalizedError { case regexFunctionCouldNotMatchAnything - var errorDescription: String? + public var errorDescription: String? { switch self { @@ -21,7 +21,7 @@ enum RegexError: LocalizedError } } -extension String +public extension String { /// Match a string according to a specified REGEX diff --git a/Cork/Logic/Shell/Shell Interface.swift b/Modules/TerminalSupport/Logic/Shell Commands.swift similarity index 98% rename from Cork/Logic/Shell/Shell Interface.swift rename to Modules/TerminalSupport/Logic/Shell Commands.swift index e9209a06..72f541f7 100644 --- a/Cork/Logic/Shell/Shell Interface.swift +++ b/Modules/TerminalSupport/Logic/Shell Commands.swift @@ -1,15 +1,15 @@ // -// Shell Interface.swift +// Shell Commands.swift // Cork // -// Created by David Bureš on 03.07.2022. +// Created by David Bureš - P on 28.10.2025. // import Foundation import CorkShared @discardableResult -func shell( +public func shell( _ launchPath: URL, _ arguments: [String], environment: [String: String]? = nil, @@ -46,7 +46,7 @@ func shell( /// // Do something with `errorLine` /// } /// } -func shell( +public func shell( _ launchPath: URL, _ arguments: [String], environment: [String: String]? = nil, @@ -166,7 +166,7 @@ func shell( } } -func shell( +public func shell( _ launchPath: URL, _ arguments: [String], environment: [String: String]? = nil, diff --git a/Modules/TerminalSupport/Models/Terminal Output.swift b/Modules/TerminalSupport/Models/Terminal Output.swift new file mode 100644 index 00000000..9ef9b847 --- /dev/null +++ b/Modules/TerminalSupport/Models/Terminal Output.swift @@ -0,0 +1,20 @@ +// +// Terminal Output.swift +// Cork +// +// Created by David Bureš - P on 28.10.2025. +// + +import Foundation + +public struct TerminalOutput +{ + public var standardOutput: String + public var standardError: String +} + +public enum StreamedTerminalOutput +{ + case standardOutput(String) + case standardError(String) +} diff --git a/Project.swift b/Project.swift index 4b62ae1e..7ff75c0e 100644 --- a/Project.swift +++ b/Project.swift @@ -33,9 +33,14 @@ func corkTarget(configureWithSelfCompiled: Bool) -> ProjectDescription.Target { .target(corkSharedTarget), .target(corkNotificationsTarget), .target(corkPackages_modelsTarget), + .target(corkPackages_logicTarget), + .target(corkTerminalFunctionsTarget), + .target(corkIntentsTarget), .external(name: "LaunchAtLogin"), .external(name: "DavidFoundation"), + .external(name: "ApplicationInspector"), .external(name: "ButtonKit"), + .external(name: "FactoryKit"), .package(product: "SwiftLintBuildToolPlugin", type: .plugin), .external(name: "Defaults"), .external(name: "DefaultsMacros") @@ -63,8 +68,15 @@ let corkSharedTarget: ProjectDescription.Target = .target( sources: [ "Modules/Shared/**/*.swift" ], + resources: [ + "Cork/**/*.xcassets", + "Cork/**/*.xcstrings", + "PrivacyInfo.xcprivacy", + "Cork/Logic/Helpers/Programs/Sudo Helper", + ], dependencies: [ - .external(name: "Defaults") + .external(name: "Defaults"), + .external(name: "FactoryKit") ], settings: .settings(configurations: [ .debug( @@ -102,6 +114,30 @@ let corkNotificationsTarget: ProjectDescription.Target = .target( ]) ) +let corkTerminalFunctionsTarget: ProjectDescription.Target = .target( + name: "CorkTerminalFunctions", + destinations: [.mac], + product: .staticLibrary, + bundleId: "eu.davidbures.cork-terminal-functions", + deploymentTargets: .macOS("14.0.0"), + sources: [ + "Modules/TerminalSupport/**/*.swift" + ], + dependencies: [ + .external(name: "FactoryKit") + ], + settings: .settings(configurations: [ + .debug( + name: "Debug", + xcconfig: .relativeToRoot("xcconfigs/Cork.xcconfig") + ), + .release( + name: "Release", + xcconfig: .relativeToRoot("xcconfigs/Cork.xcconfig") + ) + ]) +) + let corkPackages_modelsTarget: ProjectDescription.Target = .target( name: "CorkPackagesModels", destinations: [.mac], @@ -111,6 +147,69 @@ let corkPackages_modelsTarget: ProjectDescription.Target = .target( sources: [ "Modules/Packages/PackagesModels/**/*.swift" ], + resources: [ + "Cork/**/*.xcassets", + "Cork/**/*.xcstrings", + "PrivacyInfo.xcprivacy", + "Cork/Logic/Helpers/Programs/Sudo Helper", + ], + dependencies: [ + .external(name: "FactoryKit") + ], + settings: .settings(configurations: [ + .debug( + name: "Debug", + xcconfig: .relativeToRoot("xcconfigs/Cork.xcconfig") + ), + .release( + name: "Release", + xcconfig: .relativeToRoot("xcconfigs/Cork.xcconfig") + ) + ]) +) + +let corkPackages_logicTarget: ProjectDescription.Target = .target( + name: "CorkPackagesLogic", + destinations: [.mac], + product: .staticLibrary, + bundleId: "eu.davidbures.cork-packages-logic", + deploymentTargets: .macOS("14.0.0"), + sources: [ + "Modules/Packages/PackagesLogic/**/*.swift" + ], + resources: [ + "Cork/**/*.xcassets", + "Cork/**/*.xcstrings", + "PrivacyInfo.xcprivacy", + "Cork/Logic/Helpers/Programs/Sudo Helper", + ], + dependencies: [ + .external(name: "FactoryKit") + ], + settings: .settings(configurations: [ + .debug( + name: "Debug", + xcconfig: .relativeToRoot("xcconfigs/Cork.xcconfig") + ), + .release( + name: "Release", + xcconfig: .relativeToRoot("xcconfigs/Cork.xcconfig") + ) + ]) +) + +let corkIntentsTarget: ProjectDescription.Target = .target( + name: "CorkIntents", + destinations: [.mac], + product: .staticLibrary, + bundleId: "eu.davidbures.cork-intents", + deploymentTargets: .macOS("14.0.0"), + sources: [ + "Modules/Intents/**/*.swift" + ], + dependencies: [ + .external(name: "FactoryKit") + ], settings: .settings(configurations: [ .debug( name: "Debug", @@ -186,7 +285,10 @@ let project = Project( corkTarget(configureWithSelfCompiled: false), corkTarget(configureWithSelfCompiled: true), corkSharedTarget, + corkTerminalFunctionsTarget, corkPackages_modelsTarget, + corkPackages_logicTarget, + corkIntentsTarget, corkNotificationsTarget, corkHelpTarget, corkTestsTarget diff --git a/Tuist/Package.resolved b/Tuist/Package.resolved index d3e15e6a..50c1dc0f 100644 --- a/Tuist/Package.resolved +++ b/Tuist/Package.resolved @@ -1,5 +1,14 @@ { "pins" : [ + { + "identity" : "applicationinspector", + "kind" : "remoteSourceControl", + "location" : "https://github.com/buresdv/ApplicationInspector", + "state" : { + "revision" : "72d9888b3da342df026254a940553c31b72daec8", + "version" : "1.0.0" + } + }, { "identity" : "buttonkit", "kind" : "remoteSourceControl", @@ -27,6 +36,15 @@ "version" : "9.0.2" } }, + { + "identity" : "factory", + "kind" : "remoteSourceControl", + "location" : "https://github.com/hmlongco/Factory", + "state" : { + "branch" : "develop", + "revision" : "a46ce210c1535064beffd1f00caf9835507b656f" + } + }, { "identity" : "launchatlogin-modern", "kind" : "remoteSourceControl", diff --git a/Tuist/Package.swift b/Tuist/Package.swift index e059ba9f..525c591a 100644 --- a/Tuist/Package.swift +++ b/Tuist/Package.swift @@ -25,8 +25,10 @@ let package = Package( .package(url: "https://github.com/sindresorhus/LaunchAtLogin-Modern", .upToNextMajor(from: "1.0.0")), .package(url: "https://github.com/sindresorhus/Defaults", .upToNextMajor(from: "9.0.2")), .package(url: "https://github.com/buresdv/DavidFoundation", .upToNextMajor(from: "2.0.1")), + .package(url: "https://github.com/buresdv/ApplicationInspector", .upToNextMajor(from: "1.0.0")), .package(url: "https://github.com/Dean151/ButtonKit", .upToNextMajor(from: "0.6.1")), .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", .upToNextMajor(from: "0.56.1")), + .package(url: "https://github.com/hmlongco/Factory", branch: "develop") ], targets: [ .target(