1818var util = require ( 'util' ) ,
1919 f = util . format ,
2020 EventEmitter = require ( 'events' ) . EventEmitter ,
21- path = require ( 'path' ) ,
21+ $ path = require ( 'path' ) ,
2222 uuid = require ( 'uuid' ) ,
2323 fork = require ( 'child_process' ) . fork ,
2424 pbxWriter = require ( './pbxWriter' ) ,
25- pbxFile = require ( './pbxFile' ) ,
25+ pbxFile = require ( './pbxFile' ) . pbxFile ,
26+ pbxFileTypes = require ( './pbxFile' ) . fileTypes ,
2627 fs = require ( 'fs' ) ,
2728 parser = require ( './parser/pbxproj' ) ,
2829 plist = require ( 'simple-plist' ) ,
2930 COMMENT_KEY = / _ c o m m e n t $ / ,
30- NO_SPECIAL_SYMBOLS = / ^ [ a - z A - Z 0 - 9 _ \. \$ ] + \. [ a - z A - Z ] + $ / ;
31+ NO_SPECIAL_SYMBOLS = / ^ [ a - z A - Z 0 - 9 _ \. \$ ] + \. [ a - z A - Z ] + $ / ,
32+ HEADER_FILE_TYPE_SUFFIX = ".h" ,
33+ SOURCE_CODE_FILE_TYPE_PREFIX = "sourcecode." ;
3134
3235function pbxProject ( filename ) {
3336 if ( ! ( this instanceof pbxProject ) )
3437 return new pbxProject ( filename ) ;
3538
36- this . filepath = path . resolve ( filename )
39+ this . filepath = $ path. resolve ( filename )
3740}
3841
3942util . inherits ( pbxProject , EventEmitter )
@@ -492,17 +495,37 @@ pbxProject.prototype.removeFromPbxBuildFileSection = function(file) {
492495 }
493496}
494497
495- pbxProject . prototype . addPbxGroup = function ( filePathsArray , name , path , sourceTree ) {
498+ pbxProject . prototype . findMainPbxGroup = function ( ) {
499+ var groups = this . hash . project . objects [ 'PBXGroup' ] ;
500+ var candidates = [ ] ;
501+ for ( var key in groups ) {
502+ if ( ! groups [ key ] . path && ! groups [ key ] . name && groups [ key ] . isa ) {
503+ candidates . push ( groups [ key ] ) ;
504+ }
505+ }
506+ if ( candidates . length == 1 ) {
507+ return candidates [ 0 ] ;
508+ }
509+
510+ return null ;
511+ }
512+
513+ pbxProject . prototype . addPbxGroup = function ( filePathsArray , name , path , sourceTree , opt ) {
514+
515+ var oldGroup = this . pbxGroupByName ( name ) ;
516+ if ( oldGroup ) {
517+ this . removePbxGroup ( name , path ) ;
518+ }
519+
496520 var groups = this . hash . project . objects [ 'PBXGroup' ] ,
497- pbxGroupUuid = this . generateUuid ( ) ,
521+ pbxGroupUuid = opt . uuid || this . generateUuid ( ) ,
498522 commentKey = f ( "%s_comment" , pbxGroupUuid ) ,
499523 pbxGroup = {
500524 isa : 'PBXGroup' ,
501525 children : [ ] ,
502526 name : name ,
503- path : path ,
504527 sourceTree : sourceTree ? sourceTree : '"<group>"'
505- } ,
528+ } , //path is mandatory only for the main group
506529 fileReferenceSection = this . pbxFileReferenceSection ( ) ,
507530 filePathToReference = { } ;
508531
@@ -527,23 +550,64 @@ pbxProject.prototype.addPbxGroup = function(filePathsArray, name, path, sourceTr
527550 continue ;
528551 }
529552
530- var file = new pbxFile ( filePath ) ;
531- file . uuid = this . generateUuid ( ) ;
532- file . fileRef = this . generateUuid ( ) ;
533- this . addToPbxFileReferenceSection ( file ) ; // PBXFileReference
534- this . addToPbxBuildFileSection ( file ) ; // PBXBuildFile
535- pbxGroup . children . push ( pbxGroupChild ( file ) ) ;
553+ var srcRootPath = $path . dirname ( $path . dirname ( this . filepath ) ) ;
554+ var file = new pbxFile ( $path . relative ( srcRootPath , filePath ) ) ;
555+ if ( fs . lstatSync ( filePath ) . isDirectory ( ) ) {
556+ file . uuid = this . generateUuid ( ) ;
557+ file . fileRef = file . uuid ;
558+ this . addToPbxFileReferenceSection ( file ) ; // PBXFileReference
559+ this . addToPbxBuildFileSection ( file ) ;
560+ pbxGroup . children . push ( pbxGroupChild ( file ) ) ;
561+ var files = fs . readdirSync ( filePath ) . map ( p => $path . join ( filePath , p ) ) ;
562+ this . addPbxGroup ( files , $path . basename ( filePath ) , filePath , null , { uuid : file . uuid } ) ;
563+ } else if ( file . lastType . startsWith ( SOURCE_CODE_FILE_TYPE_PREFIX ) ) {
564+ file . uuid = this . generateUuid ( ) ;
565+ file . fileRef = this . generateUuid ( ) ;
566+ this . addToPbxFileReferenceSection ( file ) ; // PBXFileReference
567+ this . addToPbxBuildFileSection ( file ) ; // PBXBuildFile
568+ if ( ! file . lastType . endsWith ( HEADER_FILE_TYPE_SUFFIX ) ) {
569+ this . addToPbxSourcesBuildPhase ( file ) ;
570+ }
571+ pbxGroup . children . push ( pbxGroupChild ( file ) ) ;
572+ }
573+
536574 }
537575
538576 if ( groups ) {
539577 groups [ pbxGroupUuid ] = pbxGroup ;
540578 groups [ commentKey ] = name ;
541579 }
542580
543- return { uuid : pbxGroupUuid , pbxGroup : pbxGroup } ;
581+ if ( opt . isMain ) {
582+ let mainGroup = this . findMainPbxGroup ( ) ;
583+ if ( mainGroup ) {
584+ var file = new pbxFile ( $path . relative ( this . filepath , path ) ) ;
585+ file . fileRef = pbxGroupUuid ;
586+ mainGroup . children . push ( pbxGroupChild ( file ) ) ;
587+ }
588+ }
589+
590+ return { uuid : pbxGroupUuid , pbxGroup : pbxGroup } ;
544591}
545592
546- pbxProject . prototype . removePbxGroup = function ( groupName ) {
593+ pbxProject . prototype . removePbxGroup = function ( groupName , path ) {
594+ var group = this . pbxGroupByName ( groupName ) ;
595+ if ( ! group ) {
596+ return ;
597+ }
598+
599+ var children = group . children ;
600+
601+ for ( i in children ) {
602+ var file = new pbxFile ( $path . join ( path , children [ i ] . comment ) ) ;
603+ file . fileRef = children [ i ] . value ;
604+ file . uuid = file . fileRef ;
605+ this . removePbxGroup ( children [ i ] . comment , $path . join ( path , children [ i ] . comment ) ) ;
606+ this . removeFromPbxFileReferenceSection ( file ) ;
607+ this . removeFromPbxBuildFileSection ( file ) ;
608+ this . removeFromPbxSourcesBuildPhase ( file ) ;
609+ }
610+
547611 var section = this . hash . project . objects [ 'PBXGroup' ] ,
548612 key , itemKey ;
549613
@@ -616,12 +680,12 @@ pbxProject.prototype.addToXcVersionGroupSection = function(file) {
616680 isa : 'XCVersionGroup' ,
617681 children : file . models . map ( function ( el ) { return el . fileRef ; } ) ,
618682 currentVersion : file . currentModel . fileRef ,
619- name : path . basename ( file . path ) ,
683+ name : $ path. basename ( file . path ) ,
620684 path : file . path ,
621685 sourceTree : '"<group>"' ,
622686 versionGroupType : 'wrapper.xcdatamodel'
623687 } ;
624- this . xcVersionGroupSection ( ) [ commentKey ] = path . basename ( file . path ) ;
688+ this . xcVersionGroupSection ( ) [ commentKey ] = $ path. basename ( file . path ) ;
625689 }
626690}
627691
@@ -1416,7 +1480,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
14161480 isa : 'XCBuildConfiguration' ,
14171481 buildSettings : {
14181482 GCC_PREPROCESSOR_DEFINITIONS : [ '"DEBUG=1"' , '"$(inherited)"' ] ,
1419- INFOPLIST_FILE : '"' + path . join ( targetSubfolder , targetSubfolder + '-Info.plist' + '"' ) ,
1483+ INFOPLIST_FILE : '"' + $ path. join ( targetSubfolder , targetSubfolder + '-Info.plist' + '"' ) ,
14201484 LD_RUNPATH_SEARCH_PATHS : '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"' ,
14211485 PRODUCT_NAME : '"' + targetName + '"' ,
14221486 SKIP_INSTALL : 'YES'
@@ -1426,7 +1490,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) {
14261490 name : 'Release' ,
14271491 isa : 'XCBuildConfiguration' ,
14281492 buildSettings : {
1429- INFOPLIST_FILE : '"' + path . join ( targetSubfolder , targetSubfolder + '-Info.plist' + '"' ) ,
1493+ INFOPLIST_FILE : '"' + $ path. join ( targetSubfolder , targetSubfolder + '-Info.plist' + '"' ) ,
14301494 LD_RUNPATH_SEARCH_PATHS : '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"' ,
14311495 PRODUCT_NAME : '"' + targetName + '"' ,
14321496 SKIP_INSTALL : 'YES'
@@ -1616,7 +1680,7 @@ function pbxBuildFileComment(file) {
16161680}
16171681
16181682function pbxFileReferenceComment ( file ) {
1619- return file . basename || path . basename ( file . path ) ;
1683+ return file . basename || $ path. basename ( file . path ) ;
16201684}
16211685
16221686function pbxNativeTargetComment ( target ) {
@@ -1656,7 +1720,7 @@ function searchPathForFile(file, proj) {
16561720
16571721 var plugins = proj . pbxGroupByName ( 'Plugins' ) ,
16581722 pluginsPath = plugins ? plugins . path : null ,
1659- fileDir = path . dirname ( file . path ) ;
1723+ fileDir = $ path. dirname ( file . path ) ;
16601724
16611725 if ( fileDir == '.' ) {
16621726 fileDir = '' ;
@@ -2071,7 +2135,7 @@ pbxProject.prototype.addDataModelDocument = function(filePath, group, opt) {
20712135 var modelFiles = fs . readdirSync ( file . path ) ;
20722136 for ( var index in modelFiles ) {
20732137 var modelFileName = modelFiles [ index ] ;
2074- var modelFilePath = path . join ( filePath , modelFileName ) ;
2138+ var modelFilePath = $ path. join ( filePath , modelFileName ) ;
20752139
20762140 if ( modelFileName == '.xccurrentversion' ) {
20772141 currentVersionName = plist . readFileSync ( modelFilePath ) . _XCCurrentVersionName ;
0 commit comments