@@ -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) {
172177173178 }
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+
609682function checkIfOnline ( useYarn ) {
610683 if ( ! useYarn ) {
611684 // Don't ping the Yarn registry.
0 commit comments