Skip to content

Commit 8f0aed6

Browse files
author
Martin Konicek
committed
Allow configuring the way CLI installs react-native
Summary: - Added an option to override the install command in CI environments (see comment in code) - Simplify the verbose mode - Simplify how options are passed round Test plan (only tested on Mac OS): react-native init TestApp react-native init TestApp --version 0.36 In both cases the app was generated, package.json contained the correct version (latest, or 0.36). react-native init TestApp --verbose Saw progress bar. react-native init InstallCommandTest --installCommand "npm install bad-package-doesnt-exist" 404 error is printed to stdout correctly. react-native init TestApp --installCommand "npm install react-native" The app was generated. react-native init InstallCommandTest --installCommand "npm install react-native --verbose" --verbose Saw verbose output from npm. Reviewed By: bestander Differential Revision: D4284642 fbshipit-source-id: f2cdee52ab64831ae3ca064d50f23c5f73a0301f
1 parent e335ca0 commit 8f0aed6

File tree

2 files changed

+53
-61
lines changed

2 files changed

+53
-61
lines changed

react-native-cli/index.js

+52-60
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ var fs = require('fs');
3939
var path = require('path');
4040
var exec = require('child_process').exec;
4141
var execSync = require('child_process').execSync;
42-
var spawn = require('child_process').spawn;
4342
var chalk = require('chalk');
4443
var prompt = require('prompt');
4544
var semver = require('semver');
@@ -55,7 +54,9 @@ var semver = require('semver');
5554
* - "https://registry.npmjs.org/react-native/-/react-native-0.20.0.tgz" - a .tgz archive from any npm repo
5655
* - "/Users/home/react-native/react-native-0.22.0.tgz" - for package prepared with `npm pack`, useful for e2e tests
5756
*/
58-
var argv = require('minimist')(process.argv.slice(2));
57+
58+
var options = require('minimist')(process.argv.slice(2));
59+
checkForVersionArgument(options);
5960

6061
var CLI_MODULE_PATH = function() {
6162
return path.resolve(
@@ -102,20 +103,17 @@ function getYarnVersionIfAvailable() {
102103
}
103104
}
104105

105-
checkForVersionArgument();
106-
107106
var cli;
108107
var cliPath = CLI_MODULE_PATH();
109108
if (fs.existsSync(cliPath)) {
110109
cli = require(cliPath);
111110
}
112111

113-
// minimist api
114-
var commands = argv._;
112+
var commands = options._;
115113
if (cli) {
116114
cli.run();
117115
} else {
118-
if (argv._.length === 0 && (argv.h || argv.help)) {
116+
if (options._.length === 0 && (options.h || options.help)) {
119117
console.log([
120118
'',
121119
' Usage: react-native [command] [options]',
@@ -149,8 +147,7 @@ if (cli) {
149147
);
150148
process.exit(1);
151149
} else {
152-
const rnPackage = argv.version;
153-
init(commands[1], argv.verbose, rnPackage, argv.npm);
150+
init(commands[1], options);
154151
}
155152
break;
156153
default:
@@ -186,22 +183,22 @@ function validateProjectName(name) {
186183

187184
/**
188185
* @param name Project name, e.g. 'AwesomeApp'.
189-
* @param verbose If true, will run 'npm install' in verbose mode (for debugging).
190-
* @param rnPackage Version of React Native to install, e.g. '0.38.0'.
191-
* @param forceNpmClient If true, always use the npm command line client,
186+
* @param options.verbose If true, will run 'npm install' in verbose mode (for debugging).
187+
* @param options.version Version of React Native to install, e.g. '0.38.0'.
188+
* @param options.npm If true, always use the npm command line client,
192189
* don't use yarn even if available.
193190
*/
194-
function init(name, verbose, rnPackage, forceNpmClient) {
191+
function init(name, options) {
195192
validateProjectName(name);
196193

197194
if (fs.existsSync(name)) {
198-
createAfterConfirmation(name, verbose, rnPackage, forceNpmClient);
195+
createAfterConfirmation(name, options);
199196
} else {
200-
createProject(name, verbose, rnPackage, forceNpmClient);
197+
createProject(name, options);
201198
}
202199
}
203200

204-
function createAfterConfirmation(name, verbose, rnPackage, forceNpmClient) {
201+
function createAfterConfirmation(name, options) {
205202
prompt.start();
206203

207204
var property = {
@@ -214,15 +211,15 @@ function createAfterConfirmation(name, verbose, rnPackage, forceNpmClient) {
214211

215212
prompt.get(property, function (err, result) {
216213
if (result.yesno[0] === 'y') {
217-
createProject(name, verbose, rnPackage, forceNpmClient);
214+
createProject(name, options);
218215
} else {
219216
console.log('Project initialization canceled');
220217
process.exit();
221218
}
222219
});
223220
}
224221

225-
function createProject(name, verbose, rnPackage, forceNpmClient) {
222+
function createProject(name, options) {
226223
var root = path.resolve(name);
227224
var projectName = path.basename(root);
228225

@@ -246,11 +243,7 @@ function createProject(name, verbose, rnPackage, forceNpmClient) {
246243
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson));
247244
process.chdir(root);
248245

249-
if (verbose) {
250-
runVerbose(root, projectName, rnPackage, forceNpmClient);
251-
} else {
252-
run(root, projectName, rnPackage, forceNpmClient);
253-
}
246+
run(root, projectName, options);
254247
}
255248

256249
function getInstallPackage(rnPackage) {
@@ -265,46 +258,45 @@ function getInstallPackage(rnPackage) {
265258
return packageToInstall;
266259
}
267260

268-
function run(root, projectName, rnPackage, forceNpmClient) {
261+
function run(root, projectName, options) {
262+
// E.g. '0.38' or '/path/to/archive.tgz'
263+
const rnPackage = options.version;
264+
const forceNpmClient = options.npm;
269265
const yarnVersion = (!forceNpmClient) && getYarnVersionIfAvailable();
270266
var installCommand;
271-
if (yarnVersion) {
272-
console.log('Using yarn v' + yarnVersion);
273-
console.log('Installing ' + getInstallPackage(rnPackage) + '...');
274-
installCommand = 'yarn add ' + getInstallPackage(rnPackage) + ' --exact';
267+
if (options.installCommand) {
268+
// In CI environments it can be useful to provide a custom command,
269+
// to set up and use an offline mirror for installing dependencies, for example.
270+
installCommand = options.installCommand;
275271
} else {
276-
console.log('Installing ' + getInstallPackage(rnPackage) + '...');
277-
if (!forceNpmClient) {
278-
console.log('Consider installing yarn to make this faster: https://yarnpkg.com');
272+
if (yarnVersion) {
273+
console.log('Using yarn v' + yarnVersion);
274+
console.log('Installing ' + getInstallPackage(rnPackage) + '...');
275+
installCommand = 'yarn add ' + getInstallPackage(rnPackage) + ' --exact';
276+
if (options.verbose) {
277+
installCommand += ' --verbose';
278+
}
279+
} else {
280+
console.log('Installing ' + getInstallPackage(rnPackage) + '. This might take a while...');
281+
if (!forceNpmClient) {
282+
console.log('Consider installing yarn to make this faster: https://yarnpkg.com');
283+
}
284+
installCommand = 'npm install --save --save-exact ' + getInstallPackage(rnPackage);
285+
if (options.verbose) {
286+
installCommand += ' --verbose';
287+
}
279288
}
280-
installCommand = 'npm install --save --save-exact ' + getInstallPackage(rnPackage);
281289
}
282-
exec(installCommand, function(err, stdout, stderr) {
283-
if (err) {
284-
console.log(stdout);
285-
console.error(stderr);
286-
console.error('Command `' + installCommand + '` failed.');
287-
process.exit(1);
288-
}
289-
checkNodeVersion();
290-
cli = require(CLI_MODULE_PATH());
291-
cli.init(root, projectName);
292-
});
293-
}
294-
295-
function runVerbose(root, projectName, rnPackage, forceNpmClient) {
296-
// Use npm client, yarn doesn't support --verbose yet
297-
console.log('Installing ' + getInstallPackage(rnPackage) + ' from npm. This might take a while...');
298-
var proc = spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['install', '--verbose', '--save', '--save-exact', getInstallPackage(rnPackage)], {stdio: 'inherit'});
299-
proc.on('close', function (code) {
300-
if (code !== 0) {
301-
console.error('`npm install --save --save-exact react-native` failed');
302-
return;
303-
}
304-
305-
cli = require(CLI_MODULE_PATH());
306-
cli.init(root, projectName);
307-
});
290+
try {
291+
execSync(installCommand, {stdio: 'inherit'});
292+
} catch (err) {
293+
console.error(err);
294+
console.error('Command `' + installCommand + '` failed.');
295+
process.exit(1);
296+
}
297+
checkNodeVersion();
298+
cli = require(CLI_MODULE_PATH());
299+
cli.init(root, projectName);
308300
}
309301

310302
function checkNodeVersion() {
@@ -323,8 +315,8 @@ function checkNodeVersion() {
323315
}
324316
}
325317

326-
function checkForVersionArgument() {
327-
if (argv._.length === 0 && (argv.v || argv.version)) {
318+
function checkForVersionArgument(options) {
319+
if (options._.length === 0 && (options.v || options.version)) {
328320
console.log('react-native-cli: ' + require('./package.json').version);
329321
try {
330322
console.log('react-native: ' + require(REACT_NATIVE_PACKAGE_JSON_PATH()).version);

react-native-cli/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-cli",
3-
"version": "1.3.0",
3+
"version": "2.0.0",
44
"license": "BSD-3-Clause",
55
"description": "The React Native CLI tools",
66
"main": "index.js",

0 commit comments

Comments
 (0)