@@ -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 = . discarded,
169+ error: Error = . discarded,
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, outputIO, errorIO 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