microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
b7645ff29f00ff7bc3345dffe414869527f83c8c

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/commandExecutor.ts

252lines · 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(
47private currentWorkingDirectory: string = process.cwd(),
34472878RedMickey5 years ago48private logger: ILogger = new NullLogger(),
49) {}
3fb37ad5unknown10 years ago50
ce5e88eeYuri Skorokhodov5 years ago51public execute(command: string, options: Options = {}): Promise<void> {
0a68f8dbArtem Egorov8 years ago52this.logger.debug(CommandExecutor.getCommandStatusString(command, CommandStatus.Start));
34472878RedMickey5 years ago53return this.childProcess
54.execToString(command, { cwd: this.currentWorkingDirectory, env: options.env })
55.then(
56stdout => {
57this.logger.info(stdout);
58this.logger.debug(
59CommandExecutor.getCommandStatusString(command, CommandStatus.End),
60);
61},
62(reason: Error) => 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
ce5e88eeYuri Skorokhodov5 years ago84public getReactNativeVersion(): Promise<string> {
34472878RedMickey5 years ago85return ProjectVersionHelper.getReactNativeVersions(this.currentWorkingDirectory).then(
86versions => versions.reactNativeVersion,
87);
b8a56999Patricio Beltran10 years ago88}
89
c3a987a7Meena Kunnathur Balakrishnan10 years ago90/**
91* Kills the React Native packager in a child process.
92*/
ce5e88eeYuri Skorokhodov5 years ago93public killReactPackager(packagerProcess?: cp.ChildProcess): Promise<void> {
c9b4fa6cMeena Kunnathur Balakrishnan10 years ago94if (packagerProcess) {
34472878RedMickey5 years ago95return new Promise(resolve => {
a1005420dlebu10 years ago96if (HostPlatform.getPlatformId() === HostPlatformId.WINDOWS) {
34472878RedMickey5 years ago97return resolve(
98this.childProcess
99.exec("taskkill /pid " + packagerProcess.pid + " /T /F")
100.then(res => res.outcome),
101);
a1005420dlebu10 years ago102} else {
103packagerProcess.kill();
ce5e88eeYuri Skorokhodov5 years ago104return resolve();
a1005420dlebu10 years ago105}
106}).then(() => {
e2644f37Yuri Skorokhodov7 years ago107this.logger.info(localize("PackagerStopped", "Packager stopped"));
a1005420dlebu10 years ago108});
c3a987a7Meena Kunnathur Balakrishnan10 years ago109} else {
e2644f37Yuri Skorokhodov7 years ago110this.logger.warning(localize("PackagerNotFound", "Packager not found"));
ce5e88eeYuri Skorokhodov5 years ago111return Promise.resolve();
c3a987a7Meena Kunnathur Balakrishnan10 years ago112}
113}
114
f8d32439dlebu10 years ago115/**
116* Executes a react native command and waits for its completion.
117*/
34472878RedMickey5 years ago118public spawnReactCommand(
119command: string,
120args: string[] = [],
121options: Options = {},
122): ISpawnResult {
af1474acRedMickey6 years ago123const reactCommand = HostPlatform.getNpmCliCommand(this.selectReactNativeCLI());
94cd5149Artem Egorov8 years ago124return this.spawnChildProcess(reactCommand, [command, ...args], options);
5b0582f3digeff10 years ago125}
126
831f4a85Patricio Beltran9 years ago127/**
128* Spawns a child process with the params passed
129* This method has logic to do while the command is executing
130* {command} - The command to be invoked in the child process
131* {args} - Arguments to be passed to the command
132* {options} - additional options with which the child process needs to be spawned
133*/
34472878RedMickey5 years ago134public spawnWithProgress(
135command: string,
136args: string[],
137options: Options = { verbosity: CommandVerbosity.OUTPUT },
138): Promise<void> {
831f4a85Patricio Beltran9 years ago139const spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
140const commandWithArgs = command + " " + args.join(" ");
141const timeBetweenDots = 1500;
b0af599cJimmy Thomson9 years ago142let lastDotTime = 0;
831f4a85Patricio Beltran9 years ago143
144const printDot = () => {
b0af599cJimmy Thomson9 years ago145const now = Date.now();
146if (now - lastDotTime > timeBetweenDots) {
147lastDotTime = now;
0a68f8dbArtem Egorov8 years ago148this.logger.logStream(".", process.stdout);
b0af599cJimmy Thomson9 years ago149}
831f4a85Patricio Beltran9 years ago150};
151
152if (options.verbosity === CommandVerbosity.OUTPUT) {
34472878RedMickey5 years ago153this.logger.debug(
154CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.Start),
155);
831f4a85Patricio Beltran9 years ago156}
157
158const result = this.childProcess.spawn(command, args, spawnOptions);
159
160result.stdout.on("data", (data: Buffer) => {
161if (options.verbosity === CommandVerbosity.OUTPUT) {
0a68f8dbArtem Egorov8 years ago162this.logger.logStream(data, process.stdout);
b0af599cJimmy Thomson9 years ago163} else if (options.verbosity === CommandVerbosity.PROGRESS) {
831f4a85Patricio Beltran9 years ago164printDot();
165}
166});
167
168result.stderr.on("data", (data: Buffer) => {
169if (options.verbosity === CommandVerbosity.OUTPUT) {
0a68f8dbArtem Egorov8 years ago170this.logger.logStream(data, process.stderr);
b0af599cJimmy Thomson9 years ago171} else if (options.verbosity === CommandVerbosity.PROGRESS) {
831f4a85Patricio Beltran9 years ago172printDot();
173}
174});
175
ce5e88eeYuri Skorokhodov5 years ago176return new Promise((resolve, reject) => {
177result.outcome = result.outcome.then(
178() => {
179if (options.verbosity === CommandVerbosity.OUTPUT) {
34472878RedMickey5 years ago180this.logger.debug(
181CommandExecutor.getCommandStatusString(
182commandWithArgs,
183CommandStatus.End,
184),
185);
ce5e88eeYuri Skorokhodov5 years ago186}
187this.logger.logStream("\n", process.stdout);
188resolve();
189},
190reason => {
191reject(reason);
192return this.generateRejectionForCommand(commandWithArgs, reason);
34472878RedMickey5 years ago193},
194);
ce5e88eeYuri Skorokhodov5 years ago195});
831f4a85Patricio Beltran9 years ago196}
197
af1474acRedMickey6 years ago198public selectReactNativeCLI(): string {
34472878RedMickey5 years ago199return (
200CommandExecutor.ReactNativeCommand ||
201path.resolve(this.currentWorkingDirectory, "node_modules", ".bin", "react-native")
202);
af1474acRedMickey6 years ago203}
204
34472878RedMickey5 years ago205private spawnChildProcess(
206command: string,
207args: string[],
208options: Options = {},
209): ISpawnResult {
9596aa53digeff10 years ago210const spawnOptions = Object.assign({}, { cwd: this.currentWorkingDirectory }, options);
211const commandWithArgs = command + " " + args.join(" ");
3fb37ad5unknown10 years ago212
34472878RedMickey5 years ago213this.logger.debug(
214CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.Start),
215);
9596aa53digeff10 years ago216const result = this.childProcess.spawn(command, args, spawnOptions);
3fb37ad5unknown10 years ago217
218result.stderr.on("data", (data: Buffer) => {
0a68f8dbArtem Egorov8 years ago219this.logger.logStream(data, process.stderr);
3fb37ad5unknown10 years ago220});
221
222result.stdout.on("data", (data: Buffer) => {
0a68f8dbArtem Egorov8 years ago223this.logger.logStream(data, process.stdout);
3fb37ad5unknown10 years ago224});
225
10873e11digeff10 years ago226result.outcome = result.outcome.then(
9596aa53digeff10 years ago227() =>
34472878RedMickey5 years ago228this.logger.debug(
229CommandExecutor.getCommandStatusString(commandWithArgs, CommandStatus.End),
230),
231reason => this.generateRejectionForCommand(commandWithArgs, reason),
232);
efa076b0Meena Kunnathur Balakrishnan10 years ago233return result;
3fb37ad5unknown10 years ago234}
10873e11digeff10 years ago235
ce5e88eeYuri Skorokhodov5 years ago236private generateRejectionForCommand(command: string, reason: any): Promise<void> {
34472878RedMickey5 years ago237return Promise.reject<void>(
238ErrorHelper.getNestedError(reason, InternalErrorCode.CommandFailed, command),
239);
10873e11digeff10 years ago240}
0a68f8dbArtem Egorov8 years ago241
242private static getCommandStatusString(command: string, status: CommandStatus) {
243switch (status) {
244case CommandStatus.Start:
fc602bb6Yuri Skorokhodov7 years ago245return `Executing command: ${command}`;
0a68f8dbArtem Egorov8 years ago246case CommandStatus.End:
fc602bb6Yuri Skorokhodov7 years ago247return `Finished executing: ${command}`;
0a68f8dbArtem Egorov8 years ago248default:
fc602bb6Yuri Skorokhodov7 years ago249throw ErrorHelper.getInternalError(InternalErrorCode.UnsupportedCommandStatus);
0a68f8dbArtem Egorov8 years ago250}
251}
3fb37ad5unknown10 years ago252}