-
-
Notifications
You must be signed in to change notification settings - Fork 27k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add preflight CWD check for npm (#3355)
* Add preflight CWD check for npm * Typos
- Loading branch information
Showing
1 changed file
with
76 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 = '[email protected]'; | ||
} | ||
|
||
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 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(''); | ||
} 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 misconfigured 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. | ||
|