Skip to content

Commit 1a61cd4

Browse files
authored
Add preflight CWD check for npm (#3355)
* Add preflight CWD check for npm * Typos
1 parent de1beec commit 1a61cd4

File tree

1 file changed

+76
-3
lines changed

1 file changed

+76
-3
lines changed

packages/create-react-app/createReactApp.js

+76-3
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,13 @@ function createApp(name, verbose, version, template) {
158158
path.join(root, 'package.json'),
159159
JSON.stringify(packageJson, null, 2)
160160
);
161+
162+
const useYarn = shouldUseYarn();
161163
const originalDirectory = process.cwd();
162164
process.chdir(root);
165+
if (!useYarn && !checkThatNpmCanReadCwd()) {
166+
process.exit(1);
167+
}
163168

164169
if (!semver.satisfies(process.version, '>=6.0.0')) {
165170
console.log(
@@ -172,7 +177,6 @@ function createApp(name, verbose, version, template) {
172177
version = '[email protected]';
173178
}
174179

175-
const useYarn = shouldUseYarn();
176180
if (!useYarn) {
177181
const npmInfo = checkNpmVersion();
178182
if (!npmInfo.hasMinNpm) {
@@ -200,7 +204,7 @@ function shouldUseYarn() {
200204
}
201205
}
202206

203-
function install(useYarn, dependencies, verbose, isOnline) {
207+
function install(root, useYarn, dependencies, verbose, isOnline) {
204208
return new Promise((resolve, reject) => {
205209
let command;
206210
let args;
@@ -212,6 +216,14 @@ function install(useYarn, dependencies, verbose, isOnline) {
212216
}
213217
[].push.apply(args, dependencies);
214218

219+
// Explicitly set cwd() to work around issues like
220+
// https://github.com/facebookincubator/create-react-app/issues/3326.
221+
// Unfortunately we can only do this for Yarn because npm support for
222+
// equivalent --prefix flag doesn't help with this issue.
223+
// This is why for npm, we run checkThatNpmCanReadCwd() early instead.
224+
args.push('--cwd');
225+
args.push(root);
226+
215227
if (!isOnline) {
216228
console.log(chalk.yellow('You appear to be offline.'));
217229
console.log(chalk.yellow('Falling back to the local Yarn cache.'));
@@ -275,7 +287,7 @@ function run(
275287
);
276288
console.log();
277289

278-
return install(useYarn, allDependencies, verbose, isOnline).then(
290+
return install(root, useYarn, allDependencies, verbose, isOnline).then(
279291
() => packageName
280292
);
281293
})
@@ -606,6 +618,67 @@ function isSafeToCreateProjectIn(root, name) {
606618
return false;
607619
}
608620

621+
function checkThatNpmCanReadCwd() {
622+
const cwd = process.cwd();
623+
let childOutput = null;
624+
try {
625+
// Note: intentionally using spawn over exec since
626+
// the problem doesn't reproduce otherwise.
627+
// `npm config list` is the only reliable way I could find
628+
// to reproduce the wrong path. Just printing process.cwd()
629+
// in a Node process was not enough.
630+
childOutput = spawn.sync('npm', ['config', 'list']).output.join('');
631+
} catch (err) {
632+
// Something went wrong spawning node.
633+
// Not great, but it means we can't do this check.
634+
// We might fail later on, but let's continue.
635+
return true;
636+
}
637+
if (typeof childOutput !== 'string') {
638+
return true;
639+
}
640+
const lines = childOutput.split('\n');
641+
// `npm config list` output includes the following line:
642+
// "; cwd = C:\path\to\current\dir" (unquoted)
643+
// I couldn't find an easier way to get it.
644+
const prefix = '; cwd = ';
645+
const line = lines.find(line => line.indexOf(prefix) === 0);
646+
if (typeof line !== 'string') {
647+
// Fail gracefully. They could remove it.
648+
return true;
649+
}
650+
const npmCWD = line.substring(prefix.length);
651+
if (npmCWD === cwd) {
652+
return true;
653+
}
654+
console.error(
655+
chalk.red(
656+
`Could not start an npm process in the right directory.\n\n` +
657+
`The current directory is: ${chalk.bold(cwd)}\n` +
658+
`However, a newly started npm process runs in: ${chalk.bold(
659+
npmCWD
660+
)}\n\n` +
661+
`This is probably caused by a misconfigured system terminal shell.`
662+
)
663+
);
664+
if (process.platform === 'win32') {
665+
console.error(
666+
chalk.red(`On Windows, this can usually be fixed by running:\n\n`) +
667+
` ${chalk.cyan(
668+
'reg'
669+
)} delete "HKCU\\Software\\Microsoft\\Command Processor" /v AutoRun /f\n` +
670+
` ${chalk.cyan(
671+
'reg'
672+
)} delete "HKLM\\Software\\Microsoft\\Command Processor" /v AutoRun /f\n\n` +
673+
chalk.red(`Try to run the above two lines in the terminal.\n`) +
674+
chalk.red(
675+
`To learn more about this problem, read: https://blogs.msdn.microsoft.com/oldnewthing/20071121-00/?p=24433/`
676+
)
677+
);
678+
}
679+
return false;
680+
}
681+
609682
function checkIfOnline(useYarn) {
610683
if (!useYarn) {
611684
// Don't ping the Yarn registry.

0 commit comments

Comments
 (0)