Skip to content

Commit a56960f

Browse files
committed
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 5c9c2c6 commit a56960f

File tree

1 file changed

+102
-21
lines changed

1 file changed

+102
-21
lines changed

lib/pbxProject.js

+102-21
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
var util = require('util'),
22
f = util.format,
33
EventEmitter = require('events').EventEmitter,
4-
path = require('path'),
4+
$path = require('path'),
55
uuid = require('node-uuid'),
66
fork = require('child_process').fork,
77
pbxWriter = require('./pbxWriter'),
8-
pbxFile = require('./pbxFile'),
8+
pbxFile = require('./pbxFile').pbxFile,
9+
pbxFileTypes = require('./pbxFile').fileTypes,
910
fs = require('fs'),
1011
parser = require('./parser/pbxproj'),
1112
COMMENT_KEY = /_comment$/,
12-
NO_SPECIAL_SYMBOLS = /^[a-zA-Z0-9_\.\$]+\.[a-zA-Z]+$/;
13+
NO_SPECIAL_SYMBOLS = /^[a-zA-Z0-9_\.\$]+\.[a-zA-Z]+$/,
14+
HEADER_FILE_TYPE_SUFFIX = ".h",
15+
SOURCE_CODE_FILE_TYPE_PREFIX = "sourcecode.";
1316

1417
function pbxProject(filename) {
1518
if (!(this instanceof pbxProject))
1619
return new pbxProject(filename);
1720

18-
this.filepath = path.resolve(filename)
21+
this.filepath = $path.resolve(filename)
1922
}
2023

2124
util.inherits(pbxProject, EventEmitter)
@@ -286,31 +289,52 @@ pbxProject.prototype.removeFromPbxBuildFileSection = function (file) {
286289
}
287290
}
288291

289-
pbxProject.prototype.addPbxGroup = function (filePathsArray, name, path, sourceTree) {
292+
pbxProject.prototype.findMainPbxGroup = function () {
293+
var groups = this.hash.project.objects['PBXGroup'];
294+
var candidates = [];
295+
for (var key in groups) {
296+
if (!groups[key].path && !groups[key].name && groups[key].isa) {
297+
candidates.push(groups[key]);
298+
}
299+
}
300+
if (candidates.length == 1) {
301+
return candidates[0];
302+
}
303+
304+
return null;
305+
}
306+
307+
pbxProject.prototype.addPbxGroup = function (filePathsArray, name, path, sourceTree, opt) {
308+
309+
var oldGroup = this.pbxGroupByName(name);
310+
if (oldGroup) {
311+
this.removePbxGroup(name, path);
312+
}
313+
290314
var groups = this.hash.project.objects['PBXGroup'],
291-
pbxGroupUuid = this.generateUuid(),
315+
pbxGroupUuid = opt.uuid || this.generateUuid(),
292316
commentKey = f("%s_comment", pbxGroupUuid),
293317
pbxGroup = {
294318
isa: 'PBXGroup',
295319
children: [],
296320
name: name,
297-
path: path,
298321
sourceTree: sourceTree ? sourceTree : '"<group>"'
299-
},
322+
},//path is mandatory only for the main group
300323
fileReferenceSection = this.pbxFileReferenceSection(),
301324
filePathToReference = {};
302-
325+
303326
for (var key in fileReferenceSection) {
304327
// only look for comments
305328
if (!COMMENT_KEY.test(key)) continue;
306-
329+
307330
var fileReferenceKey = key.split(COMMENT_KEY)[0],
308331
fileReference = fileReferenceSection[fileReferenceKey];
309-
332+
310333
filePathToReference[fileReference.path] = {fileRef: fileReferenceKey, basename: fileReferenceSection[key]};
311334
}
312335

313336
for (var index = 0; index < filePathsArray.length; index++) {
337+
314338
var filePath = filePathsArray[index],
315339
filePathQuoted = "\"" + filePath + "\"";
316340
if (filePathToReference[filePath]) {
@@ -320,23 +344,80 @@ pbxProject.prototype.addPbxGroup = function (filePathsArray, name, path, sourceT
320344
pbxGroup.children.push(pbxGroupChild(filePathToReference[filePathQuoted]));
321345
continue;
322346
}
323-
324-
var file = new pbxFile(filePath);
325-
file.uuid = this.generateUuid();
326-
file.fileRef = this.generateUuid();
327-
this.addToPbxFileReferenceSection(file); // PBXFileReference
328-
this.addToPbxBuildFileSection(file); // PBXBuildFile
329-
pbxGroup.children.push(pbxGroupChild(file));
347+
348+
var srcRootPath = $path.dirname($path.dirname(this.filepath));
349+
var file = new pbxFile($path.relative(srcRootPath, filePath));
350+
if (fs.lstatSync(filePath).isDirectory()) {
351+
file.uuid = this.generateUuid();
352+
file.fileRef = file.uuid;
353+
this.addToPbxFileReferenceSection(file); // PBXFileReference
354+
this.addToPbxBuildFileSection(file);
355+
pbxGroup.children.push(pbxGroupChild(file));
356+
var files = fs.readdirSync(filePath).map(p => $path.join(filePath, p));
357+
this.addPbxGroup(files, $path.basename(filePath), filePath, null, {uuid: file.uuid});
358+
}else if (file.lastType.startsWith(SOURCE_CODE_FILE_TYPE_PREFIX)) {
359+
file.uuid = this.generateUuid();
360+
file.fileRef = this.generateUuid();
361+
this.addToPbxFileReferenceSection(file); // PBXFileReference
362+
this.addToPbxBuildFileSection(file); // PBXBuildFile
363+
if (!file.lastType.endsWith(HEADER_FILE_TYPE_SUFFIX)) {
364+
this.addToPbxSourcesBuildPhase(file);
365+
}
366+
pbxGroup.children.push(pbxGroupChild(file));
367+
}
368+
330369
}
331-
370+
332371
if (groups) {
333372
groups[pbxGroupUuid] = pbxGroup;
334373
groups[commentKey] = name;
335374
}
336-
375+
376+
if (opt.isMain) {
377+
let mainGroup = this.findMainPbxGroup();
378+
if (mainGroup) {
379+
var file = new pbxFile($path.relative(this.filepath, path));
380+
file.fileRef = pbxGroupUuid;
381+
mainGroup.children.push(pbxGroupChild(file));
382+
}
383+
}
384+
337385
return {uuid: pbxGroupUuid, pbxGroup: pbxGroup};
338386
}
339387

388+
pbxProject.prototype.removePbxGroup = function(name, path) {
389+
var group = this.pbxGroupByName(name);
390+
if (!group) {
391+
return;
392+
}
393+
394+
var children = group.children;
395+
396+
for(i in children) {
397+
var file = new pbxFile($path.join(path, children[i].comment));
398+
file.fileRef = children[i].value;
399+
file.uuid = file.fileRef;
400+
this.removePbxGroup(children[i].comment, $path.join(path, children[i].comment));
401+
this.removeFromPbxFileReferenceSection(file);
402+
this.removeFromPbxBuildFileSection(file);
403+
this.removeFromPbxSourcesBuildPhase(file);
404+
}
405+
406+
//copied from https://github.com/alunny/node-xcode/blob/master/lib/pbxProject.js#L527
407+
var section = this.hash.project.objects['PBXGroup'],
408+
key, itemKey;
409+
410+
for (key in section) {
411+
// only look for comments
412+
if (!COMMENT_KEY.test(key)) continue;
413+
414+
if (section[key] == name) {
415+
itemKey = key.split(COMMENT_KEY)[0];
416+
delete section[itemKey];
417+
}
418+
}
419+
}
420+
340421
pbxProject.prototype.addToPbxFileReferenceSection = function (file) {
341422
var commentKey = f("%s_comment", file.fileRef);
342423

@@ -1048,7 +1129,7 @@ function searchPathForFile(file, proj) {
10481129

10491130
var plugins = proj.pbxGroupByName('Plugins'),
10501131
pluginsPath = plugins ? plugins.path : null,
1051-
fileDir = path.dirname(file.path);
1132+
fileDir = $path.dirname(file.path);
10521133

10531134
if (fileDir == '.') {
10541135
fileDir = '';

0 commit comments

Comments
 (0)