feat: add cleanup so that the script is idempotent

This commit is contained in:
Riccardo Cipolleschi
2025-09-09 15:15:07 +01:00
parent bbfb22cd23
commit 51f5cbb4fc
@@ -30,6 +30,80 @@ function convertXcodeProjectToJSON(projectPath) {
return JSON.parse(jsonOutput);
}
/**
* Remove all existing SwiftPM package references and dependencies from Xcode project
* @param {Object} xcodeProject - The xcode project converted in JSON format
*/
function deintegrateSwiftPM(xcodeProject) {
const objects = xcodeProject.objects;
const objectsToRemove = [];
// Step 1: Find all PBXNativeTarget objects and clean up their SwiftPM dependencies
for (const objectId in objects) {
const object = objects[objectId];
if (object.isa === "PBXNativeTarget") {
// Find PBXFrameworksBuildPhase
for (const buildPhaseId of object.buildPhases || []) {
const buildPhaseObject = objects[buildPhaseId];
if (buildPhaseObject && buildPhaseObject.isa === "PBXFrameworksBuildPhase") {
const filesToRemove = [];
// Check each file in the build phase
for (const fileId of buildPhaseObject.files || []) {
const buildFileObject = objects[fileId];
if (buildFileObject && buildFileObject.isa === "PBXBuildFile" && buildFileObject.productRef) {
const productRefObject = objects[buildFileObject.productRef];
if (productRefObject && productRefObject.isa === "XCSwiftPackageProductDependency") {
// Mark for removal: the product dependency, the build file, and remove from files list
objectsToRemove.push(buildFileObject.productRef);
objectsToRemove.push(fileId);
filesToRemove.push(fileId);
}
}
}
// Remove files from the build phase
if (filesToRemove.length > 0) {
buildPhaseObject.files = (buildPhaseObject.files || []).filter(fileId => !filesToRemove.includes(fileId));
}
}
}
}
}
// Step 2: Find PBXProject and clean up packageReferences
for (const objectId in objects) {
const object = objects[objectId];
if (object.isa === "PBXProject") {
const packageReferencesToRemove = [];
// Check each package reference
for (const packageRefId of object.packageReferences || []) {
const packageRefObject = objects[packageRefId];
if (packageRefObject && packageRefObject.isa === "XCLocalSwiftPackageReference") {
// Mark for removal
objectsToRemove.push(packageRefId);
packageReferencesToRemove.push(packageRefId);
}
}
// Remove package references from the project
if (packageReferencesToRemove.length > 0) {
object.packageReferences = (object.packageReferences || []).filter(refId => !packageReferencesToRemove.includes(refId));
}
break;
}
}
// Step 3: Remove all marked objects
for (const objectId of objectsToRemove) {
delete objects[objectId];
}
console.log(`✓ Removed ${objectsToRemove.length} SwiftPM-related objects from Xcode project`);
}
/**
* Add local SwiftPM package references and product dependencies to Xcode project
* @param {string} relativePath - The relative path of where the Package.swift is located
@@ -116,6 +190,9 @@ function integrateSwiftPackagesInXcode(xcodeProjectPath, packageSwiftObjects, ap
// Convert to JSON
const xcodeProject = convertXcodeProjectToJSON(projectPbxprojPath);
// Remove any existing SwiftPM integrations first
deintegrateSwiftPM(xcodeProject);
// Iterate over PackageSwift objects and execute addLocalSwiftPM
for (const packageSwift of packageSwiftObjects) {
addLocalSwiftPM(
@@ -157,6 +234,7 @@ if (require.main === module) {
module.exports = {
generateXcodeObjectId,
convertXcodeProjectToJSON,
deintegrateSwiftPM,
addLocalSwiftPM,
integrateSwiftPackagesInXcode
};