@@ -142,6 +142,67 @@ public func run<
142
142
143
143
// MARK: - Custom Execution Body
144
144
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
+
145
206
/// Run an executable with given parameters and a custom closure
146
207
/// to manage the running subprocess' lifetime and stream its standard output.
147
208
/// - Parameters:
0 commit comments