@@ -158,8 +158,13 @@ function createApp(name, verbose, version, template) {
158
158
path . join ( root , 'package.json' ) ,
159
159
JSON . stringify ( packageJson , null , 2 )
160
160
) ;
161
+
162
+ const useYarn = shouldUseYarn ( ) ;
161
163
const originalDirectory = process . cwd ( ) ;
162
164
process . chdir ( root ) ;
165
+ if ( ! useYarn && ! checkThatNpmCanReadCwd ( ) ) {
166
+ process . exit ( 1 ) ;
167
+ }
163
168
164
169
if ( ! semver . satisfies ( process . version , '>=6.0.0' ) ) {
165
170
console . log (
@@ -172,7 +177,6 @@ function createApp(name, verbose, version, template) {
172
177
173
178
}
174
179
175
- const useYarn = shouldUseYarn ( ) ;
176
180
if ( ! useYarn ) {
177
181
const npmInfo = checkNpmVersion ( ) ;
178
182
if ( ! npmInfo . hasMinNpm ) {
@@ -200,7 +204,7 @@ function shouldUseYarn() {
200
204
}
201
205
}
202
206
203
- function install ( useYarn , dependencies , verbose , isOnline ) {
207
+ function install ( root , useYarn , dependencies , verbose , isOnline ) {
204
208
return new Promise ( ( resolve , reject ) => {
205
209
let command ;
206
210
let args ;
@@ -212,6 +216,14 @@ function install(useYarn, dependencies, verbose, isOnline) {
212
216
}
213
217
[ ] . push . apply ( args , dependencies ) ;
214
218
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
+
215
227
if ( ! isOnline ) {
216
228
console . log ( chalk . yellow ( 'You appear to be offline.' ) ) ;
217
229
console . log ( chalk . yellow ( 'Falling back to the local Yarn cache.' ) ) ;
@@ -275,7 +287,7 @@ function run(
275
287
) ;
276
288
console . log ( ) ;
277
289
278
- return install ( useYarn , allDependencies , verbose , isOnline ) . then (
290
+ return install ( root , useYarn , allDependencies , verbose , isOnline ) . then (
279
291
( ) => packageName
280
292
) ;
281
293
} )
@@ -606,6 +618,67 @@ function isSafeToCreateProjectIn(root, name) {
606
618
return false ;
607
619
}
608
620
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
+
609
682
function checkIfOnline ( useYarn ) {
610
683
if ( ! useYarn ) {
611
684
// Don't ping the Yarn registry.
0 commit comments