Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure that PbxGroups are not duplicated #17

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ node_modules/*
.DS_Store
npm-debug.log
package-lock.json

.ns-build-pbxgroup-data.json
*.tgz
52 changes: 52 additions & 0 deletions lib/guidMapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const fs = require('fs');
const path = require('path');

function guidMapper(filePath) {
this.filePath = filePath;
this.data = this.loadFromFile();
}

guidMapper.prototype.loadFromFile = function () {
try {
const rawData = fs.readFileSync(this.filePath, 'utf8');
return JSON.parse(rawData);
} catch (error) {
// If file doesn't exist or there's an error parsing it, initialize with an empty object.
return {};
}
};

guidMapper.prototype.writeFileSync = function () {
const jsonData = JSON.stringify(this.data, null, 2);
fs.writeFileSync(this.filePath, jsonData, 'utf8');
};

guidMapper.prototype.addEntry = function (guid, path, name) {
if(!!guid && !! path && !!name){
this.data[guid] = { path: path, name: name };
}
};

guidMapper.prototype.removeEntry = function (guid) {
if (this.data[guid]) {
delete this.data[guid];
}
};

guidMapper.prototype.getEntries = function () {
return this.data;
};

guidMapper.prototype.findEntryGuid = function (name, path) {
for (const guid in this.data) {
if (this.data.hasOwnProperty(guid)) {
const entry = this.data[guid];
if (entry.path === path && entry.name === name) {
return guid;
}
}
}
return null;
};

module.exports = guidMapper;
27 changes: 26 additions & 1 deletion lib/pbxProject.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ var util = require('util'),
isEntitlementFileType = constants.isEntitlementFileType,
isAssetFileType = constants.isAssetFileType,
isPlistFileType = constants.isPlistFileType,
isModuleMapFileType = constants.isModuleMapFileType;
isModuleMapFileType = constants.isModuleMapFileType,
guidMapper = require('./guidMapper');

function pbxProject(filename) {
if (!(this instanceof pbxProject))
Expand Down Expand Up @@ -74,6 +75,10 @@ pbxProject.prototype.parseSync = function() {
}

pbxProject.prototype.writeSync = function(options) {
if(this.pbxGroupTracker){
this.pbxGroupTracker.writeFileSync();
}

this.writer = new pbxWriter(this.hash, options);
return this.writer.writeSync();
}
Expand Down Expand Up @@ -538,10 +543,27 @@ pbxProject.prototype.findMainPbxGroup = function () {

return null;
}
pbxProject.prototype.getPbxGroupTracker = function (path) {

if(!this.pbxGroupTracker){
this.pbxGroupTracker = new guidMapper($path.join(path, '.ns-build-pbxgroup-data.json'));
}

return this.pbxGroupTracker;
}

pbxProject.prototype.addPbxGroup = function (filePathsArray, name, path, sourceTree, opt) {
opt = opt || {};
var srcRootPath = $path.dirname($path.dirname(this.filepath));

var existingGroupId = this.getPbxGroupTracker(srcRootPath).findEntryGuid(name, path);
if(existingGroupId){
if(this.getPBXGroupByKey(existingGroupId)){
this.removePbxGroupByKey(existingGroupId, path);
}
this.pbxGroupTracker.removeEntry(existingGroupId);
}

var groups = this.hash.project.objects['PBXGroup'],
pbxGroupUuid = opt.uuid || this.generateUuid(),
commentKey = f("%s_comment", pbxGroupUuid),
Expand All @@ -560,6 +582,9 @@ pbxProject.prototype.addPbxGroup = function (filePathsArray, name, path, sourceT
pbxGroup.path = path;
}

// save to group to the tracker
this.pbxGroupTracker.addEntry(pbxGroupUuid, path, name);

for (var key in fileReferenceSection) {
// only look for comments
if (!COMMENT_KEY.test(key)) continue;
Expand Down
69 changes: 69 additions & 0 deletions test/guidMapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
var guidMapper = require('../lib/guidMapper');
const fs = require('fs');
const $uuid = require('uuid');
const TEST_FILE_NAME = 'test/.ns-build-pbxgroup-data.json';
const goodGUID = $uuid.v4();
const goodName = "goodName";
const badName = 'badName';
const goodPath = "goodPath";
const badPath = "badPath";
exports.setUp = function(callback) {
if(fs.existsSync(TEST_FILE_NAME)){
fs.rmSync(TEST_FILE_NAME);
}
callback();
}
exports.tearDown = function(callback) {
if(fs.existsSync(TEST_FILE_NAME)){
fs.rmSync(TEST_FILE_NAME);
}
callback();
}
function addTestData(){
var mapper = new guidMapper(TEST_FILE_NAME);
mapper.addEntry(goodGUID, goodPath, goodName);
mapper.writeFileSync();
}
exports.operations = {
'should be able to add to map': function(test) {
var mapper = new guidMapper(TEST_FILE_NAME);
mapper.addEntry(goodGUID, goodPath, goodName);
mapper.writeFileSync();
mapper = new guidMapper(TEST_FILE_NAME);
const result = mapper.findEntryGuid(goodName, goodPath);

test.ok(result === goodGUID)
test.done();
},
'should not match only on name': function(test) {
addTestData();
var mapper = new guidMapper(TEST_FILE_NAME);

const result = mapper.findEntryGuid(goodName, badPath);

test.ok(result === null)
test.done();
},
'should not match only on path': function(test) {
addTestData();
var mapper = new guidMapper(TEST_FILE_NAME);

const result = mapper.findEntryGuid(badName, goodPath);

test.ok(result === null)
test.done();
},
'can remove': function(test) {
addTestData();
var mapper = new guidMapper(TEST_FILE_NAME);
mapper.removeEntry(goodGUID);
var result = mapper.findEntryGuid(goodName, goodPath);

test.ok(result === null);
mapper.writeFileSync();
result = mapper.findEntryGuid(goodName, goodPath);
test.ok(result === null)

test.done();
}
}
17 changes: 17 additions & 0 deletions test/pbxProject.js
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,20 @@ exports['addToPbxFileReferenceSection'] = {
}
}


exports['addPbxGroup'] = {
'should not add the same group twice': function (test) {
var newProj = new pbx('test/parser/projects/group.pbxproj');
newProj.parse(function (err, hash) {
this.hash.project.objects['PBXVariantGroup']={};
var group1 = newProj.addPbxGroup(['test/somefile'], "TestGroup", "test/somepath", null, null);
var group2 = newProj.addPbxGroup(['test/somefile'], "TestGroup", "test/somepath", null, null);
test.equal(newProj.getPBXGroupByKey(group1.uuid), null);
test.equal(newProj.getPBXGroupByKey(group2.uuid).name, "TestGroup");
test.equal(newProj.getPbxGroupTracker().getEntries().hasOwnProperty(group1.uuid), false);
test.equal(newProj.getPbxGroupTracker().getEntries().hasOwnProperty(group2.uuid), true);

test.done();
});
}
}