microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
147d9cc549da9c4c4297f65e799484b78fe8de80

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/commandExecutor.ts

191lines · 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): ChildProcess {
45 return this.spawnChildProcess(command, args, options, outputChannel).spawnedProcess;
46 }
47
48 /**
49 * Spawns a child process with the params passed
50 * This method waits until the spawned process finishes execution
51 * {command} - The command to be invoked in the child process
52 * {args} - Arguments to be passed to the command
53 * {options} - additional options with which the child process needs to be spawned
54 * {outputChannel} - optional object of type vscode.OutputChannel where logs need to be printed
55 */
56 public spawnAndWaitForCompletion(command: string, args: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<void> {
57 return this.spawnChildProcess(command, args, options, outputChannel).outcome;
58 }
59
60 public spawnReactCommand(command: string, args?: string[], options: Options = {}, outputChannel?: OutputChannel): ChildProcess {
61 return this.spawnChildReactCommandProcess(command, args, options, outputChannel).spawnedProcess;
62 }
63
64 /**
65 * Spawns the React Native packager in a child process.
66 */
67 public spawnReactPackager(args?: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<ChildProcess> {
68 let deferred = Q.defer<ChildProcess>();
69 let command = this.getReactCommandName();
70 let runArguments = ["start"];
71
72 if (args) {
73 runArguments = runArguments.concat(args);
74 }
75
76 let spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
77
78 let result = new Node.ChildProcess().spawn(command, runArguments, spawnOptions);
79 result.spawnedProcess.once("error", (error: any) => {
80 deferred.reject({ error: error });
81 });
82
83 result.stderr.on("data", (data: Buffer) => {
84 if (outputChannel) {
85 outputChannel.append(data.toString());
86 } else {
87 process.stderr.write(data);
88 }
89 });
90
91 result.stdout.on("data", (data: Buffer) => {
92 if (outputChannel) {
93 outputChannel.append(data.toString());
94 } else {
95 process.stdout.write(data);
96 }
97 });
98
99 Q.delay(300).then(() => deferred.resolve(result.spawnedProcess));
100 return deferred.promise;
101 }
102
103 /**
104 * Kills the React Native packager in a child process.
105 */
106 public killReactPackager(packagerProcess: ChildProcess, outputChannel?: OutputChannel): void {
107 Log.logMessage("Stopping Packager", outputChannel);
108
109 if (packagerProcess) {
110 /* To reliably kill the child process on all versions of Windows,
111 * please use taskkill to end the packager process */
112 if (process.platform === "win32") {
113 new Node.ChildProcess().exec("taskkill /pid " + packagerProcess.pid + " /T /F").outcome.then(() => {
114 Log.logMessage("Packager stopped", outputChannel);
115 }, function() {
116 Log.logError("Failed to exit the React Native packager", outputChannel);
117 });
118 } else {
119 packagerProcess.kill();
120 Log.logMessage("Packager stopped", outputChannel);
121 }
122
123 packagerProcess = null;
124 } else {
125 Log.logMessage("Packager not found", outputChannel);
126 }
127 }
128
129
130
131 /**
132 * Executes a react native command and waits for its completion.
133 */
134 public spawnAndWaitReactCommand(command: string, args?: string[], options: Options = {}, outputChannel?: OutputChannel): Q.Promise<void> {
135 return this.spawnChildReactCommandProcess(command, args, options, outputChannel).outcome;
136 }
137
138 public spawnChildReactCommandProcess(command: string, args?: string[], options: Options = {}, outputChannel?: OutputChannel): ISpawnResult {
139 let runArguments = [command];
140 if (args) {
141 runArguments = runArguments.concat(args);
142 }
143 return this.spawnChildProcess(this.getReactCommandName(), runArguments, options, outputChannel);
144 }
145
146 /**
147 * Resolves the dev machine, desktop platform.
148 */
149 private getReactCommandName() {
150 let platform = process.platform;
151 switch (platform) {
152 case "darwin":
153 return "react-native";
154 case "win32":
155 default:
156 return "react-native.cmd";
157 }
158 }
159
160 private spawnChildProcess(command: string, args: string[], options: Options = {}, outputChannel?: OutputChannel): ISpawnResult {
161 let spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
162 let commandWithArgs = command + " " + args.join(" ");
163
164 Log.commandStarted(commandWithArgs, outputChannel);
165 let result = new Node.ChildProcess().spawnWithExitHandler(command, args, spawnOptions);
166
167 result.stderr.on("data", (data: Buffer) => {
168 if (outputChannel) {
169 outputChannel.append(data.toString());
170 } else {
171 process.stderr.write(data);
172 }
173 });
174
175 result.stdout.on("data", (data: Buffer) => {
176 if (outputChannel) {
177 outputChannel.append(data.toString());
178 } else {
179 process.stdout.write(data);
180 }
181 });
182
183 result.outcome.done(() => {
184 Log.commandEnded(commandWithArgs, outputChannel);
185 }, (reason) => {
186 Log.commandFailed(commandWithArgs, reason, outputChannel);
187 });
188
189 return result;
190 }
191}
192