const fs = require('fs') const log = require('npmlog') const path = require('path') const xcode = require('xcode') log.heading = 'react-native-branch' function addBranchConfigToXcodeProject() { const projectName = findXcodeProjectName() if (!projectName) { log.error('could not find an Xcode project') return } const xcodeprojPath = path.join('.', 'ios', projectName + '.xcodeproj') const projectPbxprojPath = path.join(xcodeprojPath, 'project.pbxproj') const project = xcode.project(projectPbxprojPath) project.parse(function(error) { if (error) { log.error('Error loading ' + xcodeprojPath) return } if (fs.existsSync(path.join('.', 'branch.ios.json'))) { includePathInProject(project, projectName, path.join('..', 'branch.ios.json')) } else if (fs.existsSync(path.join('.', 'branch.json'))) { includePathInProject(project, projectName, path.join('..', 'branch.json')) } if (fs.existsSync(path.join('.', 'branch.ios.debug.json'))) { includePathInProject(project, projectName, path.join('..', 'branch.ios.debug.json')) } else if (fs.existsSync(path.join('.', 'branch.debug.json'))) { includePathInProject(project, projectName, path.join('..', 'branch.debug.json')) } if (fs.writeFileSync(projectPbxprojPath, project.writeSync()) <= 0) { log.error('error writing updated project') return } log.info('Added Branch configuration to project ' + xcodeprojPath) }) } function removeBranchConfigFromXcodeProject() { const projectName = findXcodeProjectName() if (!projectName) { log.error('could not find an Xcode project') return } const xcodeprojPath = path.join('.', 'ios', projectName + '.xcodeproj') const projectPbxprojPath = path.join(xcodeprojPath, 'project.pbxproj') const project = xcode.project(projectPbxprojPath) project.parse(function(error) { if (error) { log.error('Error loading ' + xcodeprojPath) return } // paths relative to group removePathFromProject(project, projectName, path.join('..', 'branch.json')) removePathFromProject(project, projectName, path.join('..', 'branch.debug.json')) removePathFromProject(project, projectName, path.join('..', 'branch.ios.json')) removePathFromProject(project, projectName, path.join('..', 'branch.ios.debug.json')) if (fs.writeFileSync(projectPbxprojPath, project.writeSync()) <= 0) { log.error('error writing updated project') return } log.info('Removed Branch configuration from project ' + xcodeprojPath) }) } function includePathInProject(project, groupName, path) { const groupKey = getGroupKeyByName(project, groupName) if (!groupKey) { log.error('Could not find key for group ' + groupName) return } // path relative to group const file = project.addFile(path, groupKey) if (!file) { // TODO: Can get here if the file is already in the project log.error('Failed to add file to project') return } file.uuid = project.generateUuid() file.target = getTargetKeyByName(project, groupName) correctForPath(file, project, groupName) project.addToPbxBuildFileSection(file) project.addToPbxResourcesBuildPhase(file) } function removePathFromProject(project, groupName, path) { const file = project.removeFile(path, {}) if (!file) { log.warn('Did not find ' + path + ' in project') return } file.target = getTargetKeyByName(project, groupName) correctForPath(file, project, groupName) const groupKey = getGroupKeyByName(project, groupName) if (!groupKey) { log.error('Could not find key for group ' + groupName) return } project.removeFromPbxBuildFileSection(file) project.removeFromPbxResourcesBuildPhase(file) project.removeFromPbxGroup(file, groupKey) } function getGroupKeyByName(project, groupName) { const objects = project.hash.project.objects['PBXGroup'] for (const key in objects) { const name = objects[key].name if (name == groupName) return key } return null } function getTargetKeyByName(project, targetName) { const targets = project.pbxNativeTargetSection() for (const key in targets) { const name = targets[key].name if (name == targetName) return key } return null } function correctForPath(file, project, group) { const r_group_dir = new RegExp('^' + group + '[\\\\/]'); if (project.pbxGroupByName(group).path) file.path = file.path.replace(r_group_dir, ''); return file; } function findXcodeProjectName() { // look for a .xcodeproj directory under ios files = fs.readdirSync(path.join('.', 'ios')) const regex = /^([^/]+)\.xcodeproj$/ projectDir = files.find(function(filename) { if (!filename.match(regex)) { return false } stats = fs.statSync(path.join('.', 'ios', filename)) return stats.isDirectory() }) if (!projectDir) return null const result = regex.exec(projectDir) return result[1] } module.exports = { addBranchConfigToXcodeProject: addBranchConfigToXcodeProject, removeBranchConfigFromXcodeProject: removeBranchConfigFromXcodeProject }