Skip to content

Commit 73bb809

Browse files
tdermendjievKristian D. Dimitrov
authored andcommitted
feat: Implement adding and removing of pbx groups
*support for c++ files added *recursively add pbxGroup and its children *recursively remove pbxGroup and its children *make sure pbx group name is not duplicated on adding new group
1 parent 52fa3f1 commit 73bb809

File tree

1 file changed

+87
-23
lines changed

1 file changed

+87
-23
lines changed

lib/pbxProject.js

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,25 @@
1818
var 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 = /_comment$/,
30-
NO_SPECIAL_SYMBOLS = /^[a-zA-Z0-9_\.\$]+\.[a-zA-Z]+$/;
31+
NO_SPECIAL_SYMBOLS = /^[a-zA-Z0-9_\.\$]+\.[a-zA-Z]+$/,
32+
HEADER_FILE_TYPE_SUFFIX = ".h",
33+
SOURCE_CODE_FILE_TYPE_PREFIX = "sourcecode.";
3134

3235
function 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

3942
util.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

16181682
function pbxFileReferenceComment(file) {
1619-
return file.basename || path.basename(file.path);
1683+
return file.basename || $path.basename(file.path);
16201684
}
16211685

16221686
function 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

Comments
 (0)