microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9d03d24a40909f27a4fcde08d428ead3e7063d07

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/commandExecutor.ts

207lines · 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 {ChildProcess} from "child_process";
5import {Log} from "./log";
6import {Node} from "./node/node";
7import {ISpawnResult} from "./node/childProcess";
8import {OutputChannel} from "vscode";
9import * as Q from "q";
10
11interface EnvironmentOptions {
12 REACT_DEBUGGER?: string;
13}
14
15interface Options {
16 env?: EnvironmentOptions;
17}
18
19export class CommandExecutor {
20 private currentWorkingDirectory: string;
21
22 constructor(currentWorkingDirectory?: string) {
23 this.currentWorkingDirectory = currentWorkingDirectory;
24 }
25
26 public execute(command: string, options: Options = {}): Q.Promise<void> {
27 Log.commandStarted(command);
28 return new Node.ChildProcess().execToString(command, { cwd: this.currentWorkingDirectory, env: options.env })
29 .then(stdout => {
30 Log.logMessage(stdout);
31 Log.commandEnded(command);
32 },
33 reason => Log.commandFailed(command, reason));
34 }
35
36 /**
37 * Spawns a child process with the params passed and returns promise of the spawned ChildProcess
38 * This method does not wait for the spawned process to finish execution
39 * {command} - The command to be invoked in the child process
40 * {args} - Arguments to be passed to the command
41 * {options} - additional options with which the child process needs to be spawned
42 * {outputChannel} - optional object of type vscode.OutputChannel where logs need to be printed
43 */
44 public spawn(command: string, args: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<ChildProcess> {
45 return this.spawnChildProcess(command, args, options, outputChannel).then(spawnResult => {
46 let commandWithArgs = command + " " + args.join(" ");
47 spawnResult.outcome.then(() => {
48 Log.commandEnded(commandWithArgs, outputChannel);
49 },
50 (reason) => {
51 Log.commandFailed(commandWithArgs, reason, outputChannel);
52 });
53
54 return Q.resolve(spawnResult.spawnedProcess);
55 });
56 }
57
58 /**
59 * Spawns a child process with the params passed
60 * This method waits until the spawned process finishes execution
61 * {command} - The command to be invoked in the child process
62 * {args} - Arguments to be passed to the command
63 * {options} - additional options with which the child process needs to be spawned
64 * {outputChannel} - optional object of type vscode.OutputChannel where logs need to be printed
65 */
66 public spawnAndWaitForCompletion(command: string, args: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<void> {
67 return this.spawnChildProcess(command, args, options, outputChannel).then(spawnResult => {
68 let commandWithArgs = command + " " + args.join(" ");
69 return spawnResult.outcome.then(() => {
70 Log.commandEnded(commandWithArgs, outputChannel);
71 },
72 (reason) => {
73 Log.commandFailed(commandWithArgs, reason, outputChannel);
74 throw reason;
75 });
76 });
77 }
78
79 /**
80 * Executes a react native command.
81 */
82 public spawnReactCommand(command: string, args?: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<ChildProcess> {
83 let runArguments = [command];
84 if (args) {
85 runArguments = runArguments.concat(args);
86 }
87 return this.spawn(this.getReactCommandName(), runArguments, options, outputChannel);
88 }
89
90 /**
91 * Spawns the React Native packager in a child process.
92 */
93 public spawnReactPackager(args?: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<ChildProcess> {
94 let deferred = Q.defer<ChildProcess>();
95 let command = this.getReactCommandName();
96 let runArguments = ["start"];
97
98 if (args) {
99 runArguments = runArguments.concat(args);
100 }
101
102 let spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
103
104 let result = new Node.ChildProcess().spawn(command, runArguments, spawnOptions);
105 result.spawnedProcess.once("error", (error: any) => {
106 deferred.reject({ error: error });
107 });
108
109 result.stderr.on("data", (data: Buffer) => {
110 if (outputChannel) {
111 outputChannel.append(data.toString());
112 } else {
113 process.stderr.write(data);
114 }
115 });
116
117 result.stdout.on("data", (data: Buffer) => {
118 if (outputChannel) {
119 outputChannel.append(data.toString());
120 } else {
121 process.stdout.write(data);
122 }
123 });
124
125 Q.delay(300).then(() => deferred.resolve(result.spawnedProcess));
126 return deferred.promise;
127 }
128
129 /**
130 * Kills the React Native packager in a child process.
131 */
132 public killReactPackager(packagerProcess: ChildProcess, outputChannel?: OutputChannel): void {
133 Log.logMessage("Stopping Packager", outputChannel);
134
135 if (packagerProcess) {
136 /* To reliably kill the child process on all versions of Windows,
137 * please use taskkill to end the packager process */
138 if (process.platform === "win32") {
139 new Node.ChildProcess().exec("taskkill /pid " + packagerProcess.pid + " /T /F").outcome.then(() => {
140 Log.logMessage("Packager stopped", outputChannel);
141 }, function() {
142 Log.logError("Failed to exit the React Native packager", outputChannel);
143 });
144 } else {
145 packagerProcess.kill();
146 Log.logMessage("Packager stopped", outputChannel);
147 }
148
149 packagerProcess = null;
150 } else {
151 Log.logMessage("Packager not found", outputChannel);
152 }
153 }
154
155
156
157 /**
158 * Executes a react native command and waits for its completion.
159 */
160 public spawnAndWaitReactCommand(command: string, args?: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<void> {
161 let runArguments = [command];
162 if (args) {
163 runArguments = runArguments.concat(args);
164 }
165 return this.spawnAndWaitForCompletion(this.getReactCommandName(), runArguments, options, outputChannel);
166 }
167
168 /**
169 * Resolves the dev machine, desktop platform.
170 */
171 private getReactCommandName() {
172 let platform = process.platform;
173 switch (platform) {
174 case "darwin":
175 return "react-native";
176 case "win32":
177 default:
178 return "react-native.cmd";
179 }
180 }
181
182 private spawnChildProcess(command: string, args: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<ISpawnResult> {
183 let spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
184 let commandWithArgs = command + " " + args.join(" ");
185
186 Log.commandStarted(commandWithArgs, outputChannel);
187 let result = new Node.ChildProcess().spawnWithExitHandler(command, args, spawnOptions);
188
189 result.stderr.on("data", (data: Buffer) => {
190 if (outputChannel) {
191 outputChannel.append(data.toString());
192 } else {
193 process.stderr.write(data);
194 }
195 });
196
197 result.stdout.on("data", (data: Buffer) => {
198 if (outputChannel) {
199 outputChannel.append(data.toString());
200 } else {
201 process.stdout.write(data);
202 }
203 });
204
205 return Q.resolve(result);
206 }
207}
208