initial commit taken from gitlab.lrz.de

This commit is contained in:
privatereese
2018-08-24 18:09:42 +02:00
parent ae54ed4c48
commit fc05486403
28494 changed files with 2159823 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs-extra');
const path = require('path');
const groupFilesByType = require('../groupFilesByType');
/**
* Copies each file from an array of assets provided to targetPath directory
*
* For now, the only types of files that are handled are:
* - Fonts (otf, ttf) - copied to targetPath/fonts under original name
*/
module.exports = function copyAssetsAndroid(files, project) {
const assets = groupFilesByType(files);
(assets.font || []).forEach(asset =>
fs.copySync(asset, path.join(project.assetsPath, 'fonts', path.basename(asset)))
);
};

15
node_modules/react-native/local-cli/link/android/fs.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs-extra');
exports.readFile = (file) =>
() => fs.readFileSync(file, 'utf8');
exports.writeFile = (file, content) => content ?
fs.writeFileSync(file, content, 'utf8') :
(c) => fs.writeFileSync(file, c, 'utf8');

View File

@@ -0,0 +1,9 @@
module.exports = function() {
return {
isInstalled: require('./isInstalled'),
register: require('./registerNativeModule'),
unregister: require('./unregisterNativeModule'),
copyAssets: require('./copyAssets'),
unlinkAssets: require('./unlinkAssets')
};
};

View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs');
const makeBuildPatch = require('./patches/makeBuildPatch');
module.exports = function isInstalled(config, name) {
const buildGradle = fs.readFileSync(config.buildGradlePath);
return makeBuildPatch(name).installPattern.test(buildGradle);
};

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const toCamelCase = require('lodash').camelCase;
module.exports = function applyParams(str, params, prefix) {
return str.replace(
/\$\{(\w+)\}/g,
(pattern, param) => {
const name = toCamelCase(prefix) + '_' + param;
return params[param]
? `getResources().getString(R.string.${name})`
: null;
}
);
};

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs');
module.exports = function applyPatch(file, patch) {
fs.writeFileSync(file, fs
.readFileSync(file, 'utf8')
.replace(patch.pattern, match => `${match}${patch.patch}`)
);
};

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = function makeBuildPatch(name) {
const installPattern = new RegExp(
`\\s{4}(compile)(\\(|\\s)(project)\\(\\\':${name}\\\'\\)(\\)|\\s)`
);
return {
installPattern,
pattern: /[^ \t]dependencies {\n/,
patch: ` compile project(':${name}')\n`
};
};

View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = function makeImportPatch(packageImportPath) {
return {
pattern: 'import com.facebook.react.ReactApplication;',
patch: '\n' + packageImportPath,
};
};

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const applyParams = require('./applyParams');
module.exports = function makePackagePatch(packageInstance, params, prefix) {
const processedInstance = applyParams(packageInstance, params, prefix);
return {
pattern: 'new MainReactPackage()',
patch: ',\n ' + processedInstance,
};
};

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const path = require('path');
const isWin = process.platform === 'win32';
module.exports = function makeSettingsPatch(name, androidConfig, projectConfig) {
var projectDir = path.relative(
path.dirname(projectConfig.settingsGradlePath),
androidConfig.sourceDir
);
/*
* Fix for Windows
* Backslashes is the escape character and will result in
* an invalid path in settings.gradle
* https://github.com/rnpm/rnpm/issues/113
*/
if (isWin) {
projectDir = projectDir.replace(/\\/g, '/');
}
return {
pattern: '\n',
patch: `include ':${name}'\n` +
`project(':${name}').projectDir = ` +
`new File(rootProject.projectDir, '${projectDir}')\n`,
};
};

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const toCamelCase = require('lodash').camelCase;
module.exports = function makeStringsPatch(params, prefix) {
const values = Object.keys(params)
.map(param => {
const name = toCamelCase(prefix) + '_' + param;
return ' ' +
`<string moduleConfig="true" name="${name}">${params[param]}</string>`;
});
const patch = values.length > 0
? values.join('\n') + '\n'
: '';
return {
pattern: '<resources>\n',
patch,
};
};

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs');
module.exports = function revokePatch(file, patch) {
fs.writeFileSync(file, fs
.readFileSync(file, 'utf8')
.replace(patch.patch, '')
);
};

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const applyPatch = require('./patches/applyPatch');
const makeStringsPatch = require('./patches/makeStringsPatch');
const makeSettingsPatch = require('./patches/makeSettingsPatch');
const makeBuildPatch = require('./patches/makeBuildPatch');
const makeImportPatch = require('./patches/makeImportPatch');
const makePackagePatch = require('./patches/makePackagePatch');
module.exports = function registerNativeAndroidModule(
name,
androidConfig,
params,
projectConfig
) {
const buildPatch = makeBuildPatch(name);
applyPatch(
projectConfig.settingsGradlePath,
makeSettingsPatch(name, androidConfig, projectConfig)
);
applyPatch(projectConfig.buildGradlePath, buildPatch);
applyPatch(projectConfig.stringsPath, makeStringsPatch(params, name));
applyPatch(
projectConfig.mainFilePath,
makePackagePatch(androidConfig.packageInstance, params, name)
);
applyPatch(
projectConfig.mainFilePath,
makeImportPatch(androidConfig.packageImportPath)
);
};

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs-extra');
const path = require('path');
const groupFilesByType = require('../groupFilesByType');
/**
* Copies each file from an array of assets provided to targetPath directory
*
* For now, the only types of files that are handled are:
* - Fonts (otf, ttf) - copied to targetPath/fonts under original name
*/
module.exports = function unlinkAssetsAndroid(files, project) {
const assets = groupFilesByType(files);
(assets.font || []).forEach((file) => {
const filePath = path.join(project.assetsPath, 'fonts', path.basename(file));
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
});
};

View File

@@ -0,0 +1,51 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs');
const toCamelCase = require('lodash').camelCase;
const revokePatch = require('./patches/revokePatch');
const makeSettingsPatch = require('./patches/makeSettingsPatch');
const makeBuildPatch = require('./patches/makeBuildPatch');
const makeStringsPatch = require('./patches/makeStringsPatch');
const makeImportPatch = require('./patches/makeImportPatch');
const makePackagePatch = require('./patches/makePackagePatch');
module.exports = function unregisterNativeAndroidModule(
name,
androidConfig,
projectConfig
) {
const buildPatch = makeBuildPatch(name);
const strings = fs.readFileSync(projectConfig.stringsPath, 'utf8');
var params = {};
strings.replace(
/moduleConfig="true" name="(\w+)">(.*)</g,
(_, param, value) => {
params[param.slice(toCamelCase(name).length + 1)] = value;
}
);
revokePatch(
projectConfig.settingsGradlePath,
makeSettingsPatch(name, androidConfig, projectConfig)
);
revokePatch(projectConfig.buildGradlePath, buildPatch);
revokePatch(projectConfig.stringsPath, makeStringsPatch(params, name));
revokePatch(
projectConfig.mainFilePath,
makePackagePatch(androidConfig.packageInstance, params, name)
);
revokePatch(
projectConfig.mainFilePath,
makeImportPatch(androidConfig.packageImportPath)
);
};

View File

@@ -0,0 +1,8 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = (cb) => cb();

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given an array of dependencies - it returns their RNPM config
* if they were valid.
*/
module.exports = function getDependencyConfig(config, deps) {
return deps.reduce((acc, name) => {
try {
return acc.concat({
config: config.getDependencyConfig(name),
name,
});
} catch (err) {
console.log(err);
return acc;
}
}, []);
};

View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const path = require('path');
/**
* Returns an array of dependencies that should be linked/checked.
*/
module.exports = function getProjectDependencies() {
const pjson = require(path.join(process.cwd(), './package.json'));
return Object.keys(pjson.dependencies || {}).filter(name => name !== 'react-native');
};

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const groupBy = require('lodash').groupBy;
const mime = require('mime');
/**
* Since there are no officially registered MIME types
* for ttf/otf yet http://www.iana.org/assignments/media-types/media-types.xhtml,
* we define two non-standard ones for the sake of parsing
*/
mime.define({
'font/opentype': ['otf'],
'font/truetype': ['ttf'],
});
/**
* Given an array of files, it groups it by it's type.
* Type of the file is inferred from it's mimetype based on the extension
* file ends up with. The returned value is an object with properties that
* correspond to the first part of the mimetype, e.g. images will be grouped
* under `image` key since the mimetype for them is `image/jpg` etc.
*
* Example:
* Given an array ['fonts/a.ttf', 'images/b.jpg'],
* the returned object will be: {font: ['fonts/a.ttf'], image: ['images/b.jpg']}
*/
module.exports = function groupFilesByType(assets) {
return groupBy(assets, type => mime.lookup(type).split('/')[0]);
};

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const PbxFile = require('xcode/lib/pbxFile');
/**
* Given xcodeproj and filePath, it creates new file
* from path provided, adds it to the project
* and returns newly created instance of a file
*/
module.exports = function addFileToProject(project, filePath) {
const file = new PbxFile(filePath);
file.uuid = project.generateUuid();
file.fileRef = project.generateUuid();
project.addToPbxFileReferenceSection(file);
return file;
};

View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given an array of xcodeproj libraries and pbxFile,
* it appends it to that group
*
* Important: That function mutates `libraries` and it's not pure.
* It's mainly due to limitations of `xcode` library.
*/
module.exports = function addProjectToLibraries(libraries, file) {
return libraries.children.push({
value: file.fileRef,
comment: file.basename,
});
};

View File

@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const createGroupWithMessage = require('./createGroupWithMessage');
module.exports = function addSharedLibraries(project, libraries) {
if (!libraries.length) {
return;
}
// Create a Frameworks group if necessary.
createGroupWithMessage(project, 'Frameworks');
const target = project.getFirstTarget().uuid;
for (var name of libraries) {
project.addFramework(name, { target });
}
};

View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const mapHeaderSearchPaths = require('./mapHeaderSearchPaths');
module.exports = function addToHeaderSearchPaths(project, path) {
mapHeaderSearchPaths(project, searchPaths => searchPaths.concat(path));
};

View File

@@ -0,0 +1,6 @@
const isInstalledIOS = require('../isInstalled');
const isInstalledPods = require('../../pods/isInstalled');
module.exports = function isInstalled(projectConfig, name, dependencyConfig) {
return isInstalledIOS(projectConfig, dependencyConfig) || isInstalledPods(projectConfig, dependencyConfig);
};

View File

@@ -0,0 +1,16 @@
const registerDependencyIOS = require('../registerNativeModule');
const registerDependencyPods = require('../../pods/registerNativeModule');
module.exports = function registerNativeModule(
name,
dependencyConfig,
params,
projectConfig
) {
if (projectConfig.podfile && dependencyConfig.podspec) {
registerDependencyPods(name, dependencyConfig, projectConfig);
}
else {
registerDependencyIOS(dependencyConfig, projectConfig);
}
};

View File

@@ -0,0 +1,22 @@
const compact = require('lodash').compact;
const isInstalledIOS = require('../isInstalled');
const isInstalledPods = require('../../pods/isInstalled');
const unregisterDependencyIOS = require('../unregisterNativeModule');
const unregisterDependencyPods = require('../../pods/unregisterNativeModule');
module.exports = function unregisterNativeModule(
name,
dependencyConfig,
projectConfig,
otherDependencies
) {
const isIosInstalled = isInstalledIOS(projectConfig, dependencyConfig);
const isPodInstalled = isInstalledPods(projectConfig, dependencyConfig);
if (isIosInstalled) {
const iOSDependencies = compact(otherDependencies.map(d => d.config.ios));
unregisterDependencyIOS(dependencyConfig, projectConfig, iOSDependencies);
}
else if (isPodInstalled) {
unregisterDependencyPods(dependencyConfig, projectConfig);
}
};

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs-extra');
const path = require('path');
const xcode = require('xcode');
const log = require('npmlog');
const groupFilesByType = require('../groupFilesByType');
const createGroupWithMessage = require('./createGroupWithMessage');
const getPlist = require('./getPlist');
const writePlist = require('./writePlist');
/**
* This function works in a similar manner to its Android version,
* except it does not copy fonts but creates Xcode Group references
*/
module.exports = function linkAssetsIOS(files, projectConfig) {
const project = xcode.project(projectConfig.pbxprojPath).parseSync();
const assets = groupFilesByType(files);
const plist = getPlist(project, projectConfig.sourceDir);
createGroupWithMessage(project, 'Resources');
function addResourceFile(f) {
return (f || [])
.map(asset =>
project.addResourceFile(
path.relative(projectConfig.sourceDir, asset),
{ target: project.getFirstTarget().uuid }
)
)
.filter(file => file) // xcode returns false if file is already there
.map(file => file.basename);
}
addResourceFile(assets.image);
const fonts = addResourceFile(assets.font);
const existingFonts = (plist.UIAppFonts || []);
const allFonts = [...existingFonts, ...fonts];
plist.UIAppFonts = Array.from(new Set(allFonts)); // use Set to dedupe w/existing
fs.writeFileSync(
projectConfig.pbxprojPath,
project.writeSync()
);
writePlist(project, projectConfig.sourceDir, plist);
};

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const getGroup = require('./getGroup');
const hasGroup = (pbxGroup, name) => pbxGroup.children.find(group => group.comment === name);
/**
* Given project and path of the group, it deeply creates a given group
* making all outer groups if necessary
*
* Returns newly created group
*/
module.exports = function createGroup(project, path) {
return path.split('/').reduce(
(group, name) => {
if (!hasGroup(group, name)) {
const uuid = project.pbxCreateGroup(name, '""');
group.children.push({
value: uuid,
comment: name,
});
}
return project.pbxGroupByName(name);
},
getGroup(project)
);
};

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const log = require('npmlog');
const createGroup = require('./createGroup');
const getGroup = require('./getGroup');
/**
* Given project and path of the group, it checks if a group exists at that path,
* and deeply creates a group for that path if its does not already exist.
*
* Returns the existing or newly created group
*/
module.exports = function createGroupWithMessage(project, path) {
var group = getGroup(project, path);
if (!group) {
group = createGroup(project, path);
log.warn(
'ERRGROUP',
`Group '${path}' does not exist in your Xcode project. We have created it automatically for you.`
);
}
return group;
};

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Gets build property from the main target build section
*
* It differs from the project.getBuildProperty exposed by xcode in the way that:
* - it only checks for build property in the main target `Debug` section
* - `xcode` library iterates over all build sections and because it misses
* an early return when property is found, it will return undefined/wrong value
* when there's another build section typically after the one you want to access
* without the property defined (e.g. CocoaPods sections appended to project
* miss INFOPLIST_FILE), see: https://github.com/alunny/node-xcode/blob/master/lib/pbxProject.js#L1765
*/
module.exports = function getBuildProperty(project, prop) {
const target = project.getFirstTarget().firstTarget;
const config = project.pbxXCConfigurationList()[target.buildConfigurationList];
const buildSection = project.pbxXCBuildConfigurationSection()[config.buildConfigurations[0].value];
return buildSection.buildSettings[prop];
};

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const getFirstProject = (project) => project.getFirstProject().firstProject;
const findGroup = (group, name) => group.children.find(group => group.comment === name);
/**
* Returns group from .xcodeproj if one exists, null otherwise
*
* Unlike node-xcode `pbxGroupByName` - it does not return `first-matching`
* group if multiple groups with the same name exist
*
* If path is not provided, it returns top-level group
*/
module.exports = function getGroup(project, path) {
const firstProject = getFirstProject(project);
var group = project.getPBXGroupByKey(firstProject.mainGroup);
if (!path) {
return group;
}
for (var name of path.split('/')) {
var foundGroup = findGroup(group, name);
if (foundGroup) {
group = project.getPBXGroupByKey(foundGroup.value);
} else {
group = null;
break;
}
}
return group;
};

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const path = require('path');
const union = require('lodash').union;
const last = require('lodash').last;
/**
* Given an array of directories, it returns the one that contains
* all the other directories in a given array inside it.
*
* Example:
* Given an array of directories: ['/Users/Kureev/a', '/Users/Kureev/b']
* the returned folder is `/Users/Kureev`
*
* Check `getHeaderSearchPath.spec.js` for more use-cases.
*/
const getOuterDirectory = (directories) =>
directories.reduce((topDir, currentDir) => {
const currentFolders = currentDir.split(path.sep);
const topMostFolders = topDir.split(path.sep);
if (currentFolders.length === topMostFolders.length
&& last(currentFolders) !== last(topMostFolders)) {
return currentFolders.slice(0, -1).join(path.sep);
}
return currentFolders.length < topMostFolders.length
? currentDir
: topDir;
});
/**
* Given an array of headers it returns search path so Xcode can resolve
* headers when referenced like below:
* ```
* #import "CodePush.h"
* ```
* If all files are located in one directory (directories.length === 1),
* we simply return a relative path to that location.
*
* Otherwise, we loop through them all to find the outer one that contains
* all the headers inside. That location is then returned with /** appended at
* the end so Xcode marks that location as `recursive` and will look inside
* every folder of it to locate correct headers.
*/
module.exports = function getHeaderSearchPath(sourceDir, headers) {
const directories = union(
headers.map(path.dirname)
);
return directories.length === 1
? `"$(SRCROOT)${path.sep}${path.relative(sourceDir, directories[0])}"`
: `"$(SRCROOT)${path.sep}${path.relative(sourceDir, getOuterDirectory(directories))}/**"`;
};

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const glob = require('glob');
const path = require('path');
const GLOB_EXCLUDE_PATTERN = ['node_modules/**', 'Pods/**', 'Examples/**', 'examples/**'];
/**
* Given folder, it returns an array of all header files
* inside it, ignoring node_modules and examples
*/
module.exports = function getHeadersInFolder(folder) {
return glob
.sync('**/*.h', {
cwd: folder,
nodir: true,
ignore: GLOB_EXCLUDE_PATTERN,
})
.map(file => path.join(folder, file));
};

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const plistParser = require('plist');
const getPlistPath = require('./getPlistPath');
const fs = require('fs');
/**
* Returns Info.plist located in the iOS project
*
* Returns `null` if INFOPLIST_FILE is not specified.
*/
module.exports = function getPlist(project, sourceDir) {
const plistPath = getPlistPath(project, sourceDir);
if (!plistPath || !fs.existsSync(plistPath)) {
return null;
}
return plistParser.parse(
fs.readFileSync(plistPath, 'utf-8')
);
};

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const path = require('path');
const getBuildProperty = require('./getBuildProperty');
module.exports = function getPlistPath(project, sourceDir) {
const plistFile = getBuildProperty(project, 'INFOPLIST_FILE');
if (!plistFile) {
return null;
}
return path.join(
sourceDir,
plistFile.replace(/"/g, '').replace('$(SRCROOT)', '')
);
};

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given xcodeproj it returns list of products ending with
* .a extension, so that we know what elements add to target
* project static library
*/
module.exports = function getProducts(project) {
return project
.pbxGroupByName('Products')
.children
.map(c => c.comment)
.filter(c => c.indexOf('.a') > -1);
};

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given xcodeproj it returns list of targets
*/
module.exports = function getTargets(project) {
let targets = project.getFirstProject().firstProject.targets;
let nativeTargetSection = project.pbxNativeTargetSection();
return targets.map(function(target) {
let key = target.value;
let configurationListId = project.pbxNativeTargetSection()[key].buildConfigurationList;
let configurationList = project.pbxXCConfigurationList()[configurationListId];
let buildConfigurationId = configurationList.buildConfigurations[0].value;
let buildConfiguration = project.pbxXCBuildConfigurationSection()[buildConfigurationId];
return {
uuid: key,
target: nativeTargetSection[key],
name: nativeTargetSection[key].productReference_comment,
isTVOS: (buildConfiguration.buildSettings.SDKROOT && (buildConfiguration.buildSettings.SDKROOT.indexOf('appletv') !== -1)) || false
};
});
};

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given an array of libraries already imported and packageName that will be
* added, returns true or false depending on whether the library is already linked
* or not
*/
module.exports = function hasLibraryImported(libraries, packageName) {
return libraries.children
.filter(library => library.comment === packageName)
.length > 0;
};

View File

@@ -0,0 +1,9 @@
module.exports = function() {
return {
isInstalled: require('./common/isInstalled'),
register: require('./common/registerNativeModule'),
unregister: require('./common/unregisterNativeModule'),
copyAssets: require('./copyAssets'),
unlinkAssets: require('./unlinkAssets')
};
};

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const xcode = require('xcode');
const getGroup = require('./getGroup');
const hasLibraryImported = require('./hasLibraryImported');
/**
* Returns true if `xcodeproj` specified by dependencyConfig is present
* in a top level `libraryFolder`
*/
module.exports = function isInstalled(projectConfig, dependencyConfig) {
const project = xcode.project(projectConfig.pbxprojPath).parseSync();
const libraries = getGroup(project, projectConfig.libraryFolder);
if (!libraries) {
return false;
}
return hasLibraryImported(libraries, dependencyConfig.projectName);
};

View File

@@ -0,0 +1,48 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given Xcode project and path, iterate over all build configurations
* and execute func with HEADER_SEARCH_PATHS from current section
*
* We cannot use builtin addToHeaderSearchPaths method since react-native init does not
* use $(TARGET_NAME) for PRODUCT_NAME, but sets it manually so that method will skip
* that target.
*
* To workaround that issue and make it more bullet-proof for different names,
* we iterate over all configurations and look for `lc++` linker flag to detect
* React Native target.
*
* Important: That function mutates `buildSettings` and it's not pure thus you should
* not rely on its return value
*/
const defaultHeaderPaths = ['"$(inherited)"'];
module.exports = function headerSearchPathIter(project, func) {
const config = project.pbxXCBuildConfigurationSection();
Object
.keys(config)
.filter(ref => ref.indexOf('_comment') === -1)
.forEach(ref => {
const buildSettings = config[ref].buildSettings;
const shouldVisitBuildSettings = (
Array.isArray(buildSettings.OTHER_LDFLAGS) ?
buildSettings.OTHER_LDFLAGS :
[]
)
.indexOf('"-lc++"') >= 0;
if (shouldVisitBuildSettings) {
const searchPaths = buildSettings.HEADER_SEARCH_PATHS ?
[].concat(buildSettings.HEADER_SEARCH_PATHS) :
defaultHeaderPaths;
buildSettings.HEADER_SEARCH_PATHS = func(searchPaths);
}
});
};

View File

@@ -0,0 +1,83 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const xcode = require('xcode');
const fs = require('fs');
const path = require('path');
const log = require('npmlog');
const addToHeaderSearchPaths = require('./addToHeaderSearchPaths');
const getHeadersInFolder = require('./getHeadersInFolder');
const getHeaderSearchPath = require('./getHeaderSearchPath');
const getProducts = require('./getProducts');
const getTargets = require('./getTargets');
const createGroupWithMessage = require('./createGroupWithMessage');
const addFileToProject = require('./addFileToProject');
const addProjectToLibraries = require('./addProjectToLibraries');
const addSharedLibraries = require('./addSharedLibraries');
const isEmpty = require('lodash').isEmpty;
const getGroup = require('./getGroup');
/**
* Register native module IOS adds given dependency to project by adding
* its xcodeproj to project libraries as well as attaching static library
* to the first target (the main one)
*
* If library is already linked, this action is a no-op.
*/
module.exports = function registerNativeModuleIOS(dependencyConfig, projectConfig) {
const project = xcode.project(projectConfig.pbxprojPath).parseSync();
const dependencyProject = xcode.project(dependencyConfig.pbxprojPath).parseSync();
const libraries = createGroupWithMessage(project, projectConfig.libraryFolder);
const file = addFileToProject(
project,
path.relative(projectConfig.sourceDir, dependencyConfig.projectPath)
);
const targets = getTargets(project);
addProjectToLibraries(libraries, file);
getTargets(dependencyProject).forEach(product => {
var i;
if (!product.isTVOS) {
for (i = 0; i < targets.length; i++) {
if (!targets[i].isTVOS) {
project.addStaticLibrary(product.name, {
target: targets[i].uuid
});
}
}
}
if (product.isTVOS) {
for (i = 0; i < targets.length; i++) {
if (targets[i].isTVOS) {
project.addStaticLibrary(product.name, {
target: targets[i].uuid
});
}
}
}
});
addSharedLibraries(project, dependencyConfig.sharedLibraries);
const headers = getHeadersInFolder(dependencyConfig.folder);
if (!isEmpty(headers)) {
addToHeaderSearchPaths(
project,
getHeaderSearchPath(projectConfig.sourceDir, headers)
);
}
fs.writeFileSync(
projectConfig.pbxprojPath,
project.writeSync()
);
};

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const mapHeaderSearchPaths = require('./mapHeaderSearchPaths');
/**
* Given Xcode project and absolute path, it makes sure there are no headers referring to it
*/
module.exports = function addToHeaderSearchPaths(project, path) {
mapHeaderSearchPaths(project,
searchPaths => searchPaths.filter(searchPath => searchPath !== path)
);
};

View File

@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* For all files that are created and referenced from another `.xcodeproj` -
* a new PBXItemContainerProxy is created that contains `containerPortal` value
* which equals to xcodeproj file.uuid from PBXFileReference section.
*/
module.exports = function removeFromPbxItemContainerProxySection(project, file) {
const section = project.hash.project.objects.PBXContainerItemProxy;
for (var key of Object.keys(section)) {
if (section[key].containerPortal === file.uuid) {
delete section[key];
}
}
return;
};

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Every file added to the project from another project is attached to
* `PBXItemContainerProxy` through `PBXReferenceProxy`.
*/
module.exports = function removeFromPbxReferenceProxySection(project, file) {
const section = project.hash.project.objects.PBXReferenceProxy;
for (var key of Object.keys(section)) {
if (section[key].path === file.basename) {
delete section[key];
}
}
return;
};

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* For each file (.xcodeproj), there's an entry in `projectReferences` created
* that has two entries - `ProjectRef` - reference to a file.uuid and
* `ProductGroup` - uuid of a Products group.
*
* When projectReference is found - it's deleted and the removed value is returned
* so that ProductGroup in PBXGroup section can be removed as well.
*
* Otherwise returns null
*/
module.exports = function removeFromProjectReferences(project, file) {
const firstProject = project.getFirstProject().firstProject;
const projectRef = firstProject.projectReferences.find(item => item.ProjectRef === file.uuid);
if (!projectRef) {
return null;
}
firstProject.projectReferences.splice(
firstProject.projectReferences.indexOf(projectRef),
1
);
return projectRef;
};

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const PbxFile = require('xcode/lib/pbxFile');
const removeFromPbxReferenceProxySection = require('./removeFromPbxReferenceProxySection');
/**
* Removes file from static libraries
*
* Similar to `node-xcode` addStaticLibrary
*/
module.exports = function removeFromStaticLibraries(project, path, opts) {
const file = new PbxFile(path);
file.target = opts ? opts.target : undefined;
project.removeFromPbxFileReferenceSection(file);
project.removeFromPbxBuildFileSection(file);
project.removeFromPbxFrameworksBuildPhase(file);
project.removeFromLibrarySearchPaths(file);
removeFromPbxReferenceProxySection(project, file);
return file;
};

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = function removeProductGroup(project, productGroupId) {
const section = project.hash.project.objects.PBXGroup;
for (var key of Object.keys(section)) {
if (key === productGroupId) {
delete section[key];
}
}
return;
};

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given an array of xcodeproj libraries and pbxFile,
* it removes it from that group by comparing basenames
*
* Important: That function mutates `libraries` and it's not pure.
* It's mainly due to limitations of `xcode` library.
*/
module.exports = function removeProjectFromLibraries(libraries, file) {
libraries.children = libraries.children.filter(library =>
library.comment !== file.basename
);
};

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const PbxFile = require('xcode/lib/pbxFile');
const removeFromPbxItemContainerProxySection = require('./removeFromPbxItemContainerProxySection');
const removeFromProjectReferences = require('./removeFromProjectReferences');
const removeProductGroup = require('./removeProductGroup');
/**
* Given xcodeproj and filePath, it creates new file
* from path provided and removes it. That operation is required since
* underlying method requires PbxFile instance to be passed (it does not
* have to have uuid or fileRef defined since it will do equality check
* by path)
*
* Returns removed file (that one will have UUID)
*/
module.exports = function removeProjectFromProject(project, filePath) {
const file = project.removeFromPbxFileReferenceSection(new PbxFile(filePath));
const projectRef = removeFromProjectReferences(project, file);
if (projectRef) {
removeProductGroup(project, projectRef.ProductGroup);
}
removeFromPbxItemContainerProxySection(project, file);
return file;
};

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = function removeSharedLibraries(project, libraries) {
if (!libraries.length) {
return;
}
const target = project.getFirstTarget().uuid;
for (var name of libraries) {
project.removeFramework(name, { target });
}
};

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const fs = require('fs-extra');
const path = require('path');
const xcode = require('xcode');
const log = require('npmlog');
const groupFilesByType = require('../groupFilesByType');
const getPlist = require('./getPlist');
const writePlist = require('./writePlist');
const difference = require('lodash').difference;
/**
* Unlinks assets from iOS project. Removes references for fonts from `Info.plist`
* fonts provided by application and from `Resources` group
*/
module.exports = function unlinkAssetsIOS(files, projectConfig) {
const project = xcode.project(projectConfig.pbxprojPath).parseSync();
const assets = groupFilesByType(files);
const plist = getPlist(project, projectConfig.sourceDir);
if (!plist) {
return log.error(
'ERRPLIST',
'Could not locate Info.plist file. Check if your project has \'INFOPLIST_FILE\' set properly'
);
}
if (!project.pbxGroupByName('Resources')) {
return log.error(
'ERRGROUP',
'Group \'Resources\' does not exist in your Xcode project. There is nothing to unlink.'
);
}
const removeResourceFile = function (f) {
(f || [])
.map(asset =>
project.removeResourceFile(
path.relative(projectConfig.sourceDir, asset),
{ target: project.getFirstTarget().uuid }
)
)
.map(file => file.basename);
};
removeResourceFile(assets.image);
const fonts = removeResourceFile(assets.font);
plist.UIAppFonts = difference(plist.UIAppFonts || [], fonts);
fs.writeFileSync(
projectConfig.pbxprojPath,
project.writeSync()
);
writePlist(project, projectConfig.sourceDir, plist);
};

View File

@@ -0,0 +1,71 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const xcode = require('xcode');
const path = require('path');
const fs = require('fs');
const difference = require('lodash').difference;
const isEmpty = require('lodash').isEmpty;
const getGroup = require('./getGroup');
const getProducts = require('./getProducts');
const getTargets = require('./getTargets');
const getHeadersInFolder = require('./getHeadersInFolder');
const getHeaderSearchPath = require('./getHeaderSearchPath');
const removeProjectFromProject = require('./removeProjectFromProject');
const removeProjectFromLibraries = require('./removeProjectFromLibraries');
const removeFromStaticLibraries = require('./removeFromStaticLibraries');
const removeFromHeaderSearchPaths = require('./removeFromHeaderSearchPaths');
const removeSharedLibraries = require('./removeSharedLibraries');
/**
* Unregister native module IOS
*
* If library is already unlinked, this action is a no-op.
*/
module.exports = function unregisterNativeModule(dependencyConfig, projectConfig, iOSDependencies) {
const project = xcode.project(projectConfig.pbxprojPath).parseSync();
const dependencyProject = xcode.project(dependencyConfig.pbxprojPath).parseSync();
const libraries = getGroup(project, projectConfig.libraryFolder);
const file = removeProjectFromProject(
project,
path.relative(projectConfig.sourceDir, dependencyConfig.projectPath)
);
removeProjectFromLibraries(libraries, file);
getTargets(dependencyProject).forEach(target => {
removeFromStaticLibraries(project, target.name, {
target: project.getFirstTarget().uuid,
});
});
const sharedLibraries = difference(
dependencyConfig.sharedLibraries,
iOSDependencies.reduce(
(libs, dependency) => libs.concat(dependency.sharedLibraries),
projectConfig.sharedLibraries
)
);
removeSharedLibraries(project, sharedLibraries);
const headers = getHeadersInFolder(dependencyConfig.folder);
if (!isEmpty(headers)) {
removeFromHeaderSearchPaths(
project,
getHeaderSearchPath(projectConfig.sourceDir, headers)
);
}
fs.writeFileSync(
projectConfig.pbxprojPath,
project.writeSync()
);
};

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const plistParser = require('plist');
const getPlistPath = require('./getPlistPath');
const fs = require('fs');
/**
* Writes to Info.plist located in the iOS project
*
* Returns `null` if INFOPLIST_FILE is not specified or file is non-existent.
*/
module.exports = function writePlist(project, sourceDir, plist) {
const plistPath = getPlistPath(project, sourceDir);
if (!plistPath) {
return null;
}
// We start with an offset of -1, because Xcode maintains a custom
// indentation of the plist.
// Ref: https://github.com/facebook/react-native/issues/11668
return fs.writeFileSync(
plistPath,
plistParser.build(plist, { indent: '\t', offset: -1 }) + '\n'
);
};

162
node_modules/react-native/local-cli/link/link.js generated vendored Normal file
View File

@@ -0,0 +1,162 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const log = require('npmlog');
const path = require('path');
const uniqBy = require('lodash').uniqBy;
const flatten = require('lodash').flatten;
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const chalk = require('chalk');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const isEmpty = require('lodash').isEmpty;
const promiseWaterfall = require('./promiseWaterfall');
const getProjectDependencies = require('./getProjectDependencies');
const getDependencyConfig = require('./getDependencyConfig');
const pollParams = require('./pollParams');
const commandStub = require('./commandStub');
const promisify = require('./promisify');
const findReactNativeScripts = require('../util/findReactNativeScripts');
import type {RNConfig} from '../core';
log.heading = 'rnpm-link';
const dedupeAssets = (assets) => uniqBy(assets, asset => path.basename(asset));
const linkDependency = async (platforms, project, dependency) => {
const params = await pollParams(dependency.config.params);
Object.keys(platforms || {})
.forEach(platform => {
if (!project[platform] || !dependency.config[platform]) {
return null;
}
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
if (!linkConfig || !linkConfig.isInstalled || !linkConfig.register) {
return null;
}
const isInstalled = linkConfig.isInstalled(project[platform], dependency.name, dependency.config[platform]);
if (isInstalled) {
log.info(chalk.grey(`Platform '${platform}' module ${dependency.name} is already linked`));
return null;
}
log.info(`Linking ${dependency.name} ${platform} dependency`);
linkConfig.register(
dependency.name,
dependency.config[platform],
params,
project[platform]
);
log.info(`Platform '${platform}' module ${dependency.name} has been successfully linked`);
});
};
const linkAssets = (platforms, project, assets) => {
if (isEmpty(assets)) {
return;
}
Object.keys(platforms || {})
.forEach(platform => {
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
if (!linkConfig || !linkConfig.copyAssets) {
return;
}
log.info(`Linking assets to ${platform} project`);
linkConfig.copyAssets(assets, project[platform]);
});
log.info('Assets have been successfully linked to your project');
};
/**
* Updates project and links all dependencies to it.
*
* @param args If optional argument [packageName] is provided,
* only that package is processed.
* @param config CLI config, see local-cli/core/index.js
*/
function link(args: Array<string>, config: RNConfig) {
let project;
let platforms;
try {
project = config.getProjectConfig();
platforms = config.getPlatformConfig();
} catch (err) {
log.error(
'ERRPACKAGEJSON',
'No package found. Are you sure this is a React Native project?'
);
return Promise.reject(err);
}
const hasProjectConfig = Object.keys(platforms).reduce((acc, key) => acc || key in project, false);
if (!hasProjectConfig && findReactNativeScripts()) {
throw new Error(
'`react-native link` can not be used in Create React Native App projects. ' +
'If you need to include a library that relies on custom native code, ' +
'you might have to eject first. ' +
'See https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md ' +
'for more information.'
);
}
let packageName = args[0];
// Check if install package by specific version (eg. package@latest)
if (packageName !== undefined) {
packageName = packageName.split('@')[0];
}
const dependencies = getDependencyConfig(
config,
packageName ? [packageName] : getProjectDependencies()
);
const assets = dedupeAssets(dependencies.reduce(
(acc, dependency) => acc.concat(dependency.config.assets),
project.assets
));
const tasks = flatten(dependencies.map(dependency => [
() => promisify(dependency.config.commands.prelink || commandStub),
() => linkDependency(platforms, project, dependency),
() => promisify(dependency.config.commands.postlink || commandStub),
]));
tasks.push(() => linkAssets(platforms, project, assets));
return promiseWaterfall(tasks).catch(err => {
log.error(
`Something went wrong while linking. Error: ${err.message} \n` +
'Please file an issue here: https://github.com/facebook/react-native/issues'
);
throw err;
});
}
module.exports = {
func: link,
description: 'links all native dependencies (updates native build files)',
name: 'link [packageName]',
};

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function addPodEntry(podLines, linesToAddEntry, podName, nodePath) {
const newEntry = `pod '${podName}', :path => '../node_modules/${nodePath}'\n`;
if (!linesToAddEntry) {
return;
} else if (Array.isArray(linesToAddEntry)) {
linesToAddEntry.map(({ line, indentation }, idx) =>
podLines.splice(line + idx, 0, getLineToAdd(newEntry, indentation))
);
} else {
const { line, indentation } = linesToAddEntry;
podLines.splice(line, 0, getLineToAdd(newEntry, indentation));
}
};
function getLineToAdd(newEntry, indentation) {
const spaces = Array(indentation + 1).join(' ');
return spaces + newEntry;
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function findLineToAddPod(podLines, firstTargetLine) {
// match line with new target: target 'project_name' do (most likely target inside podfile main target)
const nextTarget = /target (\'|\")\w+(\'|\") do/g;
// match line that has only 'end' (if we don't catch new target or function, this would mean this is end of current target)
const endOfCurrentTarget = /^\s*end\s*$/g;
// match function definition, like: post_install do |installer| (some Podfiles have function defined inside main target
const functionDefinition = /^\s*[a-z_]+\s+do(\s+\|[a-z]+\|)?/g;
for (let i = firstTargetLine, len = podLines.length; i < len; i++) {
const matchNextConstruct = podLines[i].match(nextTarget) || podLines[i].match(functionDefinition);
const matchEnd = podLines[i].match(endOfCurrentTarget);
if (matchNextConstruct || matchEnd) {
const firstNonSpaceCharacter = podLines[i].search(/\S/);
return {
indentation: firstNonSpaceCharacter + (matchEnd ? 2 : 0),
line: i
};
}
}
return null;
};

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const MARKER_TEXT = '# Add new pods below this line';
module.exports = function findMarkedLinesInPodfile(podLines) {
const result = [];
for (let i = 0, len = podLines.length; i < len; i++) {
if (podLines[i].includes(MARKER_TEXT)) {
result.push({ line: i + 1, indentation: podLines[i].indexOf('#') });
}
}
return result;
};

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function findPodTargetLine(podLines, projectName) {
const targetName = projectName.replace('.xcodeproj', '');
//match first target definition in file: target 'target_name' do
const targetRegex = new RegExp('target (\'|\")' + targetName + '(\'|\") do', 'g');
for (let i = 0, len = podLines.length; i < len; i++) {
const match = podLines[i].match(targetRegex);
if (match) {
return i + 1;
}
}
return null;
};

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const readPodfile = require('./readPodfile');
module.exports = function isInstalled(iOSProject, dependencyConfig) {
if (!iOSProject.podfile) {
return false;
}
// match line with pod declaration: pod 'dependencyPodName' (other possible parameters of pod are ignored)
const dependencyRegExp = new RegExp('pod\\s+(\'|\")' + dependencyConfig.podspec + '(\'|\")', 'g');
const podLines = readPodfile(iOSProject.podfile);
for (let i = 0, len = podLines.length; i < len; i++) {
const match = podLines[i].match(dependencyRegExp);
if (match) {
return true;
}
}
return false;
};

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const fs = require('fs');
module.exports = function readPodfile(podfilePath) {
const podContent = fs.readFileSync(podfilePath, 'utf8');
return podContent.split(/\r?\n/g);
};

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const readPodfile = require('./readPodfile');
const findPodTargetLine = require('./findPodTargetLine');
const findLineToAddPod = require('./findLineToAddPod');
const findMarkedLinesInPodfile = require('./findMarkedLinesInPodfile');
const addPodEntry = require('./addPodEntry');
const savePodFile = require('./savePodFile');
module.exports = function registerNativeModulePods(name, dependencyConfig, iOSProject) {
const podLines = readPodfile(iOSProject.podfile);
const linesToAddEntry = getLinesToAddEntry(podLines, iOSProject);
addPodEntry(podLines, linesToAddEntry, dependencyConfig.podspec, name);
savePodFile(iOSProject.podfile, podLines);
};
function getLinesToAddEntry(podLines, { projectName }) {
const linesToAddPodWithMarker = findMarkedLinesInPodfile(podLines);
if (linesToAddPodWithMarker.length > 0) {
return linesToAddPodWithMarker;
} else {
const firstTargetLined = findPodTargetLine(podLines, projectName);
return findLineToAddPod(podLines, firstTargetLined);
}
}

View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function removePodEntry(podfileContent, podName) {
// this regex should catch line(s) with full pod definition, like: pod 'podname', :path => '../node_modules/podname', :subspecs => ['Sub2', 'Sub1']
const podRegex = new RegExp("\\n( |\\t)*pod\\s+(\"|')" + podName + "(\"|')(,\\s*(:[a-z]+\\s*=>)?\\s*((\"|').*?(\"|')|\\[[\\s\\S]*?\\]))*\\n", 'g');
return podfileContent.replace(podRegex, '\n');
};

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const fs = require('fs');
module.exports = function savePodFile(podfilePath, podLines) {
const newPodfile = podLines.join('\n');
fs.writeFileSync(podfilePath, newPodfile);
};

View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const fs = require('fs');
const removePodEntry = require('./removePodEntry');
/**
* Unregister native module IOS with CocoaPods
*/
module.exports = function unregisterNativeModule(dependencyConfig, iOSProject) {
const podContent = fs.readFileSync(iOSProject.podfile, 'utf8');
const removed = removePodEntry(podContent, dependencyConfig.podspec);
fs.writeFileSync(iOSProject.podfile, removed);
};

16
node_modules/react-native/local-cli/link/pollParams.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var inquirer = require('inquirer');
module.exports = (questions) => new Promise((resolve, reject) => {
if (!questions) {
return resolve({});
}
inquirer.prompt(questions).then(resolve, reject);
});

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Given an array of promise creators, executes them in a sequence.
*
* If any of the promises in the chain fails, all subsequent promises
* will be skipped
*
* Returns the value last promise from a sequence resolved
*/
module.exports = function promiseWaterfall(tasks) {
return tasks.reduce(
(prevTaskPromise, task) => prevTaskPromise.then(task),
Promise.resolve()
);
};

10
node_modules/react-native/local-cli/link/promisify.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = (func) => new Promise((resolve, reject) =>
func((err, res) => err ? reject(err) : resolve(res))
);

138
node_modules/react-native/local-cli/link/unlink.js generated vendored Normal file
View File

@@ -0,0 +1,138 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const log = require('npmlog');
const getProjectDependencies = require('./getProjectDependencies');
const getDependencyConfig = require('./getDependencyConfig');
const difference = require('lodash').difference;
const filter = require('lodash').filter;
const flatten = require('lodash').flatten;
const isEmpty = require('lodash').isEmpty;
const promiseWaterfall = require('./promiseWaterfall');
const commandStub = require('./commandStub');
const promisify = require('./promisify');
log.heading = 'rnpm-link';
const unlinkDependency = (platforms, project, dependency, packageName, otherDependencies) => {
Object.keys(platforms || {})
.forEach(platform => {
if (!project[platform] || !dependency[platform]) {
return;
}
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
if (!linkConfig || !linkConfig.isInstalled || !linkConfig.unregister) {
return;
}
const isInstalled = linkConfig.isInstalled(project[platform], packageName, dependency[platform]);
if (!isInstalled) {
log.info(`Platform '${platform}' module ${packageName} is not installed`);
return;
}
log.info(`Unlinking ${packageName} ${platform} dependency`);
linkConfig.unregister(
packageName,
dependency[platform],
project[platform],
otherDependencies
);
log.info(`Platform '${platform}' module ${dependency.name} has been successfully unlinked`);
});
};
/**
* Updates project and unlink specific dependency
*
* If optional argument [packageName] is provided, it's the only one
* that's checked
*/
function unlink(args, config) {
const packageName = args[0];
let platforms;
let project;
let dependency;
try {
platforms = config.getPlatformConfig();
project = config.getProjectConfig();
} catch (err) {
log.error(
'ERRPACKAGEJSON',
'No package found. Are you sure it\'s a React Native project?'
);
return Promise.reject(err);
}
try {
dependency = config.getDependencyConfig(packageName);
} catch (err) {
log.warn(
'ERRINVALIDPROJ',
`Project ${packageName} is not a react-native library`
);
return Promise.reject(err);
}
const allDependencies = getDependencyConfig(config, getProjectDependencies());
const otherDependencies = filter(allDependencies, d => d.name !== packageName);
const tasks = [
() => promisify(dependency.commands.preunlink || commandStub),
() => unlinkDependency(platforms, project, dependency, packageName, otherDependencies),
() => promisify(dependency.commands.postunlink || commandStub)
];
return promiseWaterfall(tasks)
.then(() => {
// @todo move all these to `tasks` array, just like in
// link
const assets = difference(
dependency.assets,
flatten(allDependencies, d => d.assets)
);
if (isEmpty(assets)) {
return Promise.resolve();
}
Object.keys(platforms || {})
.forEach(platform => {
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
if (!linkConfig || !linkConfig.unlinkAssets) {
return;
}
log.info(`Unlinking assets from ${platform} project`);
linkConfig.unlinkAssets(assets, project[platform]);
});
log.info(
`${packageName} assets has been successfully unlinked from your project`
);
})
.catch(err => {
log.error(
`It seems something went wrong while unlinking. Error: ${err.message}`
);
throw err;
});
}
module.exports = {
func: unlink,
description: 'unlink native dependency',
name: 'unlink <packageName>',
};