mirror of https://github.com/buresdv/Cork
~ More work… (at least the errors are in the app now)
This commit is contained in:
parent
6db193811a
commit
094caff1cb
|
|
@ -1,177 +0,0 @@
|
|||
//
|
||||
// Get Contents of Folder.swift
|
||||
// Cork
|
||||
//
|
||||
// Created by David Bureš on 03.07.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkShared
|
||||
|
||||
/*
|
||||
func getContentsOfFolder(targetFolder: URL) async throws -> Set<BrewPackage>
|
||||
{
|
||||
do
|
||||
{
|
||||
guard let items = targetFolder.validPackageURLs
|
||||
else
|
||||
{
|
||||
throw PackageLoadingError.failedWhileLoadingPackages(failureReason: String(localized: "alert.fatal.could-not-filter-invalid-packages"))
|
||||
}
|
||||
|
||||
let loadedPackages: Set<BrewPackage> = try await withThrowingTaskGroup(of: BrewPackage.self, returning: Set<BrewPackage>.self)
|
||||
{ taskGroup in
|
||||
for item in items
|
||||
{
|
||||
let fullURLToPackageFolderCurrentlyBeingProcessed: URL = targetFolder.appendingPathComponent(item, conformingTo: .folder)
|
||||
|
||||
taskGroup.addTask(priority: .high)
|
||||
{
|
||||
guard let versionURLs: [URL] = fullURLToPackageFolderCurrentlyBeingProcessed.packageVersionURLs
|
||||
else
|
||||
{
|
||||
if targetFolder.appendingPathComponent(item, conformingTo: .fileURL).isDirectory
|
||||
{
|
||||
AppConstants.shared.logger.error("Failed while getting package version for package \(fullURLToPackageFolderCurrentlyBeingProcessed.lastPathComponent). Package does not have any version installed.")
|
||||
throw PackageLoadingError.packageDoesNotHaveAnyVersionsInstalled(item)
|
||||
}
|
||||
else
|
||||
{
|
||||
AppConstants.shared.logger.error("Failed while getting package version for package \(fullURLToPackageFolderCurrentlyBeingProcessed.lastPathComponent). Package is not a folder")
|
||||
throw PackageLoadingError.packageIsNotAFolder(item, targetFolder.appendingPathComponent(item, conformingTo: .fileURL))
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if versionURLs.isEmpty
|
||||
{
|
||||
throw PackageLoadingError.packageDoesNotHaveAnyVersionsInstalled(item)
|
||||
}
|
||||
|
||||
let wasPackageInstalledIntentionally: Bool = try await targetFolder.checkIfPackageWasInstalledIntentionally(versionURLs)
|
||||
|
||||
let foundPackage: BrewPackage = .init(
|
||||
name: item,
|
||||
type: targetFolder.packageType,
|
||||
installedOn: fullURLToPackageFolderCurrentlyBeingProcessed.creationDate,
|
||||
versions: versionURLs.versions,
|
||||
installedIntentionally: wasPackageInstalledIntentionally,
|
||||
sizeInBytes: fullURLToPackageFolderCurrentlyBeingProcessed.directorySize
|
||||
)
|
||||
|
||||
return foundPackage
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var loadedPackages: Set<BrewPackage> = .init()
|
||||
for try await package in taskGroup
|
||||
{
|
||||
loadedPackages.insert(package)
|
||||
}
|
||||
return loadedPackages
|
||||
}
|
||||
|
||||
return loadedPackages
|
||||
}
|
||||
catch
|
||||
{
|
||||
AppConstants.shared.logger.error("Failed while accessing folder: \(error)")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// MARK: - Sub-functions
|
||||
|
||||
private extension URL
|
||||
{
|
||||
/// ``[URL]`` to packages without hidden files or symlinks.
|
||||
/// e.g. only actual package URLs
|
||||
var validPackageURLs: [String]?
|
||||
{
|
||||
let items: [String]? = try? FileManager.default.contentsOfDirectory(atPath: path).filter { !$0.hasPrefix(".") }.filter
|
||||
{ item in
|
||||
/// Filter out all symlinks from the folder
|
||||
let completeURLtoItem: URL = self.appendingPathComponent(item, conformingTo: .folder)
|
||||
|
||||
guard let isSymlink = completeURLtoItem.isSymlink()
|
||||
else
|
||||
{
|
||||
return false
|
||||
}
|
||||
|
||||
return !isSymlink
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
/// Get URLs to a package's versions
|
||||
var packageVersionURLs: [URL]?
|
||||
{
|
||||
AppConstants.shared.logger.debug("Will check URL \(self)")
|
||||
do
|
||||
{
|
||||
let versions: [URL] = try FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: [.isHiddenKey], options: .skipsHiddenFiles)
|
||||
|
||||
if versions.isEmpty
|
||||
{
|
||||
AppConstants.shared.logger.warning("Package URL \(self, privacy: .public) has no versions installed")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
AppConstants.shared.logger.debug("URL \(self) has these versions: \(versions))")
|
||||
|
||||
return versions
|
||||
}
|
||||
catch
|
||||
{
|
||||
AppConstants.shared.logger.error("Failed while loading version for package \(lastPathComponent, privacy: .public) at URL \(self, privacy: .public)")
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension [URL]
|
||||
{
|
||||
/// Returns an array of versions from an array of URLs to available versions
|
||||
var versions: [String]
|
||||
{
|
||||
return map
|
||||
{ versionURL in
|
||||
versionURL.lastPathComponent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Getting list of URLs in folder
|
||||
|
||||
func getContentsOfFolder(targetFolder: URL, options: FileManager.DirectoryEnumerationOptions? = nil) throws -> [URL]
|
||||
{
|
||||
do
|
||||
{
|
||||
if let options
|
||||
{
|
||||
return try FileManager.default.contentsOfDirectory(at: targetFolder, includingPropertiesForKeys: nil, options: options)
|
||||
}
|
||||
else
|
||||
{
|
||||
return try FileManager.default.contentsOfDirectory(at: targetFolder, includingPropertiesForKeys: nil)
|
||||
}
|
||||
}
|
||||
catch let folderReadingError
|
||||
{
|
||||
AppConstants.shared.logger.error("\(folderReadingError.localizedDescription)")
|
||||
|
||||
throw folderReadingError
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkModels
|
||||
|
||||
func deleteCachedDownloads() throws(CachedDownloadDeletionError)
|
||||
{
|
||||
|
|
@ -15,7 +16,7 @@ func deleteCachedDownloads() throws(CachedDownloadDeletionError)
|
|||
/// This folder has the symlinks, so we have do **delete ONLY THE SYMLINKS**
|
||||
do
|
||||
{
|
||||
for url in try getContentsOfFolder(targetFolder: AppConstants.shared.brewCachedFormulaeDownloadsPath)
|
||||
for url in try AppConstants.shared.brewCachedFormulaeDownloadsPath.getContents()
|
||||
{
|
||||
if let isSymlink = url.isSymlink()
|
||||
{
|
||||
|
|
@ -47,7 +48,7 @@ func deleteCachedDownloads() throws(CachedDownloadDeletionError)
|
|||
/// This folder has the symlinks, so we have to **delete ONLY THE SYMLINKS**
|
||||
do
|
||||
{
|
||||
for url in try getContentsOfFolder(targetFolder: AppConstants.shared.brewCachedCasksDownloadsPath)
|
||||
for url in try AppConstants.shared.brewCachedCasksDownloadsPath.getContents()
|
||||
{
|
||||
if let isSymlink = url.isSymlink()
|
||||
{
|
||||
|
|
@ -79,7 +80,7 @@ func deleteCachedDownloads() throws(CachedDownloadDeletionError)
|
|||
/// This folder has the downloads themselves, so we have do **DELETE EVERYTHING THAT IS NOT A SYMLINK**
|
||||
do
|
||||
{
|
||||
for url in try getContentsOfFolder(targetFolder: AppConstants.shared.brewCachedDownloadsPath)
|
||||
for url in try AppConstants.shared.brewCachedDownloadsPath.getContents()
|
||||
{
|
||||
if let isSymlink = url.isSymlink()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
//
|
||||
// Load up Installed Packages.swift
|
||||
// Cork
|
||||
//
|
||||
// Created by David Bureš on 11.02.2023.
|
||||
//
|
||||
|
||||
import CorkShared
|
||||
import Foundation
|
||||
|
||||
/*
|
||||
@MainActor
|
||||
func loadUpPackages(whatToLoad: BrewPackage.PackageType, appState: AppState) async -> Set<BrewPackage>
|
||||
{
|
||||
AppConstants.shared.logger.info("Started \(whatToLoad == .formula ? "Formula" : "Cask", privacy: .public) loading task at \(Date(), privacy: .public)")
|
||||
|
||||
var contentsOfFolder: Set<BrewPackage> = .init()
|
||||
|
||||
do
|
||||
{
|
||||
switch whatToLoad
|
||||
{
|
||||
case .formula:
|
||||
contentsOfFolder = try await getContentsOfFolder(targetFolder: AppConstants.shared.brewCellarPath)
|
||||
case .cask:
|
||||
contentsOfFolder = try await getContentsOfFolder(targetFolder: AppConstants.shared.brewCaskPath)
|
||||
}
|
||||
}
|
||||
catch let packageLoadingError as PackageLoadingError
|
||||
{
|
||||
switch packageLoadingError
|
||||
{
|
||||
case .couldNotReadContentsOfParentFolder(let failureReason):
|
||||
appState.showAlert(errorToShow: .couldNotGetContentsOfPackageFolder(failureReason))
|
||||
case .failedWhileLoadingPackages:
|
||||
appState.showAlert(errorToShow: .couldNotLoadAnyPackages(packageLoadingError))
|
||||
case .failedWhileLoadingCertainPackage(let offendingPackage, let offendingPackageURL, let failureReason):
|
||||
appState.showAlert(errorToShow: .couldNotLoadCertainPackage(offendingPackage, offendingPackageURL, failureReason: failureReason))
|
||||
case .packageDoesNotHaveAnyVersionsInstalled(let offendingPackage):
|
||||
appState.showAlert(errorToShow: .installedPackageHasNoVersions(corruptedPackageName: offendingPackage))
|
||||
case .packageIsNotAFolder(let offendingFile, let offendingFileURL):
|
||||
appState.showAlert(errorToShow: .installedPackageIsNotAFolder(itemName: offendingFile, itemURL: offendingFileURL))
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Something got completely fucked up while loading packages")
|
||||
}
|
||||
|
||||
AppConstants.shared.logger.info("Finished \(whatToLoad == .formula ? "Formula" : "Cask", privacy: .public) loading task at \(Date(), privacy: .auto)")
|
||||
|
||||
return contentsOfFolder
|
||||
}
|
||||
*/
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
|
||||
extension ServicesTracker
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
|
||||
extension ServicesTracker
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
|
||||
enum ServiceStoppingError: LocalizedError
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
|
||||
extension HomebrewService
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
import CorkModels
|
||||
|
||||
@MainActor
|
||||
func refreshPackages(_ updateProgressTracker: UpdateProgressTracker, outdatedPackagesTracker: OutdatedPackagesTracker) async -> PackageUpdateAvailability
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
|
||||
@MainActor
|
||||
func updatePackages(updateProgressTracker: UpdateProgressTracker, detailStage: UpdatingProcessDetails) async
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import SwiftUI
|
|||
import CorkShared
|
||||
import Defaults
|
||||
import DefaultsMacros
|
||||
import CorkModels
|
||||
|
||||
@Observable @MainActor
|
||||
class TopPackagesTracker
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkModels
|
||||
import CorkTerminalFunctions
|
||||
|
||||
@Observable
|
||||
class InstallationProgressTracker
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import CorkModels
|
||||
|
||||
struct RealTimeTerminalLine: Identifiable, Hashable, Equatable
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
//
|
||||
// Brew Package Details.swift
|
||||
// Cork
|
||||
//
|
||||
// Created by David Bureš on 18.07.2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
|
||||
enum PinningUnpinningError: LocalizedError
|
||||
{
|
||||
case failedWhileChangingPinnedStatus
|
||||
|
||||
var errorDescription: String?
|
||||
{
|
||||
switch self
|
||||
{
|
||||
case .failedWhileChangingPinnedStatus:
|
||||
return String(localized: "error.package-details.couldnt-pin-unpin")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Observable @MainActor
|
||||
class BrewPackageDetails
|
||||
{
|
||||
// MARK: - Immutable properties
|
||||
|
||||
/// Name of the package
|
||||
let name: String
|
||||
|
||||
let description: String?
|
||||
|
||||
let homepage: URL
|
||||
let tap: BrewTap
|
||||
let installedAsDependency: Bool
|
||||
let dependencies: [BrewPackageDependency]?
|
||||
let outdated: Bool
|
||||
let caveats: String?
|
||||
|
||||
let deprecated: Bool
|
||||
let deprecationReason: String?
|
||||
|
||||
let isCompatible: Bool?
|
||||
|
||||
var dependents: [String]?
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
init(
|
||||
name: String,
|
||||
description: String?,
|
||||
homepage: URL,
|
||||
tap: BrewTap,
|
||||
installedAsDependency: Bool,
|
||||
dependents: [String]? = nil,
|
||||
dependencies: [BrewPackageDependency]? = nil,
|
||||
outdated: Bool,
|
||||
caveats: String? = nil,
|
||||
deprecated: Bool,
|
||||
deprecationReason: String? = nil,
|
||||
isCompatible: Bool?
|
||||
){
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.homepage = homepage
|
||||
self.tap = tap
|
||||
self.installedAsDependency = installedAsDependency
|
||||
self.dependents = dependents
|
||||
self.dependencies = dependencies
|
||||
self.outdated = outdated
|
||||
self.deprecated = deprecated
|
||||
self.deprecationReason = deprecationReason
|
||||
self.caveats = caveats
|
||||
self.isCompatible = isCompatible
|
||||
}
|
||||
|
||||
// MARK: - Functions
|
||||
|
||||
func loadDependents() async
|
||||
{
|
||||
AppConstants.shared.logger.debug("Will load dependents for \(self.name)")
|
||||
let packageDependentsRaw: String = await shell(AppConstants.shared.brewExecutablePath, ["uses", "--installed", name]).standardOutput
|
||||
|
||||
let finalDependents: [String] = packageDependentsRaw.components(separatedBy: "\n").dropLast()
|
||||
|
||||
AppConstants.shared.logger.debug("Dependents loaded: \(finalDependents)")
|
||||
|
||||
dependents = finalDependents
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// Package Dependency.swift
|
||||
// Cork
|
||||
//
|
||||
// Created by David Bureš on 27.02.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct BrewPackageDependency: Identifiable, Hashable
|
||||
{
|
||||
let id: UUID = .init()
|
||||
let name: String
|
||||
let version: String
|
||||
let directlyDeclared: Bool
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import CorkModels
|
||||
|
||||
@Observable
|
||||
class SearchResultTracker
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
protocol DismissablePane: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import ButtonKit
|
|||
import CorkNotifications
|
||||
import CorkShared
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
struct MenuBar_OrphanCleanup: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
struct MenuBar_PackageInstallation: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
struct PackagePreview: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
import CorkShared
|
||||
import Defaults
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
struct BasicPackageInfoView: View
|
||||
{
|
||||
@Default(.caveatDisplayOptions) var caveatDisplayOptions: PackageCaveatDisplay
|
||||
|
||||
let package: BrewPackage
|
||||
let packageDetails: BrewPackageDetails
|
||||
let packageDetails: BrewPackage.BrewPackageDetails
|
||||
|
||||
let isLoadingDetails: Bool
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import Defaults
|
||||
import CorkModels
|
||||
|
||||
struct DependencyList: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import ButtonKit
|
||||
import CorkModels
|
||||
|
||||
struct PinUnpinButton: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkShared
|
||||
import CorkModels
|
||||
import CorkTerminalFunctions
|
||||
|
||||
struct ReinstallCorruptedPackageView: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import SwiftUI
|
|||
import CorkShared
|
||||
import ButtonKit
|
||||
import Defaults
|
||||
import CorkModels
|
||||
|
||||
/// Button for uninstalling packages
|
||||
struct UninstallPackageButton: View
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
struct UninstallationProgressWheel: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
/// Package name that contains only the name of the package, not its version in the `package@version` format
|
||||
struct SanitizedPackageName: View
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import SwiftUI
|
||||
import CorkShared
|
||||
import Defaults
|
||||
import CorkModels
|
||||
|
||||
struct PackageAndTapOverviewBox: View
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum CachedDownloadDeletionError: LocalizedError
|
||||
public enum CachedDownloadDeletionError: LocalizedError
|
||||
{
|
||||
case couldNotReadContentsOfCachedFormulaeDownloadsFolder(associatedError: String)
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ enum CachedDownloadDeletionError: LocalizedError
|
|||
|
||||
case couldNotReadContentsOfCachedDownloadsFolder(associatedError: String)
|
||||
|
||||
var errorDescription: String?
|
||||
public var errorDescription: String?
|
||||
{
|
||||
switch self
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
enum PackageSynchronizationError: LocalizedError
|
||||
public enum PackageSynchronizationError: LocalizedError
|
||||
{
|
||||
case synchronizationReturnedNil
|
||||
|
||||
var errorDescription: String?
|
||||
public var errorDescription: String?
|
||||
{
|
||||
switch self
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkModels
|
||||
|
||||
extension CachedDownloadsTracker
|
||||
public extension CachedDownloadsTracker
|
||||
{
|
||||
/// Load cached downloads and assign their types
|
||||
@MainActor
|
||||
|
|
@ -8,8 +8,9 @@
|
|||
import CorkShared
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkTerminalFunctions
|
||||
|
||||
extension BrewPackagesTracker
|
||||
public extension BrewPackagesTracker
|
||||
{
|
||||
@MainActor
|
||||
func uninstallSelectedPackage(
|
||||
|
|
|
|||
|
|
@ -8,12 +8,13 @@
|
|||
import CorkShared
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import CorkModels
|
||||
|
||||
extension BrewPackagesTracker
|
||||
public extension BrewPackagesTracker
|
||||
{
|
||||
/// Synchronizes installed packages and cached downloads
|
||||
func synchronizeInstalledPackages(cachedDownloadsTracker: CachedDownloadsTracker) async throws(PackageSynchronizationError)
|
||||
func synchronizeInstalledPackages(
|
||||
cachedDownloadsTracker: CachedDownloadsTracker
|
||||
) async throws(PackageSynchronizationError)
|
||||
{
|
||||
AppConstants.shared.logger.debug("Will start synchronization process")
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import SwiftUI
|
|||
import CorkModels
|
||||
import CorkTerminalFunctions
|
||||
|
||||
enum OutdatedPackageRetrievalError: LocalizedError
|
||||
public enum OutdatedPackageRetrievalError: LocalizedError
|
||||
{
|
||||
case homeNotSet, couldNotDecodeCommandOutput(String), otherError(String)
|
||||
|
||||
var errorDescription: String?
|
||||
public var errorDescription: String?
|
||||
{
|
||||
switch self
|
||||
{
|
||||
|
|
@ -29,7 +29,7 @@ enum OutdatedPackageRetrievalError: LocalizedError
|
|||
}
|
||||
}
|
||||
|
||||
extension OutdatedPackagesTracker
|
||||
public extension OutdatedPackagesTracker
|
||||
{
|
||||
/// This struct alows us to parse the JSON output of the outdated package function. It is not used outside this function
|
||||
fileprivate struct OutdatedPackageCommandOutput: Codable
|
||||
|
|
@ -78,7 +78,10 @@ extension OutdatedPackagesTracker
|
|||
}
|
||||
|
||||
/// Load outdated packages into the outdated package tracker
|
||||
private func getOutdatedPackagesInternal(brewPackagesTracker: BrewPackagesTracker, forUpdatingType updatingType: OutdatedPackage.PackageUpdatingType) async throws -> Set<OutdatedPackage>
|
||||
private nonisolated func getOutdatedPackagesInternal(
|
||||
brewPackagesTracker: BrewPackagesTracker,
|
||||
forUpdatingType updatingType: OutdatedPackage.PackageUpdatingType
|
||||
) async throws -> Set<OutdatedPackage>
|
||||
{
|
||||
// First, we have to pull the newest updates
|
||||
await shell(AppConstants.shared.brewExecutablePath, ["update"])
|
||||
|
|
@ -137,13 +140,17 @@ extension OutdatedPackagesTracker
|
|||
|
||||
// MARK: - Helper functions
|
||||
|
||||
private func getOutdatedFormulae(from intermediaryArray: [OutdatedPackageCommandOutput.Formulae], brewPackagesTracker: BrewPackagesTracker, forUpdatingType updatingType: OutdatedPackage.PackageUpdatingType) async -> Set<OutdatedPackage>
|
||||
private nonisolated func getOutdatedFormulae(
|
||||
from intermediaryArray: [OutdatedPackageCommandOutput.Formulae],
|
||||
brewPackagesTracker: BrewPackagesTracker,
|
||||
forUpdatingType updatingType: OutdatedPackage.PackageUpdatingType
|
||||
) async -> Set<OutdatedPackage>
|
||||
{
|
||||
var finalOutdatedFormulaTracker: Set<OutdatedPackage> = .init()
|
||||
|
||||
for outdatedFormula in intermediaryArray
|
||||
{
|
||||
if let foundOutdatedFormula = brewPackagesTracker.successfullyLoadedFormulae.first(where: { $0.name == outdatedFormula.name })
|
||||
if let foundOutdatedFormula = await brewPackagesTracker.successfullyLoadedFormulae.first(where: { $0.name == outdatedFormula.name })
|
||||
{
|
||||
finalOutdatedFormulaTracker.insert(.init(
|
||||
package: foundOutdatedFormula,
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
import Foundation
|
||||
import CorkModels
|
||||
|
||||
extension URL
|
||||
public extension URL
|
||||
{
|
||||
/// Determine a package's type type from its URL
|
||||
var packageType: BrewPackage.PackageType
|
||||
|
|
@ -7,9 +7,8 @@
|
|||
|
||||
import CorkShared
|
||||
import Foundation
|
||||
import CorkModels
|
||||
|
||||
extension BrewPackagesTracker
|
||||
public extension BrewPackagesTracker
|
||||
{
|
||||
/// Parent function for loading installed packages from disk
|
||||
/// Abstracts away the function ``loadInstalledPackagesFromFolder(packageTypeToLoad:)``, transforming errors thrown by ``loadInstalledPackagesFromFolder(packageTypeToLoad:)`` into displayable errors
|
||||
|
|
@ -17,7 +16,7 @@ extension BrewPackagesTracker
|
|||
/// - packageTypeToLoad: Which ``PackageType`` to load
|
||||
/// - appState: ``AppState`` used to display loading errors
|
||||
/// - Returns: A set of loaded ``BrewPackage``s for the specified ``PackageType``
|
||||
public func loadInstalledPackages(
|
||||
func loadInstalledPackages(
|
||||
packageTypeToLoad: BrewPackage.PackageType, appState: AppState
|
||||
) async -> BrewPackages?
|
||||
{
|
||||
|
|
@ -91,7 +90,7 @@ private extension BrewPackagesTracker
|
|||
{
|
||||
/// This gets URLs to all package folders in a folder.
|
||||
/// `/opt/homebrew/Caskroom/microsoft-edge/`
|
||||
let urlsInParentFolder: [URL] = try getContentsOfFolder(targetFolder: packageTypeToLoad.parentFolder, options: [.skipsHiddenFiles])
|
||||
let urlsInParentFolder: [URL] = try packageTypeToLoad.parentFolder.getContents(options: [.skipsHiddenFiles])
|
||||
|
||||
AppConstants.shared.logger.debug("Loaded contents of folder: \(urlsInParentFolder)")
|
||||
|
||||
|
|
@ -207,7 +206,7 @@ private extension BrewPackagesTracker
|
|||
{
|
||||
/// Gets URL to installed versions of a package provided as ``packageURL``
|
||||
/// `/opt/homebrew/Cellar/cmake/3.30.5`, `/opt/homebrew/Cellar/cmake/3.30.4`
|
||||
let versionURLs: [URL] = try getContentsOfFolder(targetFolder: packageURL, options: [.skipsHiddenFiles])
|
||||
let versionURLs: [URL] = try packageURL.getContents(options: [.skipsHiddenFiles])
|
||||
|
||||
guard !versionURLs.isEmpty
|
||||
else
|
||||
|
|
@ -8,9 +8,8 @@
|
|||
import CorkShared
|
||||
import Foundation
|
||||
import SwiftData
|
||||
import CorkModels
|
||||
|
||||
extension BrewPackagesTracker
|
||||
public extension BrewPackagesTracker
|
||||
{
|
||||
enum AdoptableCasksLoadingError: LocalizedError
|
||||
{
|
||||
|
|
@ -38,6 +37,7 @@ extension BrewPackagesTracker
|
|||
}
|
||||
|
||||
/// Get a list of casks that can be adopted into the Homebrew updating mechanism
|
||||
nonisolated
|
||||
func getAdoptableCasks(
|
||||
cacheUsePolicy: HomebrewDataCacheUsePolicy
|
||||
) async throws(AdoptableCasksLoadingError) -> [AdoptableApp]
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import CorkShared
|
||||
import Foundation
|
||||
import CorkModels
|
||||
import CorkTerminalFunctions
|
||||
|
||||
enum BrewPackageInfoLoadingError: LocalizedError
|
||||
|
|
@ -258,7 +257,7 @@ extension BrewPackage
|
|||
|
||||
/// Load package details
|
||||
@MainActor
|
||||
func loadDetails() async throws -> BrewPackageDetails
|
||||
func loadDetails() async throws -> BrewPackage.BrewPackageDetails
|
||||
{
|
||||
let decoder: JSONDecoder = {
|
||||
let decoder: JSONDecoder = .init()
|
||||
|
|
@ -18,7 +18,7 @@ public extension TapTracker
|
|||
|
||||
do
|
||||
{
|
||||
let contentsOfTapFolder: [URL] = try getContentsOfFolder(targetFolder: AppConstants.shared.tapPath, options: .skipsHiddenFiles)
|
||||
let contentsOfTapFolder: [URL] = try AppConstants.shared.tapPath.getContents(options: .skipsHiddenFiles)
|
||||
|
||||
AppConstants.shared.logger.debug("Contents of tap folder: \(contentsOfTapFolder)")
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ public extension TapTracker
|
|||
|
||||
do
|
||||
{
|
||||
let contentsOfTapRepoParent: [URL] = try getContentsOfFolder(targetFolder: tapRepoParentURL, options: .skipsHiddenFiles)
|
||||
let contentsOfTapRepoParent: [URL] = try tapRepoParentURL.getContents(options: .skipsHiddenFiles)
|
||||
|
||||
for repoURL in contentsOfTapRepoParent
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import CorkModels
|
||||
|
||||
extension BrewPackagesTracker
|
||||
public extension BrewPackagesTracker
|
||||
{
|
||||
/// Update a ``BrewPackage``'s property in-place
|
||||
/// Used to update the UI when a property on ``BrewPackage`` changes
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Get Contents of Folder.swift
|
||||
// Cork
|
||||
//
|
||||
// Created by David Bureš - P on 09.11.2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
|
||||
public extension URL
|
||||
{
|
||||
/// Get the contents of a folder as a list of URLs to items in it
|
||||
func getContents(
|
||||
options: FileManager.DirectoryEnumerationOptions? = nil
|
||||
) throws -> [URL]
|
||||
{
|
||||
do
|
||||
{
|
||||
if let options
|
||||
{
|
||||
return try FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: nil, options: options)
|
||||
}
|
||||
else
|
||||
{
|
||||
return try FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: nil)
|
||||
}
|
||||
}
|
||||
catch let folderReadingError
|
||||
{
|
||||
AppConstants.shared.logger.error("\(folderReadingError.localizedDescription)")
|
||||
|
||||
throw folderReadingError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,16 +22,27 @@ public typealias BrewPackages = Set<Result<BrewPackage, BrewPackage.PackageLoadi
|
|||
/// A representation of a Homebrew package
|
||||
public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable
|
||||
{
|
||||
public init(name: String, type: BrewPackage.PackageType, installedOn: Date?, versions: [String], url: URL?, sizeInBytes: Int64?, downloadCount: Int?) {
|
||||
public init(
|
||||
name: String,
|
||||
type: BrewPackage.PackageType,
|
||||
isTagged: Bool? = nil,
|
||||
isPinned: Bool? = nil,
|
||||
installedOn: Date?,
|
||||
versions: [String],
|
||||
url: URL?,
|
||||
installedIntentionally: Bool? = nil,
|
||||
sizeInBytes: Int64?,
|
||||
downloadCount: Int?
|
||||
) {
|
||||
self.id = .init()
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.isTagged = false
|
||||
self.isPinned = false
|
||||
self.isTagged = isTagged ?? false
|
||||
self.isPinned = isPinned ?? false
|
||||
self.installedOn = installedOn
|
||||
self.versions = versions
|
||||
self.url = url
|
||||
self.installedIntentionally = true
|
||||
self.installedIntentionally = self.type == .cask ? true : installedIntentionally ?? false // If the package is cask, it was installed intentionally. If it's a formula, check if an override was provided, and if not, set it to false
|
||||
self.sizeInBytes = sizeInBytes
|
||||
self.downloadCount = downloadCount
|
||||
self.isBeingModified = false
|
||||
|
|
@ -43,14 +54,14 @@ public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable
|
|||
let type: PackageType
|
||||
var isTagged: Bool = false
|
||||
|
||||
public var isPinned: Bool = false
|
||||
public var isPinned: Bool
|
||||
|
||||
public let installedOn: Date?
|
||||
public let versions: [String]
|
||||
|
||||
public let url: URL?
|
||||
|
||||
public var installedIntentionally: Bool = true
|
||||
public var installedIntentionally: Bool
|
||||
|
||||
public let sizeInBytes: Int64?
|
||||
|
||||
|
|
@ -177,7 +188,7 @@ public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable
|
|||
isTagged.toggle()
|
||||
}
|
||||
|
||||
enum PinnedStatus
|
||||
public enum PinnedStatus
|
||||
{
|
||||
case pinned
|
||||
case unpinned
|
||||
|
|
@ -188,7 +199,7 @@ public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable
|
|||
/// Optionally specify which status to change the package to.
|
||||
///
|
||||
/// This function only changes the pinned status in the UI. Use the function ``performPinnedStatusChangeAction(appState:brewPackagesTracker:)`` to trigger a pinned status change in Homebrew.
|
||||
mutating func changePinnedStatus(to status: PinnedStatus? = nil)
|
||||
public mutating func changePinnedStatus(to status: PinnedStatus? = nil)
|
||||
{
|
||||
if let status
|
||||
{
|
||||
|
|
@ -208,7 +219,7 @@ public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable
|
|||
/// Perform a pinned status change in Homebrew.
|
||||
///
|
||||
/// For changing the pinned status of the package in the UI, use the function ``changePinnedStatus(to:)``
|
||||
func performPinnedStatusChangeAction(appState: AppState, brewPackagesTracker: BrewPackagesTracker) async
|
||||
public func performPinnedStatusChangeAction(appState: AppState, brewPackagesTracker: BrewPackagesTracker) async
|
||||
{
|
||||
/// We need to get the number of packages that were pinned before the action, because if there's only one and it gets unpinned, the whole folder with pinned packages is deleted - therefore, there would be a bug where unpinning the last package would make it seem like the whole process failed
|
||||
async let numberOfPinnedPackagesBeforePinChangeAction: Int = await brewPackagesTracker.successfullyLoadedFormulae.filter { $0.isPinned }.count
|
||||
|
|
@ -257,7 +268,7 @@ public struct BrewPackage: Identifiable, Equatable, Hashable, Codable, Sendable
|
|||
await brewPackagesTracker.applyPinnedStatus(namesOfPinnedPackages: brewPackagesTracker.getNamesOfPinnedPackages(atPinnedPackagesPath: pinnedPackagesPath))
|
||||
}
|
||||
|
||||
mutating func changeBeingModifiedStatus(to setState: Bool? = nil)
|
||||
public mutating func changeBeingModifiedStatus(to setState: Bool? = nil)
|
||||
{
|
||||
let packageName: String = self.name
|
||||
|
||||
|
|
|
|||
|
|
@ -9,23 +9,23 @@ import Charts
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct CachedDownload: Identifiable, Hashable
|
||||
public struct CachedDownload: Identifiable, Hashable
|
||||
{
|
||||
var id: UUID = .init()
|
||||
public var id: UUID = .init()
|
||||
|
||||
let packageName: String
|
||||
let sizeInBytes: Int
|
||||
public let packageName: String
|
||||
public let sizeInBytes: Int
|
||||
|
||||
var packageType: CachedDownload.CachedDownloadType?
|
||||
public var packageType: CachedDownload.CachedDownloadType?
|
||||
|
||||
enum CachedDownloadType: String, CustomStringConvertible, Plottable
|
||||
public enum CachedDownloadType: String, CustomStringConvertible, Plottable
|
||||
{
|
||||
case formula
|
||||
case cask
|
||||
case other
|
||||
case unknown
|
||||
|
||||
var description: String
|
||||
public var description: String
|
||||
{
|
||||
switch self
|
||||
{
|
||||
|
|
@ -40,7 +40,7 @@ struct CachedDownload: Identifiable, Hashable
|
|||
}
|
||||
}
|
||||
|
||||
var color: Color
|
||||
public var color: Color
|
||||
{
|
||||
switch self
|
||||
{
|
||||
|
|
@ -7,11 +7,9 @@
|
|||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkModels
|
||||
|
||||
extension CachedDownloadsTracker
|
||||
{
|
||||
@MainActor
|
||||
func assignPackageTypeToCachedDownloads(brewPackagesTracker: BrewPackagesTracker)
|
||||
{
|
||||
var cachedDownloadsTracker: [CachedDownload] = .init()
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public struct OutdatedPackage: Identifiable, Equatable, Hashable
|
||||
public struct OutdatedPackage: Identifiable, Equatable, Hashable, Sendable
|
||||
{
|
||||
public init(package: BrewPackage, installedVersions: [String], newerVersion: String, updatingManagedBy: PackageUpdatingType) {
|
||||
self.package = package
|
||||
|
|
@ -17,7 +17,7 @@ public struct OutdatedPackage: Identifiable, Equatable, Hashable
|
|||
self.updatingManagedBy = updatingManagedBy
|
||||
}
|
||||
|
||||
public enum PackageUpdatingType
|
||||
public enum PackageUpdatingType: Sendable
|
||||
{
|
||||
/// The package is updating through Homebrew
|
||||
case homebrew
|
||||
|
|
@ -46,7 +46,7 @@ public struct OutdatedPackage: Identifiable, Equatable, Hashable
|
|||
|
||||
public var isMarkedForUpdating: Bool
|
||||
|
||||
public var updatingManagedBy: PackageUpdatingType
|
||||
public let updatingManagedBy: PackageUpdatingType
|
||||
|
||||
public static func == (lhs: OutdatedPackage, rhs: OutdatedPackage) -> Bool
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,24 +11,24 @@ import Defaults
|
|||
import DefaultsMacros
|
||||
|
||||
@Observable @MainActor
|
||||
class OutdatedPackagesTracker
|
||||
public class OutdatedPackagesTracker
|
||||
{
|
||||
@ObservableDefault(.displayOnlyIntentionallyInstalledPackagesByDefault) @ObservationIgnored var displayOnlyIntentionallyInstalledPackagesByDefault: Bool
|
||||
|
||||
@ObservableDefault(.includeGreedyOutdatedPackages) @ObservationIgnored var includeGreedyOutdatedPackages: Bool
|
||||
|
||||
enum OutdatedPackageDisplayStage: Equatable
|
||||
public enum OutdatedPackageDisplayStage: Equatable
|
||||
{
|
||||
case checkingForUpdates, showingOutdatedPackages, noUpdatesAvailable, erroredOut(reason: String)
|
||||
}
|
||||
|
||||
var isCheckingForPackageUpdates: Bool = true
|
||||
public var isCheckingForPackageUpdates: Bool = true
|
||||
|
||||
var outdatedPackages: Set<OutdatedPackage> = .init()
|
||||
public var outdatedPackages: Set<OutdatedPackage> = .init()
|
||||
|
||||
var errorOutReason: String?
|
||||
public var errorOutReason: String?
|
||||
|
||||
var displayableOutdatedPackages: Set<OutdatedPackage>
|
||||
public var displayableOutdatedPackages: Set<OutdatedPackage>
|
||||
{
|
||||
/// Depending on whether greedy updating is enabled:
|
||||
/// - If enabled, include packages that are also self-updating
|
||||
|
|
@ -54,7 +54,7 @@ class OutdatedPackagesTracker
|
|||
}
|
||||
}
|
||||
|
||||
var outdatedPackageDisplayStage: OutdatedPackageDisplayStage
|
||||
public var outdatedPackageDisplayStage: OutdatedPackageDisplayStage
|
||||
{
|
||||
if let errorOutReason
|
||||
{
|
||||
|
|
@ -78,16 +78,13 @@ class OutdatedPackagesTracker
|
|||
}
|
||||
}
|
||||
|
||||
extension OutdatedPackagesTracker
|
||||
public extension OutdatedPackagesTracker
|
||||
{
|
||||
func setOutdatedPackages(to packages: Set<OutdatedPackage>)
|
||||
{
|
||||
self.outdatedPackages = packages
|
||||
}
|
||||
}
|
||||
|
||||
extension OutdatedPackagesTracker
|
||||
{
|
||||
func checkForUpdates()
|
||||
{
|
||||
self.errorOutReason = nil
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// Brew Package details.swift
|
||||
// CorkModels
|
||||
//
|
||||
// Created by David Bureš - P on 10.11.2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CorkShared
|
||||
import CorkTerminalFunctions
|
||||
|
||||
enum PinningUnpinningError: LocalizedError
|
||||
{
|
||||
case failedWhileChangingPinnedStatus
|
||||
|
||||
var errorDescription: String?
|
||||
{
|
||||
switch self
|
||||
{
|
||||
case .failedWhileChangingPinnedStatus:
|
||||
return String(localized: "error.package-details.couldnt-pin-unpin")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension BrewPackage
|
||||
{
|
||||
/// MOre information about this Homebrew package
|
||||
@Observable @MainActor
|
||||
class BrewPackageDetails
|
||||
{
|
||||
// MARK: - Immutable properties
|
||||
|
||||
/// Name of the package
|
||||
public let name: String
|
||||
|
||||
public let description: String?
|
||||
|
||||
public let homepage: URL
|
||||
public let tap: BrewTap
|
||||
public let installedAsDependency: Bool
|
||||
public let dependencies: [BrewPackageDependency]?
|
||||
public let outdated: Bool
|
||||
public let caveats: String?
|
||||
|
||||
public let deprecated: Bool
|
||||
public let deprecationReason: String?
|
||||
|
||||
public let isCompatible: Bool?
|
||||
|
||||
public var dependents: [String]?
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
public init(
|
||||
name: String,
|
||||
description: String?,
|
||||
homepage: URL,
|
||||
tap: BrewTap,
|
||||
installedAsDependency: Bool,
|
||||
dependents: [String]? = nil,
|
||||
dependencies: [BrewPackageDependency]? = nil,
|
||||
outdated: Bool,
|
||||
caveats: String? = nil,
|
||||
deprecated: Bool,
|
||||
deprecationReason: String? = nil,
|
||||
isCompatible: Bool?
|
||||
){
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.homepage = homepage
|
||||
self.tap = tap
|
||||
self.installedAsDependency = installedAsDependency
|
||||
self.dependents = dependents
|
||||
self.dependencies = dependencies
|
||||
self.outdated = outdated
|
||||
self.deprecated = deprecated
|
||||
self.deprecationReason = deprecationReason
|
||||
self.caveats = caveats
|
||||
self.isCompatible = isCompatible
|
||||
}
|
||||
|
||||
// MARK: - Functions
|
||||
|
||||
public func loadDependents() async
|
||||
{
|
||||
AppConstants.shared.logger.debug("Will load dependents for \(self.name)")
|
||||
let packageDependentsRaw: String = await shell(AppConstants.shared.brewExecutablePath, ["uses", "--installed", name]).standardOutput
|
||||
|
||||
let finalDependents: [String] = packageDependentsRaw.components(separatedBy: "\n").dropLast()
|
||||
|
||||
AppConstants.shared.logger.debug("Dependents loaded: \(finalDependents)")
|
||||
|
||||
dependents = finalDependents
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Package Dependency.swift
|
||||
// Cork
|
||||
//
|
||||
// Created by David Bureš on 27.02.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct BrewPackageDependency: Identifiable, Hashable
|
||||
{
|
||||
public init(
|
||||
name: String,
|
||||
version: String,
|
||||
directlyDeclared: Bool
|
||||
) {
|
||||
self.id = .init()
|
||||
self.name = name
|
||||
self.version = version
|
||||
self.directlyDeclared = directlyDeclared
|
||||
}
|
||||
|
||||
public let id: UUID
|
||||
public let name: String
|
||||
public let version: String
|
||||
public let directlyDeclared: Bool
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ public class BrewPackagesTracker
|
|||
}
|
||||
}
|
||||
|
||||
extension BrewPackagesTracker
|
||||
public extension BrewPackagesTracker
|
||||
{
|
||||
|
||||
var numberOfInstalledFormulae: Int
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ import SwiftUI
|
|||
import CorkShared
|
||||
|
||||
@Observable @MainActor
|
||||
class CachedDownloadsTracker
|
||||
public class CachedDownloadsTracker
|
||||
{
|
||||
var cachedDownloads: [CachedDownload] = .init()
|
||||
public var cachedDownloads: [CachedDownload] = .init()
|
||||
|
||||
private var cachedDownloadsTemp: [CachedDownload] = .init()
|
||||
|
||||
/// Calculate the size of the cached downloads dynamically without accessing the file system for the operation
|
||||
var cachedDownloadsSize: Int
|
||||
public var cachedDownloadsSize: Int
|
||||
{
|
||||
return cachedDownloads.reduce(0) { $0 + $1.sizeInBytes }
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
extension URL
|
||||
public extension URL
|
||||
{
|
||||
var directorySize: Int64
|
||||
{
|
||||
|
|
@ -5,14 +5,13 @@
|
|||
// Created by David Bureš on 19.08.2023.
|
||||
//
|
||||
|
||||
import CorkShared
|
||||
import Foundation
|
||||
|
||||
enum DataDownloadingError: LocalizedError
|
||||
public enum DataDownloadingError: LocalizedError
|
||||
{
|
||||
case invalidResponseCode(responseCode: Int?), noDataReceived, invalidURL, couldntExecuteRequest(error: String)
|
||||
|
||||
var errorDescription: String?
|
||||
public var errorDescription: String?
|
||||
{
|
||||
switch self
|
||||
{
|
||||
|
|
@ -35,7 +34,7 @@ enum DataDownloadingError: LocalizedError
|
|||
}
|
||||
}
|
||||
|
||||
func downloadDataFromURL(
|
||||
public func downloadDataFromURL(
|
||||
_ url: URL,
|
||||
parameters: [URLQueryItem]? = nil,
|
||||
cachingPolicy: URLRequest.CachePolicy = .useProtocolCachePolicy
|
||||
|
|
@ -11,6 +11,14 @@ public struct TerminalOutput
|
|||
{
|
||||
public var standardOutput: String
|
||||
public var standardError: String
|
||||
|
||||
public init(
|
||||
standardOutput: String,
|
||||
standardError: String
|
||||
) {
|
||||
self.standardOutput = standardOutput
|
||||
self.standardError = standardError
|
||||
}
|
||||
}
|
||||
|
||||
public enum StreamedTerminalOutput
|
||||
|
|
|
|||
|
|
@ -156,7 +156,9 @@ let corkModelsTarget: ProjectDescription.Target = .target(
|
|||
dependencies: [
|
||||
.target(corkSharedTarget),
|
||||
.target(corkNotificationsTarget),
|
||||
.external(name: "FactoryKit")
|
||||
.external(name: "FactoryKit"),
|
||||
.external(name: "Defaults"),
|
||||
.external(name: "DefaultsMacros"),
|
||||
],
|
||||
settings: .settings(configurations: [
|
||||
.debug(
|
||||
|
|
|
|||
Loading…
Reference in New Issue