From 138bf50bfbf8df5d006098069c14e1f6e7787cdb Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 30 Oct 2017 20:16:44 +0000 Subject: [PATCH 1/2] Add preflight CWD check for npm --- packages/create-react-app/createReactApp.js | 79 ++++++++++++++++++++- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/packages/create-react-app/createReactApp.js b/packages/create-react-app/createReactApp.js index 161beab50e8..0b464b97708 100755 --- a/packages/create-react-app/createReactApp.js +++ b/packages/create-react-app/createReactApp.js @@ -158,8 +158,13 @@ function createApp(name, verbose, version, template) { path.join(root, 'package.json'), JSON.stringify(packageJson, null, 2) ); + + const useYarn = shouldUseYarn(); const originalDirectory = process.cwd(); process.chdir(root); + if (!useYarn && !checkThatNpmCanReadCwd()) { + process.exit(1); + } if (!semver.satisfies(process.version, '>=6.0.0')) { console.log( @@ -172,7 +177,6 @@ function createApp(name, verbose, version, template) { version = 'react-scripts@0.9.x'; } - const useYarn = shouldUseYarn(); if (!useYarn) { const npmInfo = checkNpmVersion(); if (!npmInfo.hasMinNpm) { @@ -200,7 +204,7 @@ function shouldUseYarn() { } } -function install(useYarn, dependencies, verbose, isOnline) { +function install(root, useYarn, dependencies, verbose, isOnline) { return new Promise((resolve, reject) => { let command; let args; @@ -212,6 +216,14 @@ function install(useYarn, dependencies, verbose, isOnline) { } [].push.apply(args, dependencies); + // Explicitly set cwd() to work around issues like + // https://github.com/facebookincubator/create-react-app/issues/3326. + // Unfortunately we can only do this for Yarn because npm support for + // equivalent --prefix flag doesn't help with this issue. + // This is why for npm, we run checkThatNpmCanReadCwd() early instead. + args.push('--cwd'); + args.push(root); + if (!isOnline) { console.log(chalk.yellow('You appear to be offline.')); console.log(chalk.yellow('Falling back to the local Yarn cache.')); @@ -275,7 +287,7 @@ function run( ); console.log(); - return install(useYarn, allDependencies, verbose, isOnline).then( + return install(root, useYarn, allDependencies, verbose, isOnline).then( () => packageName ); }) @@ -606,6 +618,67 @@ function isSafeToCreateProjectIn(root, name) { return false; } +function checkThatNpmCanReadCwd() { + const cwd = process.cwd(); + let childOutput = null; + try { + // Note: intentionally using spawn over exec since + // the problem doesn't reproduce otherwise. + // `npm config list` is the only reliably way I could find + // to reproduce the wrong path. Just printing process.cwd() + // in a Node process was not enough. + childOutput = spawn.sync('npm', ['config', 'list']).output.join(''); + } catch (err) { + // Something went wrong spawning node. + // Not great, but it means we can't do this check. + // We might fail later on, but let's continue. + return true; + } + if (typeof childOutput !== 'string') { + return true; + } + const lines = childOutput.split('\n'); + // `npm config list` output includes the following line: + // "; cwd = C:\path\to\current\dir" (unquoted) + // I couldn't find an easier way to get it. + const prefix = '; cwd = '; + const line = lines.find(line => line.indexOf(prefix) === 0); + if (typeof line !== 'string') { + // Fail gracefully. They could remove it. + return true; + } + const npmCWD = line.substring(prefix.length); + if (npmCWD === cwd) { + return true; + } + console.error( + chalk.red( + `Could not start an npm process in the right directory.\n\n` + + `The current directory is: ${chalk.bold(cwd)}\n` + + `However, a newly started npm process runs in: ${chalk.bold( + npmCWD + )}\n\n` + + `This is probably caused by a miconfigured system terminal shell.` + ) + ); + if (process.platform === 'win32') { + console.error( + chalk.red(`On Windows, this can usually be fixed by running:\n\n`) + + ` ${chalk.cyan( + 'reg' + )} delete "HKCU\\Software\\Microsoft\\Command Processor" /v AutoRun /f\n` + + ` ${chalk.cyan( + 'reg' + )} delete "HKLM\\Software\\Microsoft\\Command Processor" /v AutoRun /f\n\n` + + chalk.red(`Try to run the above two lines in the terminal.\n`) + + chalk.red( + `To learn more about this problem, read: https://blogs.msdn.microsoft.com/oldnewthing/20071121-00/?p=24433/` + ) + ); + } + return false; +} + function checkIfOnline(useYarn) { if (!useYarn) { // Don't ping the Yarn registry. From ae860a356fbd550068545c2fc80f7f1986eef28d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 30 Oct 2017 21:23:52 +0000 Subject: [PATCH 2/2] Typos --- packages/create-react-app/createReactApp.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-react-app/createReactApp.js b/packages/create-react-app/createReactApp.js index 0b464b97708..9ff7c08cf9e 100755 --- a/packages/create-react-app/createReactApp.js +++ b/packages/create-react-app/createReactApp.js @@ -624,7 +624,7 @@ function checkThatNpmCanReadCwd() { try { // Note: intentionally using spawn over exec since // the problem doesn't reproduce otherwise. - // `npm config list` is the only reliably way I could find + // `npm config list` is the only reliable way I could find // to reproduce the wrong path. Just printing process.cwd() // in a Node process was not enough. childOutput = spawn.sync('npm', ['config', 'list']).output.join(''); @@ -658,7 +658,7 @@ function checkThatNpmCanReadCwd() { `However, a newly started npm process runs in: ${chalk.bold( npmCWD )}\n\n` + - `This is probably caused by a miconfigured system terminal shell.` + `This is probably caused by a misconfigured system terminal shell.` ) ); if (process.platform === 'win32') {