diff --git a/Sources/ScipioKit/Executor.swift b/Sources/ScipioKit/Executor.swift index 4a89165b..9e047142 100644 --- a/Sources/ScipioKit/Executor.swift +++ b/Sources/ScipioKit/Executor.swift @@ -11,6 +11,7 @@ private actor ProcessOutputBuffer { @_spi(Internals) public protocol Executor: Sendable { + associatedtype Result: ExecutorResult /// Executes the command with the given arguments and environment variables. /// /// - Parameters: @@ -23,7 +24,7 @@ public protocol Executor: Sendable { /// - Note: /// This does not merge with the existing environment. @discardableResult - func execute(_ arguments: [String], environment: [String: String]?) async throws -> ExecutorResult + func execute(_ arguments: [String], environment: [String: String]?) async throws -> Result } @_spi(Internals) @@ -55,12 +56,12 @@ public protocol ExecutorResult: Sendable { public extension Executor { @discardableResult - func execute(_ arguments: [String]) async throws -> ExecutorResult { + func execute(_ arguments: [String]) async throws -> some ExecutorResult { try await execute(arguments, environment: nil) } @discardableResult - func execute(_ arguments: String...) async throws -> ExecutorResult { + func execute(_ arguments: String...) async throws -> some ExecutorResult { try await execute(arguments) } } @@ -114,7 +115,10 @@ public struct ProcessExecutor: Executor, Sendable { public var streamOutput: (@Sendable ([UInt8]) async -> Void)? - public func execute(_ arguments: [String], environment: [String: String]?) async throws -> ExecutorResult { + public func execute( + _ arguments: [String], + environment: [String: String]? + ) async throws -> some ExecutorResult { guard let executable = arguments.first, !executable.isEmpty else { throw ProcessExecutorError.executableNotFound } @@ -185,7 +189,7 @@ public struct ProcessExecutor: Executor, Sendable { let finalErrorOutput = try await errorOutputTask.value // Wait for process to complete - return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in process.terminationHandler = { process in outputHandle.readabilityHandler = nil errorHandle.readabilityHandler = nil diff --git a/Tests/ScipioKitTests/CacheSystemTests.swift b/Tests/ScipioKitTests/CacheSystemTests.swift index a6dde519..e04b0a2e 100644 --- a/Tests/ScipioKitTests/CacheSystemTests.swift +++ b/Tests/ScipioKitTests/CacheSystemTests.swift @@ -219,7 +219,7 @@ final class CacheSystemTests: XCTestCase { } // Ensure that the cache key is properly calculated when the package is in a repository with the correct tag." - let processExecutor: Executor = ProcessExecutor() + let processExecutor = ProcessExecutor() let tempTestingPackagePathString = tempTestingPackagePath.path(percentEncoded: false) try await processExecutor.execute(["/usr/bin/xcrun", "git", "init", tempTestingPackagePathString]) try await processExecutor.execute([ diff --git a/Tests/ScipioKitTests/TestingExecutor.swift b/Tests/ScipioKitTests/TestingExecutor.swift index 068d8172..506db859 100644 --- a/Tests/ScipioKitTests/TestingExecutor.swift +++ b/Tests/ScipioKitTests/TestingExecutor.swift @@ -1,19 +1,19 @@ import Foundation @testable @_spi(Internals) import ScipioKit -actor StubbableExecutor: Executor { - init(executeHook: @escaping (([String]) throws -> ExecutorResult)) { +actor StubbableExecutor: Executor { + init(executeHook: @escaping (([String]) throws -> R)) { self.executeHook = executeHook } - let executeHook: (([String]) throws -> any ExecutorResult) + let executeHook: (([String]) throws -> R) private(set) var calledArguments: [[String]] = [] var calledCount: Int { calledArguments.count } - func execute(_ arguments: [String], environment: [String: String]?) async throws -> ExecutorResult { + func execute(_ arguments: [String], environment: [String: String]?) async throws -> R { calledArguments.append(arguments) return try executeHook(arguments) }