diff --git a/Mist/Commands/Download/DownloadFirmwareCommand.swift b/Mist/Commands/Download/DownloadFirmwareCommand.swift index 8aca5d4..7bf3da3 100644 --- a/Mist/Commands/Download/DownloadFirmwareCommand.swift +++ b/Mist/Commands/Download/DownloadFirmwareCommand.swift @@ -200,16 +200,25 @@ struct DownloadFirmwareCommand: ParsableCommand { let required: Int64 = firmware.size for url in [outputURL, temporaryURL] { - let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey, .volumeAvailableCapacityKey]) - let free: Int64 + var free: Int64 = 0 +#if os(Linux) + let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityKey]) + if let volumeAvailableCapacity: Int = values.volumeAvailableCapacity { + free = Int64(volumeAvailableCapacity) + } +#else + let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey, .volumeAvailableCapacityKey]) if let volumeAvailableCapacityForImportantUsage: Int64 = values.volumeAvailableCapacityForImportantUsage, volumeAvailableCapacityForImportantUsage > 0 { free = volumeAvailableCapacityForImportantUsage } else if let volumeAvailableCapacity: Int = values.volumeAvailableCapacity { free = Int64(volumeAvailableCapacity) - } else { + } +#endif + + if free == 0 { throw MistError.notEnoughFreeSpace(volume: url.path, free: 0, required: required) } diff --git a/Mist/Commands/Download/DownloadInstallerCommand.swift b/Mist/Commands/Download/DownloadInstallerCommand.swift index 42246a6..8e67614 100644 --- a/Mist/Commands/Download/DownloadInstallerCommand.swift +++ b/Mist/Commands/Download/DownloadInstallerCommand.swift @@ -397,16 +397,25 @@ struct DownloadInstallerCommand: ParsableCommand { for volume in volumes { let required: Int64 = installer.size * volume.count let url: URL = .init(fileURLWithPath: volume.path) - let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey, .volumeAvailableCapacityKey]) - let free: Int64 + var free: Int64 = 0 +#if os(Linux) + let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityKey]) + if let volumeAvailableCapacity: Int = values.volumeAvailableCapacity { + free = Int64(volumeAvailableCapacity) + } +#else + let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey, .volumeAvailableCapacityKey]) if let volumeAvailableCapacityForImportantUsage: Int64 = values.volumeAvailableCapacityForImportantUsage, volumeAvailableCapacityForImportantUsage > 0 { free = volumeAvailableCapacityForImportantUsage } else if let volumeAvailableCapacity: Int = values.volumeAvailableCapacity { free = Int64(volumeAvailableCapacity) - } else { + } +#endif + + if free == 0 { throw MistError.notEnoughFreeSpace(volume: url.path, free: 0, required: required) } diff --git a/Mist/Extensions/URL+Extension.swift b/Mist/Extensions/URL+Extension.swift index 91c6081..8098e0f 100644 --- a/Mist/Extensions/URL+Extension.swift +++ b/Mist/Extensions/URL+Extension.swift @@ -5,7 +5,7 @@ // Created by Nindi Gill on 15/8/2022. // -import CryptoKit +import Crypto import Foundation extension URL { diff --git a/Mist/Helpers/Downloader.swift b/Mist/Helpers/Downloader.swift index a909d66..34091b1 100644 --- a/Mist/Helpers/Downloader.swift +++ b/Mist/Helpers/Downloader.swift @@ -7,6 +7,10 @@ import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + /// Helper Class used to download macOS Firmwares and Installers. class Downloader: NSObject { private static let maximumWidth: Int = 95 @@ -70,12 +74,14 @@ class Downloader: NSObject { while urlError != nil { if retries >= options.retries { +#if !os(Linux) if let error: URLError = urlError, let data: Data = error.downloadTaskResumeData { !quiet ? PrettyPrint.print("Saving resume data to '\(resumeDataURL.path)'...", noAnsi: noAnsi) : Mist.noop() try data.write(to: resumeDataURL) } +#endif throw MistError.maximumRetriesReached } @@ -168,12 +174,14 @@ class Downloader: NSObject { while urlError != nil { if retries >= options.retries { +#if !os(Linux) if let error: URLError = urlError, let data: Data = error.downloadTaskResumeData { !quiet ? PrettyPrint.print("Saving resume data to '\(resumeDataURL.path)'...", noAnsi: noAnsi) : Mist.noop() try data.write(to: resumeDataURL) } +#endif throw MistError.maximumRetriesReached } @@ -225,6 +233,9 @@ class Downloader: NSObject { } private func retry(attempt retry: Int, of maximumRetries: Int, with delay: Int, using session: URLSession) { +#if os(Linux) + mistError = MistError.generalError("Cannot retry downloads on Linux") +#else guard let urlError: URLError = urlError, let data: Data = urlError.downloadTaskResumeData else { @@ -242,6 +253,7 @@ class Downloader: NSObject { updateProgress(replacing: false) task.resume() semaphore.wait() +#endif } private func updateProgress(replacing: Bool = true) { diff --git a/Mist/Helpers/Validator.swift b/Mist/Helpers/Validator.swift index 9837be1..97f3a07 100644 --- a/Mist/Helpers/Validator.swift +++ b/Mist/Helpers/Validator.swift @@ -5,7 +5,7 @@ // Created by Nindi Gill on 29/4/2022. // -import CryptoKit +import Crypto import Foundation /// Helper Struct used to validate macOS Firmware and Installer downloads. diff --git a/Mist/Model/Hardware.swift b/Mist/Model/Hardware.swift index 727e4a0..db535d1 100644 --- a/Mist/Model/Hardware.swift +++ b/Mist/Model/Hardware.swift @@ -49,6 +49,10 @@ enum Hardware { /// /// - Returns: The entity property for the provided key. private static func registryProperty(for key: String) -> String? { +#if os(Linux) + // Cannot use Darwin/XNU kernel APIs on Linux + return nil; +#else let entry: io_service_t = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")) defer { @@ -74,5 +78,6 @@ enum Hardware { let string: String = .init(decoding: data, as: UTF8.self) return string.trimmingCharacters(in: CharacterSet(["\0"])) +#endif } } diff --git a/Mist/main.swift b/Mist/main.swift index 60d8247..947800e 100644 --- a/Mist/main.swift +++ b/Mist/main.swift @@ -7,8 +7,23 @@ import Foundation +#if os(Linux) +/// A shim for Linux that runs the given block of code. +/// +/// The existence of this shim allows you the use of auto-release pools to optimize memory footprint on Darwin platforms while maintaining +/// compatibility with Linux where this API is not implemented. +@discardableResult +public func autoreleasepool(_ block: () throws -> Result) rethrows -> Result { + return try block() +} + +public func autoreleasepool(invoking body: () throws(E) -> Result) throws(E) -> Result where E: Error, Result : ~Copyable { + return try body() +} +#else // Disable stdout stream buffering for more immediate output. setbuf(__stdoutp, nil) +#endif Mist.main() exit(0) diff --git a/Package.swift b/Package.swift index 5fc1a7b..1e656d0 100644 --- a/Package.swift +++ b/Package.swift @@ -14,6 +14,7 @@ let package: Package = .init( ], dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser", from: "1.6.1"), + .package(url: "https://github.com/apple/swift-crypto.git", "1.0.0" ..< "5.0.0"), // .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.57.2"), .package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", from: "0.61.0"), .package(url: "https://github.com/jpsim/Yams", from: "6.1.0") @@ -23,6 +24,7 @@ let package: Package = .init( name: "Mist", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "Crypto", package: "swift-crypto"), .product(name: "Yams", package: "Yams") ], path: "Mist"