Skip to content

Commit 70a9e4b

Browse files
committed
Add an overload that allows supplying custom stdout and stderr destinations AND a body
Every other combination of stdin/stdout/stderr with a custom body was present except for this one.
1 parent 8a8c6b7 commit 70a9e4b

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

Sources/Subprocess/API.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,67 @@ public func run<
142142

143143
// MARK: - Custom Execution Body
144144

145+
/// Run an executable with given parameters and a custom closure
146+
/// to manage the running subprocess' lifetime and stream its standard output.
147+
/// - Parameters:
148+
/// - executable: The executable to run.
149+
/// - arguments: The arguments to pass to the executable.
150+
/// - environment: The environment in which to run the executable.
151+
/// - workingDirectory: The working directory in which to run the executable.
152+
/// - platformOptions: The platform specific options to use
153+
/// when running the executable.
154+
/// - input: The input to send to the executable.
155+
/// - output: How to manager executable standard output.
156+
/// - error: How to manager executable standard error.
157+
/// - isolation: the isolation context to run the body closure.
158+
/// - body: The custom execution body to manually control the running process
159+
/// - Returns an executableResult type containing the return value
160+
/// of the closure.
161+
public func run<Result, Input: InputProtocol, Output: OutputProtocol, Error: OutputProtocol>(
162+
_ executable: Executable,
163+
arguments: Arguments = [],
164+
environment: Environment = .inherit,
165+
workingDirectory: FilePath? = nil,
166+
platformOptions: PlatformOptions = PlatformOptions(),
167+
input: Input = .none,
168+
output: Output,
169+
error: Error,
170+
isolation: isolated (any Actor)? = #isolation,
171+
body: ((Execution) async throws -> Result)
172+
) async throws -> ExecutionResult<Result> where Error.OutputType == Void {
173+
return try await Configuration(
174+
executable: executable,
175+
arguments: arguments,
176+
environment: environment,
177+
workingDirectory: workingDirectory,
178+
platformOptions: platformOptions
179+
).run(
180+
input: try input.createPipe(),
181+
output: try output.createPipe(),
182+
error: try error.createPipe()
183+
) { execution, inputIO, _, _ in
184+
var inputIOBox: TrackedPlatformDiskIO? = consume inputIO
185+
return try await withThrowingTaskGroup(
186+
of: Void.self,
187+
returning: Result.self
188+
) { group in
189+
var inputIOContainer: TrackedPlatformDiskIO? = inputIOBox.take()
190+
group.addTask {
191+
if let inputIO = inputIOContainer.take() {
192+
let writer = StandardInputWriter(diskIO: inputIO)
193+
try await input.write(with: writer)
194+
try await writer.finish()
195+
}
196+
}
197+
198+
// Body runs in the same isolation
199+
let result = try await body(execution)
200+
try await group.waitForAll()
201+
return result
202+
}
203+
}
204+
}
205+
145206
/// Run an executable with given parameters and a custom closure
146207
/// to manage the running subprocess' lifetime and stream its standard output.
147208
/// - Parameters:

0 commit comments

Comments
 (0)