@@ -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 )
@@ -156,6 +148,10 @@ const program = new commander.Command(packageJson.name)
156
148
157
149
if ( program . info ) {
158
150
console . log ( chalk . bold ( '\nEnvironment Info:' ) ) ;
151
+ console . log (
152
+ `\n current version of ${ packageJson . name } : ${ packageJson . version } `
153
+ ) ;
154
+ console . log ( ` running from ${ __dirname } ` ) ;
159
155
return envinfo
160
156
. run (
161
157
{
@@ -188,14 +184,6 @@ if (typeof projectName === 'undefined') {
188
184
process . exit ( 1 ) ;
189
185
}
190
186
191
- function printValidationResults ( results ) {
192
- if ( typeof results !== 'undefined' ) {
193
- results . forEach ( error => {
194
- console . error ( chalk . red ( ` * ${ error } ` ) ) ;
195
- } ) ;
196
- }
197
- }
198
-
199
187
createApp (
200
188
projectName ,
201
189
program . verbose ,
@@ -243,6 +231,7 @@ function createApp(
243
231
if ( ! isSafeToCreateProjectIn ( root , name ) ) {
244
232
process . exit ( 1 ) ;
245
233
}
234
+ console . log ( ) ;
246
235
247
236
console . log ( `Creating a new React app in ${ chalk . green ( root ) } .` ) ;
248
237
console . log ( ) ;
@@ -444,10 +433,7 @@ function run(
444
433
. then ( ( { isOnline, packageInfo, templateInfo } ) => {
445
434
let packageVersion = semver . coerce ( packageInfo . version ) ;
446
435
447
- // This environment variable can be removed post-release.
448
- const templatesVersionMinimum = process . env . CRA_INTERNAL_TEST
449
- ? '3.2.0'
450
- : '3.3.0' ;
436
+ const templatesVersionMinimum = '3.3.0' ;
451
437
452
438
// Assume compatibility if we can't test the version.
453
439
if ( ! semver . valid ( packageVersion ) ) {
@@ -587,7 +573,7 @@ function getInstallPackage(version, originalDirectory) {
587
573
if ( validSemver ) {
588
574
packageToInstall += `@${ validSemver } ` ;
589
575
} else if ( version ) {
590
- if ( version [ 0 ] === '@' && version . indexOf ( '/' ) === - 1 ) {
576
+ if ( version [ 0 ] === '@' && ! version . includes ( '/' ) ) {
591
577
packageToInstall += version ;
592
578
} else if ( version . match ( / ^ f i l e : / ) ) {
593
579
packageToInstall = `file:${ path . resolve (
@@ -654,10 +640,25 @@ function getTemplateInstallPackage(template, originalDirectory) {
654
640
const scope = packageMatch [ 1 ] || '' ;
655
641
const templateName = packageMatch [ 2 ] ;
656
642
657
- const name = templateName . startsWith ( templateToInstall )
658
- ? templateName
659
- : `${ templateToInstall } -${ templateName } ` ;
660
- templateToInstall = `${ scope } ${ name } ` ;
643
+ if (
644
+ templateName === templateToInstall ||
645
+ templateName . startsWith ( `${ templateToInstall } -` )
646
+ ) {
647
+ // Covers:
648
+ // - cra-template
649
+ // - @SCOPE/cra-template
650
+ // - cra-template-NAME
651
+ // - @SCOPE/cra-template-NAME
652
+ templateToInstall = `${ scope } ${ templateName } ` ;
653
+ } else if ( templateName . startsWith ( '@' ) ) {
654
+ // Covers using @SCOPE only
655
+ templateToInstall = `${ templateName } /${ templateToInstall } ` ;
656
+ } else {
657
+ // Covers templates without the `cra-template` prefix:
658
+ // - NAME
659
+ // - @SCOPE/NAME
660
+ templateToInstall = `${ scope } ${ templateToInstall } -${ templateName } ` ;
661
+ }
661
662
}
662
663
}
663
664
@@ -739,7 +740,7 @@ function getPackageInfo(installPackage) {
739
740
) ;
740
741
return Promise . resolve ( { name : assumedProjectName } ) ;
741
742
} ) ;
742
- } else if ( installPackage . indexOf ( 'git+' ) === 0 ) {
743
+ } else if ( installPackage . startsWith ( 'git+' ) ) {
743
744
// Pull package name out of git urls e.g:
744
745
// git+https://github.com/mycompany/react-scripts.git
745
746
// git+ssh://github.com/mycompany/react-scripts.git#v1.2.3
@@ -781,17 +782,25 @@ function checkNpmVersion() {
781
782
}
782
783
783
784
function checkYarnVersion ( ) {
785
+ const minYarnPnp = '1.12.0' ;
784
786
let hasMinYarnPnp = false ;
785
787
let yarnVersion = null ;
786
788
try {
787
789
yarnVersion = execSync ( 'yarnpkg --version' )
788
790
. toString ( )
789
791
. trim ( ) ;
790
- let trimmedYarnVersion = / ^ ( .+ ?) [ - + ] .+ $ / . exec ( yarnVersion ) ;
791
- if ( trimmedYarnVersion ) {
792
- trimmedYarnVersion = trimmedYarnVersion . pop ( ) ;
792
+ if ( semver . valid ( yarnVersion ) ) {
793
+ hasMinYarnPnp = semver . gte ( yarnVersion , minYarnPnp ) ;
794
+ } else {
795
+ // Handle non-semver compliant yarn version strings, which yarn currently
796
+ // uses for nightly builds. The regex truncates anything after the first
797
+ // dash. See #5362.
798
+ const trimmedYarnVersionMatch = / ^ ( .+ ?) [ - + ] .+ $ / . exec ( yarnVersion ) ;
799
+ if ( trimmedYarnVersionMatch ) {
800
+ const trimmedYarnVersion = trimmedYarnVersionMatch . pop ( ) ;
801
+ hasMinYarnPnp = semver . gte ( trimmedYarnVersion , minYarnPnp ) ;
802
+ }
793
803
}
794
- hasMinYarnPnp = semver . gte ( trimmedYarnVersion || yarnVersion , '1.12.0' ) ;
795
804
} catch ( err ) {
796
805
// ignore
797
806
}
@@ -836,22 +845,29 @@ function checkAppName(appName) {
836
845
const validationResult = validateProjectName ( appName ) ;
837
846
if ( ! validationResult . validForNewPackages ) {
838
847
console . error (
839
- `Could not create a project called ${ chalk . red (
840
- `"${ appName } "`
841
- ) } because of npm naming restrictions:`
848
+ chalk . red (
849
+ `Cannot create a project named ${ chalk . green (
850
+ `"${ appName } "`
851
+ ) } because of npm naming restrictions:\n`
852
+ )
842
853
) ;
843
- printValidationResults ( validationResult . errors ) ;
844
- printValidationResults ( validationResult . warnings ) ;
854
+ [
855
+ ...( validationResult . errors || [ ] ) ,
856
+ ...( validationResult . warnings || [ ] ) ,
857
+ ] . forEach ( error => {
858
+ console . error ( chalk . red ( ` * ${ error } ` ) ) ;
859
+ } ) ;
860
+ console . error ( chalk . red ( '\nPlease choose a different project name.' ) ) ;
845
861
process . exit ( 1 ) ;
846
862
}
847
863
848
864
// TODO: there should be a single place that holds the dependencies
849
865
const dependencies = [ 'react' , 'react-dom' , 'react-scripts' ] . sort ( ) ;
850
- if ( dependencies . indexOf ( appName ) >= 0 ) {
866
+ if ( dependencies . includes ( appName ) ) {
851
867
console . error (
852
868
chalk . red (
853
- `We cannot create a project called ${ chalk . green (
854
- appName
869
+ `Cannot create a project named ${ chalk . green (
870
+ `" ${ appName } "`
855
871
) } because a dependency with the same name exists.\n` +
856
872
`Due to the way npm works, the following names are not allowed:\n\n`
857
873
) +
@@ -913,41 +929,57 @@ function setCaretRangeForRuntimeDeps(packageName) {
913
929
function isSafeToCreateProjectIn ( root , name ) {
914
930
const validFiles = [
915
931
'.DS_Store' ,
916
- 'Thumbs.db' ,
917
932
'.git' ,
933
+ '.gitattributes' ,
918
934
'.gitignore' ,
919
- '.idea' ,
920
- 'README.md' ,
921
- 'LICENSE' ,
935
+ '.gitlab-ci.yml' ,
922
936
'.hg' ,
923
- '.hgignore' ,
924
937
'.hgcheck' ,
938
+ '.hgignore' ,
939
+ '.idea' ,
925
940
'.npmignore' ,
926
- 'mkdocs.yml' ,
927
- 'docs' ,
928
941
'.travis.yml' ,
929
- '.gitlab-ci.yml' ,
930
- '.gitattributes' ,
942
+ 'docs' ,
943
+ 'LICENSE' ,
944
+ 'README.md' ,
945
+ 'mkdocs.yml' ,
946
+ 'Thumbs.db' ,
931
947
] ;
932
- console . log ( ) ;
948
+ // These files should be allowed to remain on a failed install, but then
949
+ // silently removed during the next create.
950
+ const errorLogFilePatterns = [
951
+ 'npm-debug.log' ,
952
+ 'yarn-error.log' ,
953
+ 'yarn-debug.log' ,
954
+ ] ;
955
+ const isErrorLog = file => {
956
+ return errorLogFilePatterns . some ( pattern => file . startsWith ( pattern ) ) ;
957
+ } ;
933
958
934
959
const conflicts = fs
935
960
. readdirSync ( root )
936
961
. filter ( file => ! validFiles . includes ( file ) )
937
962
// IntelliJ IDEA creates module files before CRA is launched
938
963
. filter ( file => ! / \. i m l $ / . test ( file ) )
939
964
// Don't treat log files from previous installation as conflicts
940
- . filter (
941
- file => ! errorLogFilePatterns . some ( pattern => file . indexOf ( pattern ) === 0 )
942
- ) ;
965
+ . filter ( file => ! isErrorLog ( file ) ) ;
943
966
944
967
if ( conflicts . length > 0 ) {
945
968
console . log (
946
969
`The directory ${ chalk . green ( name ) } contains files that could conflict:`
947
970
) ;
948
971
console . log ( ) ;
949
972
for ( const file of conflicts ) {
950
- console . log ( ` ${ file } ` ) ;
973
+ try {
974
+ const stats = fs . lstatSync ( path . join ( root , file ) ) ;
975
+ if ( stats . isDirectory ( ) ) {
976
+ console . log ( ` ${ chalk . blue ( `${ file } /` ) } ` ) ;
977
+ } else {
978
+ console . log ( ` ${ file } ` ) ;
979
+ }
980
+ } catch ( e ) {
981
+ console . log ( ` ${ file } ` ) ;
982
+ }
951
983
}
952
984
console . log ( ) ;
953
985
console . log (
@@ -957,15 +989,11 @@ function isSafeToCreateProjectIn(root, name) {
957
989
return false ;
958
990
}
959
991
960
- // Remove any remnant files from a previous installation
961
- const currentFiles = fs . readdirSync ( path . join ( root ) ) ;
962
- currentFiles . forEach ( file => {
963
- errorLogFilePatterns . forEach ( errorLogFilePattern => {
964
- // This will catch `(npm-debug|yarn-error|yarn-debug).log*` files
965
- if ( file . indexOf ( errorLogFilePattern ) === 0 ) {
966
- fs . removeSync ( path . join ( root , file ) ) ;
967
- }
968
- } ) ;
992
+ // Remove any log files from a previous installation.
993
+ fs . readdirSync ( root ) . forEach ( file => {
994
+ if ( isErrorLog ( file ) ) {
995
+ fs . removeSync ( path . join ( root , file ) ) ;
996
+ }
969
997
} ) ;
970
998
return true ;
971
999
}
@@ -985,6 +1013,8 @@ function getProxy() {
985
1013
}
986
1014
}
987
1015
}
1016
+
1017
+ // See https://github.com/facebook/create-react-app/pull/3355
988
1018
function checkThatNpmCanReadCwd ( ) {
989
1019
const cwd = process . cwd ( ) ;
990
1020
let childOutput = null ;
@@ -1009,7 +1039,7 @@ function checkThatNpmCanReadCwd() {
1009
1039
// "; cwd = C:\path\to\current\dir" (unquoted)
1010
1040
// I couldn't find an easier way to get it.
1011
1041
const prefix = '; cwd = ' ;
1012
- const line = lines . find ( line => line . indexOf ( prefix ) === 0 ) ;
1042
+ const line = lines . find ( line => line . startsWith ( prefix ) ) ;
1013
1043
if ( typeof line !== 'string' ) {
1014
1044
// Fail gracefully. They could remove it.
1015
1045
return true ;
0 commit comments