|
8 | 8 | #if os(macOS) |
9 | 9 | import Foundation |
10 | 10 | import Combine |
| 11 | + import SKProcessRunner |
11 | 12 |
|
12 | 13 | @available(macOS 11, *) |
13 | 14 | public struct Shell {} |
|
176 | 177 | public func data(_ args: Shell.Arguments) throws -> Data { |
177 | 178 | var args = args |
178 | 179 | changedArgsBeforeRun?(&args) |
179 | | - let process = self.setupProcess(args.exec, args.commands, context: args.context) |
180 | | - let output = Shell.Standard(publisher: args.context?.standardOutput).append( |
181 | | - to: &process.standardOutput) |
182 | | - let error = Shell.Standard(publisher: args.context?.standardError).append( |
183 | | - to: &process.standardError) |
184 | | - try process.run() |
185 | | - process.waitUntilExit() |
186 | | - return try result(process, output: output.availableData, error: error.availableData) |
187 | | - .get() |
| 180 | + guard let exec = args.exec else { |
| 181 | + throw Shell.Error.processFailed(message: "Missing executable.", code: -1) |
| 182 | + } |
| 183 | + |
| 184 | + let stdoutPublisher = args.context?.standardOutput |
| 185 | + let stderrPublisher = args.context?.standardError |
| 186 | + |
| 187 | + do { |
| 188 | + let result = try SKProcessRunner.runSync( |
| 189 | + executableURL: exec, |
| 190 | + arguments: args.commands, |
| 191 | + configuration: .init( |
| 192 | + cwd: args.context?.currentDirectory, |
| 193 | + environment: args.context?.environment ?? [:], |
| 194 | + timeoutMs: 5 * 60 * 1000, |
| 195 | + maxOutputBytes: 4 * 1024 * 1024 |
| 196 | + ), |
| 197 | + onStdout: { stdoutPublisher?.send($0) }, |
| 198 | + onStderr: { stderrPublisher?.send($0) }, |
| 199 | + throwOnNonZeroExit: true |
| 200 | + ) |
| 201 | + return result.stdoutData |
| 202 | + } catch let error as SKProcessRunner.RunError { |
| 203 | + throw Shell.Error.processFailed(message: error.localizedDescription, code: -1) |
| 204 | + } |
188 | 205 | } |
189 | 206 |
|
190 | 207 | @discardableResult |
191 | 208 | public func data(_ args: Shell.Arguments, input: Data?) throws -> Data { |
192 | 209 | var args = args |
193 | 210 | changedArgsBeforeRun?(&args) |
194 | | - let process = self.setupProcess(args.exec, args.commands, context: args.context) |
195 | | - |
196 | | - if let input = input { |
197 | | - let inputPipe = Pipe() |
198 | | - process.standardInput = inputPipe |
199 | | - try inputPipe.fileHandleForWriting.write(contentsOf: input) |
200 | | - try inputPipe.fileHandleForWriting.close() |
| 211 | + guard let exec = args.exec else { |
| 212 | + throw Shell.Error.processFailed(message: "Missing executable.", code: -1) |
201 | 213 | } |
202 | 214 |
|
203 | | - let output = Shell.Standard(publisher: args.context?.standardOutput).append( |
204 | | - to: &process.standardOutput) |
205 | | - let error = Shell.Standard(publisher: args.context?.standardError).append( |
206 | | - to: &process.standardError) |
207 | | - try process.run() |
208 | | - process.waitUntilExit() |
209 | | - return try result(process, output: output.availableData, error: error.availableData) |
210 | | - .get() |
| 215 | + let stdoutPublisher = args.context?.standardOutput |
| 216 | + let stderrPublisher = args.context?.standardError |
| 217 | + |
| 218 | + do { |
| 219 | + let result = try SKProcessRunner.runSync( |
| 220 | + executableURL: exec, |
| 221 | + arguments: args.commands, |
| 222 | + stdinData: input, |
| 223 | + configuration: .init( |
| 224 | + cwd: args.context?.currentDirectory, |
| 225 | + environment: args.context?.environment ?? [:], |
| 226 | + timeoutMs: 5 * 60 * 1000, |
| 227 | + maxOutputBytes: 4 * 1024 * 1024 |
| 228 | + ), |
| 229 | + onStdout: { stdoutPublisher?.send($0) }, |
| 230 | + onStderr: { stderrPublisher?.send($0) }, |
| 231 | + throwOnNonZeroExit: true |
| 232 | + ) |
| 233 | + return result.stdoutData |
| 234 | + } catch let error as SKProcessRunner.RunError { |
| 235 | + throw Shell.Error.processFailed(message: error.localizedDescription, code: -1) |
| 236 | + } |
211 | 237 | } |
212 | 238 |
|
213 | 239 | @discardableResult |
|
337 | 363 |
|
338 | 364 | @discardableResult |
339 | 365 | public func data(_ args: Shell.Arguments) async throws -> Data { |
340 | | - try await withCheckedThrowingContinuation { continuation in |
341 | | - do { |
342 | | - var args = args |
343 | | - changedArgsBeforeRun?(&args) |
344 | | - let process = setupProcess(args.exec, args.commands, context: args.context) |
345 | | - let output = Shell.Standard(publisher: args.context?.standardOutput).append( |
346 | | - to: &process.standardOutput) |
347 | | - let error = Shell.Standard(publisher: args.context?.standardError).append( |
348 | | - to: &process.standardError) |
349 | | - try process.run() |
350 | | - process.terminationHandler = { [self] process in |
351 | | - do { |
352 | | - let data = try result( |
353 | | - process, output: output.availableData, error: error.availableData |
354 | | - ).get() |
355 | | - continuation.resume(returning: data) |
356 | | - } catch { |
357 | | - continuation.resume(throwing: error) |
358 | | - } |
359 | | - } |
360 | | - } catch { |
361 | | - continuation.resume(throwing: error) |
362 | | - } |
| 366 | + var args = args |
| 367 | + changedArgsBeforeRun?(&args) |
| 368 | + guard let exec = args.exec else { |
| 369 | + throw Shell.Error.processFailed(message: "Missing executable.", code: -1) |
| 370 | + } |
| 371 | + |
| 372 | + let stdoutPublisher = args.context?.standardOutput |
| 373 | + let stderrPublisher = args.context?.standardError |
| 374 | + |
| 375 | + do { |
| 376 | + let result = try await SKProcessRunner.run( |
| 377 | + executableURL: exec, |
| 378 | + arguments: args.commands, |
| 379 | + stdinData: nil, |
| 380 | + configuration: .init( |
| 381 | + cwd: args.context?.currentDirectory, |
| 382 | + environment: args.context?.environment ?? [:], |
| 383 | + timeoutMs: 5 * 60 * 1000, |
| 384 | + maxOutputBytes: 4 * 1024 * 1024 |
| 385 | + ), |
| 386 | + onStdout: { stdoutPublisher?.send($0) }, |
| 387 | + onStderr: { stderrPublisher?.send($0) }, |
| 388 | + throwOnNonZeroExit: true |
| 389 | + ) |
| 390 | + return result.stdoutData |
| 391 | + } catch let error as SKProcessRunner.RunError { |
| 392 | + throw Shell.Error.processFailed(message: error.localizedDescription, code: -1) |
363 | 393 | } |
364 | 394 | } |
365 | 395 |
|
|
0 commit comments