microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
43e6ccc3781e2fec953ee0059638ffa0e5d403ab

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/commandExecutor.ts

240lines · 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";
34472878RedMickey5 years ago6import { ILogger } from "../extension/log/LogHelper";
7import { NullLogger } from "../extension/log/NullLogger";
8import { ProjectVersionHelper } from "../common/projectVersionHelper";
9import { ISpawnResult } from "./node/childProcess";
10import { HostPlatform, HostPlatformId } from "./hostPlatform";
11import { ErrorHelper } from "./error/errorHelper";
12import { InternalErrorCode } from "./error/internalErrorCode";
e2644f37Yuri Skorokhodov7 years ago13import * as nls from "vscode-nls";
ce5e88eeYuri Skorokhodov5 years ago14import { Node } from "./node/node";
34472878RedMickey5 years ago15nls.config({
16messageFormat: nls.MessageFormat.bundle,
17bundleFormat: nls.BundleFormat.standalone,
18})();
e2644f37Yuri Skorokhodov7 years ago19const localize = nls.loadMessageBundle();
3fb37ad5unknown10 years ago20
831f4a85Patricio Beltran9 years ago21export enum CommandVerbosity {
22OUTPUT,
23SILENT,
24PROGRESS,
25}
26
3fb37ad5unknown10 years ago27interface EnvironmentOptions {
28REACT_DEBUGGER?: string;
29}
30
31interface Options {
32env?: EnvironmentOptions;
831f4a85Patricio Beltran9 years ago33verbosity?: CommandVerbosity;
0d827d9bJimmy Thomson9 years ago34cwd?: string;
3fb37ad5unknown10 years ago35}
36
17161993Meena Kunnathur Balakrishnan10 years ago37export enum CommandStatus {
38Start = 0,
27710197Vladimir Kotikov8 years ago39End = 1,
17161993Meena Kunnathur Balakrishnan10 years ago40}
41
3fb37ad5unknown10 years ago42export class CommandExecutor {
af1474acRedMickey6 years ago43public static ReactNativeCommand: string | null;
9596aa53digeff10 years ago44private childProcess = new Node.ChildProcess();
3fb37ad5unknown10 years ago45
0a68f8dbArtem Egorov8 years ago46constructor(
4dfb1c4cetatanova5 years ago47private nodeModulesRoot: string,
0a68f8dbArtem Egorov8 years ago48private currentWorkingDirectory: string = process.cwd(),
34472878RedMickey5 years ago49private logger: ILogger = new NullLogger(),
50) {}
3fb37ad5unknown10 years ago51
0d77292aJiglioNero4 years ago52public async execute(command: string, options: Options = {}): Promise<void> {
0a68f8dbArtem Egorov8 years ago53this.logger.debug(CommandExecutor.getCommandStatusString(command, CommandStatus.Start));
0d77292aJiglioNero4 years ago54try {
55const stdout = await this.childProcess.execToString(command, {
56cwd: this.currentWorkingDirectory,
57env: options.env,
58});
59this.logger.info(stdout);
60this.logger.debug(CommandExecutor.getCommandStatusString(command, CommandStatus.End));
61} catch (reason) {
62return this.generateRejectionForCommand(command, reason);
63}
3fb37ad5unknown10 years ago64}
65
45944d15Meena Kunnathur Balakrishnan10 years ago66/**
67* Spawns a child process with the params passed
68* This method waits until the spawned process finishes execution
69* {command} - The command to be invoked in the child process
70* {args} - Arguments to be passed to the command
71* {options} - additional options with which the child process needs to be spawned
72*/
ce5e88eeYuri Skorokhodov5 years ago73public spawn(command: string, args: string[], options: Options = {}): Promise<any> {
9596aa53digeff10 years ago74return this.spawnChildProcess(command, args, options).outcome;
45944d15Meena Kunnathur Balakrishnan10 years ago75}
76
6126d899Meena Kunnathur Balakrishnan10 years ago77/**
78* Spawns the React Native packager in a child process.
79*/
9596aa53digeff10 years ago80public spawnReactPackager(args: string[], options: Options = {}): ISpawnResult {
81return this.spawnReactCommand("start", args, options);
6126d899Meena Kunnathur Balakrishnan10 years ago82}
83
0d77292aJiglioNero4 years ago84public async getReactNativeVersion(): Promise<string> {
85const versions = await ProjectVersionHelper.getReactNativeVersions(
86this.currentWorkingDirectory,
34472878RedMickey5 years ago87);
0d77292aJiglioNero4 years ago88return versions.reactNativeVersion;
b8a56999Patricio Beltran9 years ago89}
90
c3a987a7Meena Kunnathur Balakrishnan10 years ago91/**
92* Kills the React Native packager in a child process.
93*/
0d77292aJiglioNero4 years ago94public async killReactPackager(packagerProcess?: cp.ChildProcess): Promise<void> {
c9b4fa6cMeena Kunnathur Balakrishnan10 years ago95if (packagerProcess) {
0d77292aJiglioNero4 years ago96if (HostPlatform.getPlatformId() === HostPlatformId.WINDOWS) {
97const res = await this.childProcess.exec(
98"taskkill /pid " + packagerProcess.pid + " /T /F",
99);
100await res.outcome;
101} else {
102packagerProcess.kill();
103}
104this.logger.info(localize("PackagerStopped", "Packager stopped"));
c3a987a7Meena Kunnathur Balakrishnan10 years ago105} else {
e2644f37Yuri Skorokhodov7 years ago106this.logger.warning(localize("PackagerNotFound", "Packager not found"));
c3a987a7Meena Kunnathur Balakrishnan10 years ago107}
108}
109
f8d32439dlebu10 years ago110/**
111* Executes a react native command and waits for its completion.
112*/
34472878RedMickey5 years ago113public spawnReactCommand(
114command: string,
115args: string[] = [],
116options: Options = {},
117): ISpawnResult {
af1474acRedMickey6 years ago118const reactCommand = HostPlatform.getNpmCliCommand(this.selectReactNativeCLI());
94cd5149Artem Egorov8 years ago119return this.spawnChildProcess(reactCommand, [command, ...args], options);
5b0582f3digeff10 years ago120}
121
831f4a85Patricio Beltran9 years ago122/**
123* Spawns a child process with the params passed
124* This method has logic to do while the command is executing
125* {command} - The command to be invoked in the child process
126* {args} - Arguments to be passed to the command
127* {options} - additional options with which the child process needs to be spawned
128*/
0d77292aJiglioNero4 years ago129public async spawnWithProgress(
34472878RedMickey5 years ago130command: string,
131args: string[],
132options: Options = { verbosity: CommandVerbosity.OUTPUT },
133): Promise<void> {
831f4a85Patricio Beltran9 years ago134const spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
135const commandWithArgs = command + " " + args.join(" ");
136const timeBetweenDots = 1500;
b0af599cJimmy Thomson9 years ago137let lastDotTime = 0;
831f4a85Patricio Beltran9 years ago138
139const printDot = () => {
b0af599cJimmy Thomson9 years ago140const now = Date.now();
141if (now - lastDotTime > timeBetweenDots) {
142lastDotTime = now;
0a68f8dbArtem Egorov8 years ago143this.logger.logStream(".", process.stdout);
b0af599cJimmy Thomson9 years ago144}
831f4a85Patricio Beltran9 years ago145};
146
147if (options.verbosity === CommandVerbosity.OUTPUT) {
34472878RedMickey5 years ago148this.logger.debug(
149CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.Start),
150);
831f4a85Patricio Beltran9 years ago151}
152
153const result = this.childProcess.spawn(command, args, spawnOptions);
154
155result.stdout.on("data", (data: Buffer) => {
156if (options.verbosity === CommandVerbosity.OUTPUT) {
0a68f8dbArtem Egorov8 years ago157this.logger.logStream(data, process.stdout);
b0af599cJimmy Thomson9 years ago158} else if (options.verbosity === CommandVerbosity.PROGRESS) {
831f4a85Patricio Beltran9 years ago159printDot();
160}
161});
162
163result.stderr.on("data", (data: Buffer) => {
164if (options.verbosity === CommandVerbosity.OUTPUT) {
0a68f8dbArtem Egorov8 years ago165this.logger.logStream(data, process.stderr);
b0af599cJimmy Thomson9 years ago166} else if (options.verbosity === CommandVerbosity.PROGRESS) {
831f4a85Patricio Beltran9 years ago167printDot();
168}
169});
170
0d77292aJiglioNero4 years ago171try {
172await result.outcome;
173if (options.verbosity === CommandVerbosity.OUTPUT) {
174this.logger.debug(
175CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.End),
176);
177}
178this.logger.logStream("\n", process.stdout);
179} catch (reason) {
180return this.generateRejectionForCommand(commandWithArgs, reason);
181}
831f4a85Patricio Beltran9 years ago182}
183
af1474acRedMickey6 years ago184public selectReactNativeCLI(): string {
34472878RedMickey5 years ago185return (
186CommandExecutor.ReactNativeCommand ||
4dfb1c4cetatanova5 years ago187path.resolve(this.nodeModulesRoot, "node_modules", ".bin", "react-native")
34472878RedMickey5 years ago188);
af1474acRedMickey6 years ago189}
190
34472878RedMickey5 years ago191private spawnChildProcess(
192command: string,
193args: string[],
194options: Options = {},
195): ISpawnResult {
9596aa53digeff10 years ago196const spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
197const commandWithArgs = command + " " + args.join(" ");
3fb37ad5unknown10 years ago198
34472878RedMickey5 years ago199this.logger.debug(
200CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.Start),
201);
9596aa53digeff10 years ago202const result = this.childProcess.spawn(command, args, spawnOptions);
3fb37ad5unknown10 years ago203
204result.stderr.on("data", (data: Buffer) => {
0a68f8dbArtem Egorov8 years ago205this.logger.logStream(data, process.stderr);
3fb37ad5unknown10 years ago206});
207
208result.stdout.on("data", (data: Buffer) => {
0a68f8dbArtem Egorov8 years ago209this.logger.logStream(data, process.stdout);
3fb37ad5unknown10 years ago210});
211
10873e11digeff10 years ago212result.outcome = result.outcome.then(
9596aa53digeff10 years ago213() =>
34472878RedMickey5 years ago214this.logger.debug(
215CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.End),
216),
217reason => this.generateRejectionForCommand(commandWithArgs, reason),
218);
efa076b0Meena Kunnathur Balakrishnan10 years ago219return result;
3fb37ad5unknown10 years ago220}
10873e11digeff10 years ago221
ce5e88eeYuri Skorokhodov5 years ago222private generateRejectionForCommand(command: string, reason: any): Promise<void> {
34472878RedMickey5 years ago223return Promise.reject<void>(
60ad4ec0JiglioNero5 years ago224reason.errorCode === InternalErrorCode.CommandFailed
225? reason
226: ErrorHelper.getNestedError(reason, InternalErrorCode.CommandFailed, command),
34472878RedMickey5 years ago227);
10873e11digeff10 years ago228}
0a68f8dbArtem Egorov8 years ago229
230private static getCommandStatusString(command: string, status: CommandStatus) {
231switch (status) {
232case CommandStatus.Start:
fc602bb6Yuri Skorokhodov7 years ago233return `Executing command: ${command}`;
0a68f8dbArtem Egorov8 years ago234case CommandStatus.End:
fc602bb6Yuri Skorokhodov7 years ago235return `Finished executing: ${command}`;
0a68f8dbArtem Egorov8 years ago236default:
fc602bb6Yuri Skorokhodov7 years ago237throw ErrorHelper.getInternalError(InternalErrorCode.UnsupportedCommandStatus);
0a68f8dbArtem Egorov8 years ago238}
239}
3fb37ad5unknown10 years ago240}