microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
efbe1ba61ca71887b3fa9a2d1ae3afb9a78cb87e

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/common/node/childProcess.ts

104lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as nodeChildProcess from "child_process";
5import Q = require("q");
6import {ErrorHelper} from "../error/errorHelper";
7import {InternalErrorCode} from "../error/internalErrorCode";
8
9// Uncomment the following lines to record all spawned processes executions
10// import {Recorder} from "../../../test/resources/processExecution/recorder";
11// Recorder.installGlobalRecorder();
12
13export interface IExecResult {
14 process: nodeChildProcess.ChildProcess;
15 outcome: Q.Promise<string>;
16}
17
18export interface ISpawnResult {
19 spawnedProcess: nodeChildProcess.ChildProcess;
20 stdin: NodeJS.WritableStream;
21 stdout: NodeJS.ReadableStream;
22 stderr: NodeJS.ReadableStream;
23 startup: Q.Promise<void>; // The app started succesfully
24 outcome: Q.Promise<void>; // The app finished succesfully
25}
26
27interface IExecOptions {
28 cwd?: string;
29 stdio?: any;
30 env?: any;
31 encoding?: string;
32 timeout?: number;
33 maxBuffer?: number;
34 killSignal?: string;
35}
36
37interface ISpawnOptions {
38 cwd?: string;
39 stdio?: any;
40 env?: any;
41 detached?: boolean;
42}
43
44export class ChildProcess {
45 public static ERROR_TIMEOUT_MILLISECONDS = 300;
46 private childProcess: typeof nodeChildProcess;
47
48 constructor({childProcess = nodeChildProcess} = {}) {
49 this.childProcess = childProcess;
50 }
51
52 public exec(command: string, options: IExecOptions = {}): IExecResult {
53 let outcome = Q.defer<string>();
54
55 let execProcess = this.childProcess.exec(command, options, (error: Error, stdout: string, stderr: string) => {
56 if (error) {
57 outcome.reject(ErrorHelper.getNestedError(error, InternalErrorCode.CommandFailed, command));
58 } else {
59 outcome.resolve(stdout);
60 }
61 });
62
63 return { process: execProcess, outcome: outcome.promise };
64 }
65
66 public execToString(command: string, options: IExecOptions = {}): Q.Promise<string> {
67 return this.exec(command, options).outcome.then(stdout => stdout.toString());
68 }
69
70 public spawn(command: string, args: string[] = [], options: ISpawnOptions = {}): ISpawnResult {
71 const startup = Q.defer<void>();
72 const outcome = Q.defer<void>();
73
74 const spawnedProcess = this.childProcess.spawn(command, args, options);
75
76 spawnedProcess.once("error", (error: any) => {
77 startup.reject(error);
78 outcome.reject(error);
79 });
80
81 Q.delay(ChildProcess.ERROR_TIMEOUT_MILLISECONDS).done(() =>
82 startup.resolve(void 0));
83
84 startup.promise.done(() => {}, () => {}); // Most callers don't use startup, and Q prints a warning if we don't attach any .done()
85
86 spawnedProcess.once("exit", (code: number) => {
87 if (code === 0) {
88 outcome.resolve(void 0);
89 } else {
90 const commandWithArgs = command + " " + args.join(" ");
91 outcome.reject(ErrorHelper.getInternalError(InternalErrorCode.CommandFailed, commandWithArgs, code));
92 }
93 });
94
95 return {
96 spawnedProcess: spawnedProcess,
97 stdin: spawnedProcess.stdin,
98 stdout: spawnedProcess.stdout,
99 stderr: spawnedProcess.stderr,
100 startup: startup.promise,
101 outcome: outcome.promise,
102 };
103 }
104}
105