This commit is contained in:
2023-03-05 14:37:02 -05:00
parent 5b8b912844
commit 8524efb765
23 changed files with 926 additions and 11 deletions

View File

@@ -0,0 +1,37 @@
import Dependencies
import Foundation
import XCTestDynamicOverlay
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
public struct ShellClient {
public var foregroundShell: ([String]) throws -> Void
public var backgroundShell: ([String]) throws -> String
public func foregroundShell(_ arguments: String...) throws {
try self.foregroundShell(arguments)
}
@discardableResult
public func backgroundShell(_ arguments: String...) throws -> String {
try self.backgroundShell(arguments)
}
}
extension ShellClient: TestDependencyKey {
public static let noop = Self.init(
foregroundShell: unimplemented(),
backgroundShell: unimplemented(placeholder: "")
)
public static let testValue: ShellClient = .noop
}
extension DependencyValues {
public var shellClient: ShellClient {
get { self[ShellClient.self] }
set { self[ShellClient.self] = newValue }
}
}

View File

@@ -0,0 +1,59 @@
import Dependencies
import Foundation
import LoggingDependency
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
extension ShellClient: DependencyKey {
public static var liveValue: ShellClient {
@Dependency(\.logger) var logger
return .init(
foregroundShell: { arguments in
logger.debug("Running in foreground shell.")
logger.debug("$ \(arguments.joined(separator: " "))")
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = arguments
task.launch()
task.waitUntilExit()
guard task.terminationStatus == 0 else {
throw ShellError(terminationStatus: task.terminationStatus)
}
},
backgroundShell: { arguments in
logger.debug("Running background shell.")
logger.debug("$ \(arguments.joined(separator: " "))")
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = arguments
// grab stdout
let output = Pipe()
task.standardOutput = output
// ignore stderr
let error = Pipe()
task.standardError = error
task.launch()
task.waitUntilExit()
guard task.terminationStatus == 0 else {
throw ShellError(terminationStatus: task.terminationStatus)
}
return String(decoding: output.fileHandleForReading.readDataToEndOfFile(), as: UTF8.self)
.trimmingCharacters(in: .whitespacesAndNewlines)
}
)
}
}
struct ShellError: Swift.Error {
var terminationStatus: Int32
}