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
}