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
This commit is contained in:
parent
d21aa92480
commit
76cd2f7bf2
|
@ -39,7 +39,6 @@ var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
var execSync = require('child_process').execSync;
|
var execSync = require('child_process').execSync;
|
||||||
var spawn = require('child_process').spawn;
|
|
||||||
var chalk = require('chalk');
|
var chalk = require('chalk');
|
||||||
var prompt = require('prompt');
|
var prompt = require('prompt');
|
||||||
var semver = require('semver');
|
var semver = require('semver');
|
||||||
|
@ -55,7 +54,9 @@ var semver = require('semver');
|
||||||
* - "https://registry.npmjs.org/react-native/-/react-native-0.20.0.tgz" - a .tgz archive from any npm repo
|
* - "https://registry.npmjs.org/react-native/-/react-native-0.20.0.tgz" - a .tgz archive from any npm repo
|
||||||
* - "/Users/home/react-native/react-native-0.22.0.tgz" - for package prepared with `npm pack`, useful for e2e tests
|
* - "/Users/home/react-native/react-native-0.22.0.tgz" - for package prepared with `npm pack`, useful for e2e tests
|
||||||
*/
|
*/
|
||||||
var argv = require('minimist')(process.argv.slice(2));
|
|
||||||
|
var options = require('minimist')(process.argv.slice(2));
|
||||||
|
checkForVersionArgument(options);
|
||||||
|
|
||||||
var CLI_MODULE_PATH = function() {
|
var CLI_MODULE_PATH = function() {
|
||||||
return path.resolve(
|
return path.resolve(
|
||||||
|
@ -102,20 +103,17 @@ function getYarnVersionIfAvailable() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForVersionArgument();
|
|
||||||
|
|
||||||
var cli;
|
var cli;
|
||||||
var cliPath = CLI_MODULE_PATH();
|
var cliPath = CLI_MODULE_PATH();
|
||||||
if (fs.existsSync(cliPath)) {
|
if (fs.existsSync(cliPath)) {
|
||||||
cli = require(cliPath);
|
cli = require(cliPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// minimist api
|
var commands = options._;
|
||||||
var commands = argv._;
|
|
||||||
if (cli) {
|
if (cli) {
|
||||||
cli.run();
|
cli.run();
|
||||||
} else {
|
} else {
|
||||||
if (argv._.length === 0 && (argv.h || argv.help)) {
|
if (options._.length === 0 && (options.h || options.help)) {
|
||||||
console.log([
|
console.log([
|
||||||
'',
|
'',
|
||||||
' Usage: react-native [command] [options]',
|
' Usage: react-native [command] [options]',
|
||||||
|
@ -149,8 +147,7 @@ if (cli) {
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
const rnPackage = argv.version;
|
init(commands[1], options);
|
||||||
init(commands[1], argv.verbose, rnPackage, argv.npm);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -186,22 +183,22 @@ function validateProjectName(name) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name Project name, e.g. 'AwesomeApp'.
|
* @param name Project name, e.g. 'AwesomeApp'.
|
||||||
* @param verbose If true, will run 'npm install' in verbose mode (for debugging).
|
* @param options.verbose If true, will run 'npm install' in verbose mode (for debugging).
|
||||||
* @param rnPackage Version of React Native to install, e.g. '0.38.0'.
|
* @param options.version Version of React Native to install, e.g. '0.38.0'.
|
||||||
* @param forceNpmClient If true, always use the npm command line client,
|
* @param options.npm If true, always use the npm command line client,
|
||||||
* don't use yarn even if available.
|
* don't use yarn even if available.
|
||||||
*/
|
*/
|
||||||
function init(name, verbose, rnPackage, forceNpmClient) {
|
function init(name, options) {
|
||||||
validateProjectName(name);
|
validateProjectName(name);
|
||||||
|
|
||||||
if (fs.existsSync(name)) {
|
if (fs.existsSync(name)) {
|
||||||
createAfterConfirmation(name, verbose, rnPackage, forceNpmClient);
|
createAfterConfirmation(name, options);
|
||||||
} else {
|
} else {
|
||||||
createProject(name, verbose, rnPackage, forceNpmClient);
|
createProject(name, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAfterConfirmation(name, verbose, rnPackage, forceNpmClient) {
|
function createAfterConfirmation(name, options) {
|
||||||
prompt.start();
|
prompt.start();
|
||||||
|
|
||||||
var property = {
|
var property = {
|
||||||
|
@ -214,7 +211,7 @@ function createAfterConfirmation(name, verbose, rnPackage, forceNpmClient) {
|
||||||
|
|
||||||
prompt.get(property, function (err, result) {
|
prompt.get(property, function (err, result) {
|
||||||
if (result.yesno[0] === 'y') {
|
if (result.yesno[0] === 'y') {
|
||||||
createProject(name, verbose, rnPackage, forceNpmClient);
|
createProject(name, options);
|
||||||
} else {
|
} else {
|
||||||
console.log('Project initialization canceled');
|
console.log('Project initialization canceled');
|
||||||
process.exit();
|
process.exit();
|
||||||
|
@ -222,7 +219,7 @@ function createAfterConfirmation(name, verbose, rnPackage, forceNpmClient) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createProject(name, verbose, rnPackage, forceNpmClient) {
|
function createProject(name, options) {
|
||||||
var root = path.resolve(name);
|
var root = path.resolve(name);
|
||||||
var projectName = path.basename(root);
|
var projectName = path.basename(root);
|
||||||
|
|
||||||
|
@ -246,11 +243,7 @@ function createProject(name, verbose, rnPackage, forceNpmClient) {
|
||||||
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson));
|
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson));
|
||||||
process.chdir(root);
|
process.chdir(root);
|
||||||
|
|
||||||
if (verbose) {
|
run(root, projectName, options);
|
||||||
runVerbose(root, projectName, rnPackage, forceNpmClient);
|
|
||||||
} else {
|
|
||||||
run(root, projectName, rnPackage, forceNpmClient);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInstallPackage(rnPackage) {
|
function getInstallPackage(rnPackage) {
|
||||||
|
@ -265,46 +258,45 @@ function getInstallPackage(rnPackage) {
|
||||||
return packageToInstall;
|
return packageToInstall;
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(root, projectName, rnPackage, forceNpmClient) {
|
function run(root, projectName, options) {
|
||||||
|
// E.g. '0.38' or '/path/to/archive.tgz'
|
||||||
|
const rnPackage = options.version;
|
||||||
|
const forceNpmClient = options.npm;
|
||||||
const yarnVersion = (!forceNpmClient) && getYarnVersionIfAvailable();
|
const yarnVersion = (!forceNpmClient) && getYarnVersionIfAvailable();
|
||||||
var installCommand;
|
var installCommand;
|
||||||
|
if (options.installCommand) {
|
||||||
|
// In CI environments it can be useful to provide a custom command,
|
||||||
|
// to set up and use an offline mirror for installing dependencies, for example.
|
||||||
|
installCommand = options.installCommand;
|
||||||
|
} else {
|
||||||
if (yarnVersion) {
|
if (yarnVersion) {
|
||||||
console.log('Using yarn v' + yarnVersion);
|
console.log('Using yarn v' + yarnVersion);
|
||||||
console.log('Installing ' + getInstallPackage(rnPackage) + '...');
|
console.log('Installing ' + getInstallPackage(rnPackage) + '...');
|
||||||
installCommand = 'yarn add ' + getInstallPackage(rnPackage) + ' --exact';
|
installCommand = 'yarn add ' + getInstallPackage(rnPackage) + ' --exact';
|
||||||
|
if (options.verbose) {
|
||||||
|
installCommand += ' --verbose';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Installing ' + getInstallPackage(rnPackage) + '...');
|
console.log('Installing ' + getInstallPackage(rnPackage) + '. This might take a while...');
|
||||||
if (!forceNpmClient) {
|
if (!forceNpmClient) {
|
||||||
console.log('Consider installing yarn to make this faster: https://yarnpkg.com');
|
console.log('Consider installing yarn to make this faster: https://yarnpkg.com');
|
||||||
}
|
}
|
||||||
installCommand = 'npm install --save --save-exact ' + getInstallPackage(rnPackage);
|
installCommand = 'npm install --save --save-exact ' + getInstallPackage(rnPackage);
|
||||||
|
if (options.verbose) {
|
||||||
|
installCommand += ' --verbose';
|
||||||
}
|
}
|
||||||
exec(installCommand, function(err, stdout, stderr) {
|
}
|
||||||
if (err) {
|
}
|
||||||
console.log(stdout);
|
try {
|
||||||
console.error(stderr);
|
execSync(installCommand, {stdio: 'inherit'});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
console.error('Command `' + installCommand + '` failed.');
|
console.error('Command `' + installCommand + '` failed.');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
checkNodeVersion();
|
checkNodeVersion();
|
||||||
cli = require(CLI_MODULE_PATH());
|
cli = require(CLI_MODULE_PATH());
|
||||||
cli.init(root, projectName);
|
cli.init(root, projectName);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function runVerbose(root, projectName, rnPackage, forceNpmClient) {
|
|
||||||
// Use npm client, yarn doesn't support --verbose yet
|
|
||||||
console.log('Installing ' + getInstallPackage(rnPackage) + ' from npm. This might take a while...');
|
|
||||||
var proc = spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['install', '--verbose', '--save', '--save-exact', getInstallPackage(rnPackage)], {stdio: 'inherit'});
|
|
||||||
proc.on('close', function (code) {
|
|
||||||
if (code !== 0) {
|
|
||||||
console.error('`npm install --save --save-exact react-native` failed');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cli = require(CLI_MODULE_PATH());
|
|
||||||
cli.init(root, projectName);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkNodeVersion() {
|
function checkNodeVersion() {
|
||||||
|
@ -323,8 +315,8 @@ function checkNodeVersion() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkForVersionArgument() {
|
function checkForVersionArgument(options) {
|
||||||
if (argv._.length === 0 && (argv.v || argv.version)) {
|
if (options._.length === 0 && (options.v || options.version)) {
|
||||||
console.log('react-native-cli: ' + require('./package.json').version);
|
console.log('react-native-cli: ' + require('./package.json').version);
|
||||||
try {
|
try {
|
||||||
console.log('react-native: ' + require(REACT_NATIVE_PACKAGE_JSON_PATH()).version);
|
console.log('react-native: ' + require(REACT_NATIVE_PACKAGE_JSON_PATH()).version);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "react-native-cli",
|
"name": "react-native-cli",
|
||||||
"version": "1.3.0",
|
"version": "2.0.0",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"description": "The React Native CLI tools",
|
"description": "The React Native CLI tools",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|
Loading…
Reference in New Issue