(command: string, @ignoreLogging() options: ShellOptions = {})
| 214 | |
| 215 | @debugDecorator('Execing shell command', TraceOptions.BeforeCall | TraceOptions.Arguments) |
| 216 | public shellExec(command: string, @ignoreLogging() options: ShellOptions = {}): Promise<ExecutionResult<string>> { |
| 217 | const shellOptions = this.getDefaultOptions(options); |
| 218 | return new Promise((resolve, reject) => { |
| 219 | let cancelDisposable: Disposable | undefined; |
| 220 | const proc = exec(command, shellOptions, (e, stdout, stderr) => { |
| 221 | cancelDisposable?.dispose(); |
| 222 | if (e && e !== null) { |
| 223 | reject(e); |
| 224 | } else if (shellOptions.throwOnStdErr && stderr && stderr.length) { |
| 225 | reject(new Error(stderr)); |
| 226 | } else { |
| 227 | // Make sure stderr is undefined if we actually had none. This is checked |
| 228 | // elsewhere because that's how exec behaves. |
| 229 | resolve({ stderr: stderr && stderr.length > 0 ? stderr : undefined, stdout: stdout }); |
| 230 | } |
| 231 | }); |
| 232 | if (options.token) { |
| 233 | cancelDisposable = options.token.onCancellationRequested(() => { |
| 234 | if (proc.exitCode === null && !proc.killed) { |
| 235 | reject(new CancellationError()); |
| 236 | ProcessService.kill(proc.pid); |
| 237 | } |
| 238 | }); |
| 239 | } |
| 240 | |
| 241 | const disposable: IDisposable = { |
| 242 | dispose: () => { |
| 243 | if (!proc.killed) { |
| 244 | ProcessService.kill(proc.pid); |
| 245 | } |
| 246 | } |
| 247 | }; |
| 248 | this.processesToKill.add(disposable); |
| 249 | }); |
| 250 | } |
| 251 | |
| 252 | private getDefaultOptions<T extends ShellOptions | SpawnOptions>(options: T): T { |
| 253 | const defaultOptions = { ...options }; |
no test coverage detected