@@ -53,14 +53,6 @@ const validateProjectName = require('validate-npm-package-name');
53
53
54
54
const packageJson = require ( './package.json' ) ;
55
55
56
- // These files should be allowed to remain on a failed install,
57
- // but then silently removed during the next create.
58
- const errorLogFilePatterns = [
59
- 'npm-debug.log' ,
60
- 'yarn-error.log' ,
61
- 'yarn-debug.log' ,
62
- ] ;
63
-
64
56
let projectName ;
65
57
66
58
const program = new commander . Command ( packageJson . name )
@@ -192,14 +184,6 @@ if (typeof projectName === 'undefined') {
192
184
process . exit ( 1 ) ;
193
185
}
194
186
195
- function printValidationResults ( results ) {
196
- if ( typeof results !== 'undefined' ) {
197
- results . forEach ( error => {
198
- console . error ( chalk . red ( ` * ${ error } ` ) ) ;
199
- } ) ;
200
- }
201
- }
202
-
203
187
createApp (
204
188
projectName ,
205
189
program . verbose ,
@@ -247,6 +231,7 @@ function createApp(
247
231
if ( ! isSafeToCreateProjectIn ( root , name ) ) {
248
232
process . exit ( 1 ) ;
249
233
}
234
+ console . log ( ) ;
250
235
251
236
console . log ( `Creating a new React app in ${ chalk . green ( root ) } .` ) ;
252
237
console . log ( ) ;
@@ -448,10 +433,7 @@ function run(
448
433
. then ( ( { isOnline, packageInfo, templateInfo } ) => {
449
434
let packageVersion = semver . coerce ( packageInfo . version ) ;
450
435
451
- // This environment variable can be removed post-release.
452
- const templatesVersionMinimum = process . env . CRA_INTERNAL_TEST
453
- ? '3.2.0'
454
- : '3.3.0' ;
436
+ const templatesVersionMinimum = '3.3.0' ;
455
437
456
438
// Assume compatibility if we can't test the version.
457
439
if ( ! semver . valid ( packageVersion ) ) {
@@ -591,7 +573,7 @@ function getInstallPackage(version, originalDirectory) {
591
573
if ( validSemver ) {
592
574
packageToInstall += `@${ validSemver } ` ;
593
575
} else if ( version ) {
594
- if ( version [ 0 ] === '@' && version . indexOf ( '/' ) === - 1 ) {
576
+ if ( version [ 0 ] === '@' && ! version . includes ( '/' ) ) {
595
577
packageToInstall += version ;
596
578
} else if ( version . match ( / ^ f i l e : / ) ) {
597
579
packageToInstall = `file:${ path . resolve (
@@ -743,7 +725,7 @@ function getPackageInfo(installPackage) {
743
725
) ;
744
726
return Promise . resolve ( { name : assumedProjectName } ) ;
745
727
} ) ;
746
- } else if ( installPackage . indexOf ( 'git+' ) === 0 ) {
728
+ } else if ( installPackage . startsWith ( 'git+' ) ) {
747
729
// Pull package name out of git urls e.g:
748
730
// git+https://github.com/mycompany/react-scripts.git
749
731
// git+ssh://github.com/mycompany/react-scripts.git#v1.2.3
@@ -785,17 +767,25 @@ function checkNpmVersion() {
785
767
}
786
768
787
769
function checkYarnVersion ( ) {
770
+ const minYarnPnp = '1.12.0' ;
788
771
let hasMinYarnPnp = false ;
789
772
let yarnVersion = null ;
790
773
try {
791
774
yarnVersion = execSync ( 'yarnpkg --version' )
792
775
. toString ( )
793
776
. trim ( ) ;
794
- let trimmedYarnVersion = / ^ ( .+ ?) [ - + ] .+ $ / . exec ( yarnVersion ) ;
795
- if ( trimmedYarnVersion ) {
796
- trimmedYarnVersion = trimmedYarnVersion . pop ( ) ;
777
+ if ( semver . valid ( yarnVersion ) ) {
778
+ hasMinYarnPnp = semver . gte ( yarnVersion , minYarnPnp ) ;
779
+ } else {
780
+ // Handle non-semver compliant yarn version strings, which yarn currently
781
+ // uses for nightly builds. The regex truncates anything after the first
782
+ // dash. See #5362.
783
+ const trimmedYarnVersionMatch = / ^ ( .+ ?) [ - + ] .+ $ / . exec ( yarnVersion ) ;
784
+ if ( trimmedYarnVersionMatch ) {
785
+ const trimmedYarnVersion = trimmedYarnVersionMatch . pop ( ) ;
786
+ hasMinYarnPnp = semver . gte ( trimmedYarnVersion , minYarnPnp ) ;
787
+ }
797
788
}
798
- hasMinYarnPnp = semver . gte ( trimmedYarnVersion || yarnVersion , '1.12.0' ) ;
799
789
} catch ( err ) {
800
790
// ignore
801
791
}
@@ -840,22 +830,29 @@ function checkAppName(appName) {
840
830
const validationResult = validateProjectName ( appName ) ;
841
831
if ( ! validationResult . validForNewPackages ) {
842
832
console . error (
843
- `Could not create a project called ${ chalk . red (
844
- `"${ appName } "`
845
- ) } because of npm naming restrictions:`
833
+ chalk . red (
834
+ `Cannot create a project named ${ chalk . green (
835
+ `"${ appName } "`
836
+ ) } because of npm naming restrictions:\n`
837
+ )
846
838
) ;
847
- printValidationResults ( validationResult . errors ) ;
848
- printValidationResults ( validationResult . warnings ) ;
839
+ [
840
+ ...( validationResult . errors || [ ] ) ,
841
+ ...( validationResult . warnings || [ ] ) ,
842
+ ] . forEach ( error => {
843
+ console . error ( chalk . red ( ` * ${ error } ` ) ) ;
844
+ } ) ;
845
+ console . error ( chalk . red ( '\nPlease choose a different project name.' ) ) ;
849
846
process . exit ( 1 ) ;
850
847
}
851
848
852
849
// TODO: there should be a single place that holds the dependencies
853
850
const dependencies = [ 'react' , 'react-dom' , 'react-scripts' ] . sort ( ) ;
854
- if ( dependencies . indexOf ( appName ) >= 0 ) {
851
+ if ( dependencies . includes ( appName ) ) {
855
852
console . error (
856
853
chalk . red (
857
- `We cannot create a project called ${ chalk . green (
858
- appName
854
+ `Cannot create a project named ${ chalk . green (
855
+ `" ${ appName } "`
859
856
) } because a dependency with the same name exists.\n` +
860
857
`Due to the way npm works, the following names are not allowed:\n\n`
861
858
) +
@@ -917,41 +914,57 @@ function setCaretRangeForRuntimeDeps(packageName) {
917
914
function isSafeToCreateProjectIn ( root , name ) {
918
915
const validFiles = [
919
916
'.DS_Store' ,
920
- 'Thumbs.db' ,
921
917
'.git' ,
918
+ '.gitattributes' ,
922
919
'.gitignore' ,
923
- '.idea' ,
924
- 'README.md' ,
925
- 'LICENSE' ,
920
+ '.gitlab-ci.yml' ,
926
921
'.hg' ,
927
- '.hgignore' ,
928
922
'.hgcheck' ,
923
+ '.hgignore' ,
924
+ '.idea' ,
929
925
'.npmignore' ,
930
- 'mkdocs.yml' ,
931
- 'docs' ,
932
926
'.travis.yml' ,
933
- '.gitlab-ci.yml' ,
934
- '.gitattributes' ,
927
+ 'docs' ,
928
+ 'LICENSE' ,
929
+ 'README.md' ,
930
+ 'mkdocs.yml' ,
931
+ 'Thumbs.db' ,
935
932
] ;
936
- console . log ( ) ;
933
+ // These files should be allowed to remain on a failed install, but then
934
+ // silently removed during the next create.
935
+ const errorLogFilePatterns = [
936
+ 'npm-debug.log' ,
937
+ 'yarn-error.log' ,
938
+ 'yarn-debug.log' ,
939
+ ] ;
940
+ const isErrorLog = file => {
941
+ return errorLogFilePatterns . some ( pattern => file . startsWith ( pattern ) ) ;
942
+ } ;
937
943
938
944
const conflicts = fs
939
945
. readdirSync ( root )
940
946
. filter ( file => ! validFiles . includes ( file ) )
941
947
// IntelliJ IDEA creates module files before CRA is launched
942
948
. filter ( file => ! / \. i m l $ / . test ( file ) )
943
949
// Don't treat log files from previous installation as conflicts
944
- . filter (
945
- file => ! errorLogFilePatterns . some ( pattern => file . indexOf ( pattern ) === 0 )
946
- ) ;
950
+ . filter ( file => ! isErrorLog ( file ) ) ;
947
951
948
952
if ( conflicts . length > 0 ) {
949
953
console . log (
950
954
`The directory ${ chalk . green ( name ) } contains files that could conflict:`
951
955
) ;
952
956
console . log ( ) ;
953
957
for ( const file of conflicts ) {
954
- console . log ( ` ${ file } ` ) ;
958
+ try {
959
+ const stats = fs . lstatSync ( path . join ( root , file ) ) ;
960
+ if ( stats . isDirectory ( ) ) {
961
+ console . log ( ` ${ chalk . blue ( `${ file } /` ) } ` ) ;
962
+ } else {
963
+ console . log ( ` ${ file } ` ) ;
964
+ }
965
+ } catch ( e ) {
966
+ console . log ( ` ${ file } ` ) ;
967
+ }
955
968
}
956
969
console . log ( ) ;
957
970
console . log (
@@ -961,15 +974,11 @@ function isSafeToCreateProjectIn(root, name) {
961
974
return false ;
962
975
}
963
976
964
- // Remove any remnant files from a previous installation
965
- const currentFiles = fs . readdirSync ( path . join ( root ) ) ;
966
- currentFiles . forEach ( file => {
967
- errorLogFilePatterns . forEach ( errorLogFilePattern => {
968
- // This will catch `(npm-debug|yarn-error|yarn-debug).log*` files
969
- if ( file . indexOf ( errorLogFilePattern ) === 0 ) {
970
- fs . removeSync ( path . join ( root , file ) ) ;
971
- }
972
- } ) ;
977
+ // Remove any log files from a previous installation.
978
+ fs . readdirSync ( root ) . forEach ( file => {
979
+ if ( isErrorLog ( file ) ) {
980
+ fs . removeSync ( path . join ( root , file ) ) ;
981
+ }
973
982
} ) ;
974
983
return true ;
975
984
}
@@ -989,6 +998,8 @@ function getProxy() {
989
998
}
990
999
}
991
1000
}
1001
+
1002
+ // See https://github.com/facebook/create-react-app/pull/3355
992
1003
function checkThatNpmCanReadCwd ( ) {
993
1004
const cwd = process . cwd ( ) ;
994
1005
let childOutput = null ;
@@ -1013,7 +1024,7 @@ function checkThatNpmCanReadCwd() {
1013
1024
// "; cwd = C:\path\to\current\dir" (unquoted)
1014
1025
// I couldn't find an easier way to get it.
1015
1026
const prefix = '; cwd = ' ;
1016
- const line = lines . find ( line => line . indexOf ( prefix ) === 0 ) ;
1027
+ const line = lines . find ( line => line . startsWith ( prefix ) ) ;
1017
1028
if ( typeof line !== 'string' ) {
1018
1029
// Fail gracefully. They could remove it.
1019
1030
return true ;
0 commit comments