microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
transitive-dependency-serialize-javascript

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/commandExecutor.ts

281lines · modeblame

a31b007cunknown10 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
af1474acRedMickey6 years ago4import * as path from "path";
ce5e88eeYuri Skorokhodov5 years ago5import * as cp from "child_process";
09f6024fHeniker4 years ago6import * as nls from "vscode-nls";
34472878RedMickey5 years ago7import { ILogger } from "../extension/log/LogHelper";
8import { NullLogger } from "../extension/log/NullLogger";
09f6024fHeniker4 years ago9import { ProjectVersionHelper } from "./projectVersionHelper";
34472878RedMickey5 years ago10import { ISpawnResult } from "./node/childProcess";
11import { HostPlatform, HostPlatformId } from "./hostPlatform";
12import { ErrorHelper } from "./error/errorHelper";
13import { InternalErrorCode } from "./error/internalErrorCode";
ce5e88eeYuri Skorokhodov5 years ago14import { Node } from "./node/node";
09f6024fHeniker4 years ago15
34472878RedMickey5 years ago16nls.config({
17messageFormat: nls.MessageFormat.bundle,
18bundleFormat: nls.BundleFormat.standalone,
19})();
e2644f37Yuri Skorokhodov7 years ago20const localize = nls.loadMessageBundle();
3fb37ad5unknown10 years ago21
831f4a85Patricio Beltran9 years ago22export enum CommandVerbosity {
23OUTPUT,
24SILENT,
25PROGRESS,
26}
27
3fb37ad5unknown10 years ago28interface EnvironmentOptions {
29REACT_DEBUGGER?: string;
30}
31
32interface Options {
33env?: EnvironmentOptions;
831f4a85Patricio Beltran9 years ago34verbosity?: CommandVerbosity;
0d827d9bJimmy Thomson9 years ago35cwd?: string;
3fb37ad5unknown10 years ago36}
37
17161993Meena Kunnathur Balakrishnan10 years ago38export enum CommandStatus {
39Start = 0,
27710197Vladimir Kotikov8 years ago40End = 1,
17161993Meena Kunnathur Balakrishnan10 years ago41}
42
3fb37ad5unknown10 years ago43export class CommandExecutor {
af1474acRedMickey6 years ago44public static ReactNativeCommand: string | null;
9596aa53digeff10 years ago45private childProcess = new Node.ChildProcess();
3fb37ad5unknown10 years ago46
0a68f8dbArtem Egorov8 years ago47constructor(
4dfb1c4cetatanova5 years ago48private nodeModulesRoot: string,
0a68f8dbArtem Egorov8 years ago49private currentWorkingDirectory: string = process.cwd(),
34472878RedMickey5 years ago50private logger: ILogger = new NullLogger(),
51) {}
3fb37ad5unknown10 years ago52
0d77292aJiglioNero4 years ago53public async execute(command: string, options: Options = {}): Promise<void> {
0a68f8dbArtem Egorov8 years ago54this.logger.debug(CommandExecutor.getCommandStatusString(command, CommandStatus.Start));
0d77292aJiglioNero4 years ago55try {
56const stdout = await this.childProcess.execToString(command, {
57cwd: this.currentWorkingDirectory,
58env: options.env,
59});
60this.logger.info(stdout);
61this.logger.debug(CommandExecutor.getCommandStatusString(command, CommandStatus.End));
62} catch (reason) {
63return this.generateRejectionForCommand(command, reason);
64}
3fb37ad5unknown10 years ago65}
66
57fee98eEzio Li3 years ago67public async executeToString(command: string, options: Options = {}): Promise<string> {
68try {
69const stdout = await this.childProcess.execToString(command, {
70cwd: this.currentWorkingDirectory,
71env: options.env,
72});
73return stdout;
74} catch (reason) {
75return reason;
76}
77}
78
45944d15Meena Kunnathur Balakrishnan10 years ago79/**
80* Spawns a child process with the params passed
81* This method waits until the spawned process finishes execution
82* {command} - The command to be invoked in the child process
83* {args} - Arguments to be passed to the command
84* {options} - additional options with which the child process needs to be spawned
85*/
ce5e88eeYuri Skorokhodov5 years ago86public spawn(command: string, args: string[], options: Options = {}): Promise<any> {
9596aa53digeff10 years ago87return this.spawnChildProcess(command, args, options).outcome;
45944d15Meena Kunnathur Balakrishnan10 years ago88}
89
6126d899Meena Kunnathur Balakrishnan10 years ago90/**
91* Spawns the React Native packager in a child process.
92*/
9596aa53digeff10 years ago93public spawnReactPackager(args: string[], options: Options = {}): ISpawnResult {
94return this.spawnReactCommand("start", args, options);
6126d899Meena Kunnathur Balakrishnan10 years ago95}
96
efb84653Ezio Li2 years ago97/**
98* Spawns the React Native packager in a child process.
99*/
100public spawnExpoPackager(args: string[], options: Options = {}): ISpawnResult {
101return this.spawnExpoCommand("start", args, options);
102}
103
0d77292aJiglioNero4 years ago104public async getReactNativeVersion(): Promise<string> {
105const versions = await ProjectVersionHelper.getReactNativeVersions(
106this.currentWorkingDirectory,
34472878RedMickey5 years ago107);
0d77292aJiglioNero4 years ago108return versions.reactNativeVersion;
b8a56999Patricio Beltran9 years ago109}
110
c3a987a7Meena Kunnathur Balakrishnan10 years ago111/**
112* Kills the React Native packager in a child process.
113*/
0d77292aJiglioNero4 years ago114public async killReactPackager(packagerProcess?: cp.ChildProcess): Promise<void> {
c9b4fa6cMeena Kunnathur Balakrishnan10 years ago115if (packagerProcess) {
0d77292aJiglioNero4 years ago116if (HostPlatform.getPlatformId() === HostPlatformId.WINDOWS) {
117const res = await this.childProcess.exec(
09f6024fHeniker4 years ago118`taskkill /pid ${packagerProcess.pid} /T /F`,
0d77292aJiglioNero4 years ago119);
120await res.outcome;
121} else {
122packagerProcess.kill();
123}
124this.logger.info(localize("PackagerStopped", "Packager stopped"));
c3a987a7Meena Kunnathur Balakrishnan10 years ago125} else {
e2644f37Yuri Skorokhodov7 years ago126this.logger.warning(localize("PackagerNotFound", "Packager not found"));
c3a987a7Meena Kunnathur Balakrishnan10 years ago127}
128}
129
f8d32439dlebu10 years ago130/**
131* Executes a react native command and waits for its completion.
132*/
34472878RedMickey5 years ago133public spawnReactCommand(
134command: string,
135args: string[] = [],
136options: Options = {},
137): ISpawnResult {
af1474acRedMickey6 years ago138const reactCommand = HostPlatform.getNpmCliCommand(this.selectReactNativeCLI());
94cd5149Artem Egorov8 years ago139return this.spawnChildProcess(reactCommand, [command, ...args], options);
5b0582f3digeff10 years ago140}
141
efb84653Ezio Li2 years ago142/**
143* Executes a react native command and waits for its completion.
144*/
145public spawnExpoCommand(
146command: string,
147args: string[] = [],
148options: Options = {},
149): ISpawnResult {
150const expoCommand = HostPlatform.getNpmCliCommand(this.selectExpoCLI());
151return this.spawnChildProcess(expoCommand, [command, ...args], options);
152}
153
831f4a85Patricio Beltran9 years ago154/**
155* Spawns a child process with the params passed
156* This method has logic to do while the command is executing
157* {command} - The command to be invoked in the child process
158* {args} - Arguments to be passed to the command
159* {options} - additional options with which the child process needs to be spawned
160*/
0d77292aJiglioNero4 years ago161public async spawnWithProgress(
34472878RedMickey5 years ago162command: string,
163args: string[],
164options: Options = { verbosity: CommandVerbosity.OUTPUT },
165): Promise<void> {
831f4a85Patricio Beltran9 years ago166const spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
09f6024fHeniker4 years ago167const commandWithArgs = `${command} ${args.join(" ")}`;
831f4a85Patricio Beltran9 years ago168const timeBetweenDots = 1500;
b0af599cJimmy Thomson9 years ago169let lastDotTime = 0;
831f4a85Patricio Beltran9 years ago170
171const printDot = () => {
b0af599cJimmy Thomson9 years ago172const now = Date.now();
173if (now - lastDotTime > timeBetweenDots) {
174lastDotTime = now;
0a68f8dbArtem Egorov8 years ago175this.logger.logStream(".", process.stdout);
b0af599cJimmy Thomson9 years ago176}
831f4a85Patricio Beltran9 years ago177};
178
179if (options.verbosity === CommandVerbosity.OUTPUT) {
34472878RedMickey5 years ago180this.logger.debug(
181CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.Start),
182);
831f4a85Patricio Beltran9 years ago183}
184
185const result = this.childProcess.spawn(command, args, spawnOptions);
186
187result.stdout.on("data", (data: Buffer) => {
188if (options.verbosity === CommandVerbosity.OUTPUT) {
0a68f8dbArtem Egorov8 years ago189this.logger.logStream(data, process.stdout);
b0af599cJimmy Thomson9 years ago190} else if (options.verbosity === CommandVerbosity.PROGRESS) {
831f4a85Patricio Beltran9 years ago191printDot();
192}
193});
194
195result.stderr.on("data", (data: Buffer) => {
196if (options.verbosity === CommandVerbosity.OUTPUT) {
0a68f8dbArtem Egorov8 years ago197this.logger.logStream(data, process.stderr);
b0af599cJimmy Thomson9 years ago198} else if (options.verbosity === CommandVerbosity.PROGRESS) {
831f4a85Patricio Beltran9 years ago199printDot();
200}
201});
202
0d77292aJiglioNero4 years ago203try {
204await result.outcome;
205if (options.verbosity === CommandVerbosity.OUTPUT) {
206this.logger.debug(
207CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.End),
208);
209}
210this.logger.logStream("\n", process.stdout);
211} catch (reason) {
212return this.generateRejectionForCommand(commandWithArgs, reason);
213}
831f4a85Patricio Beltran9 years ago214}
215
af1474acRedMickey6 years ago216public selectReactNativeCLI(): string {
34472878RedMickey5 years ago217return (
218CommandExecutor.ReactNativeCommand ||
4dfb1c4cetatanova5 years ago219path.resolve(this.nodeModulesRoot, "node_modules", ".bin", "react-native")
34472878RedMickey5 years ago220);
af1474acRedMickey6 years ago221}
222
efb84653Ezio Li2 years ago223public selectExpoCLI(): string {
224return (
225CommandExecutor.ReactNativeCommand ||
226path.resolve(this.nodeModulesRoot, "node_modules", ".bin", "expo")
227);
228}
229
34472878RedMickey5 years ago230private spawnChildProcess(
231command: string,
232args: string[],
233options: Options = {},
234): ISpawnResult {
77e86943lexie0111 years ago235const spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options, {
236shell: true,
237});
09f6024fHeniker4 years ago238const commandWithArgs = `${command} ${args.join(" ")}`;
3fb37ad5unknown10 years ago239
34472878RedMickey5 years ago240this.logger.debug(
241CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.Start),
242);
9596aa53digeff10 years ago243const result = this.childProcess.spawn(command, args, spawnOptions);
3fb37ad5unknown10 years ago244
245result.stderr.on("data", (data: Buffer) => {
0a68f8dbArtem Egorov8 years ago246this.logger.logStream(data, process.stderr);
3fb37ad5unknown10 years ago247});
248
249result.stdout.on("data", (data: Buffer) => {
0a68f8dbArtem Egorov8 years ago250this.logger.logStream(data, process.stdout);
3fb37ad5unknown10 years ago251});
252
10873e11digeff10 years ago253result.outcome = result.outcome.then(
9596aa53digeff10 years ago254() =>
34472878RedMickey5 years ago255this.logger.debug(
256CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.End),
257),
258reason => this.generateRejectionForCommand(commandWithArgs, reason),
259);
efa076b0Meena Kunnathur Balakrishnan10 years ago260return result;
3fb37ad5unknown10 years ago261}
10873e11digeff10 years ago262
ce5e88eeYuri Skorokhodov5 years ago263private generateRejectionForCommand(command: string, reason: any): Promise<void> {
34472878RedMickey5 years ago264return Promise.reject<void>(
60ad4ec0JiglioNero5 years ago265reason.errorCode === InternalErrorCode.CommandFailed
266? reason
267: ErrorHelper.getNestedError(reason, InternalErrorCode.CommandFailed, command),
34472878RedMickey5 years ago268);
10873e11digeff10 years ago269}
0a68f8dbArtem Egorov8 years ago270
271private static getCommandStatusString(command: string, status: CommandStatus) {
272switch (status) {
273case CommandStatus.Start:
fc602bb6Yuri Skorokhodov7 years ago274return `Executing command: ${command}`;
0a68f8dbArtem Egorov8 years ago275case CommandStatus.End:
fc602bb6Yuri Skorokhodov7 years ago276return `Finished executing: ${command}`;
0a68f8dbArtem Egorov8 years ago277default:
fc602bb6Yuri Skorokhodov7 years ago278throw ErrorHelper.getInternalError(InternalErrorCode.UnsupportedCommandStatus);
0a68f8dbArtem Egorov8 years ago279}
280}
3fb37ad5unknown10 years ago281}