You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2015/12/03 03:33:38 UTC

[06/51] [partial] ios commit: CB-9827 Implement and expose PlatformApi for iOS

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/lib/pbxProject.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/lib/pbxProject.js b/bin/node_modules/xcode/lib/pbxProject.js
new file mode 100644
index 0000000..5270588
--- /dev/null
+++ b/bin/node_modules/xcode/lib/pbxProject.js
@@ -0,0 +1,1623 @@
+var util = require('util'),
+    f = util.format,
+    EventEmitter = require('events').EventEmitter,
+    path = require('path'),
+    uuid = require('node-uuid'),
+    fork = require('child_process').fork,
+    pbxWriter = require('./pbxWriter'),
+    pbxFile = require('./pbxFile'),
+    fs = require('fs'),
+    parser = require('./parser/pbxproj'),
+    COMMENT_KEY = /_comment$/
+
+function pbxProject(filename) {
+    if (!(this instanceof pbxProject))
+        return new pbxProject(filename);
+
+    this.filepath = path.resolve(filename)
+}
+
+util.inherits(pbxProject, EventEmitter)
+
+pbxProject.prototype.parse = function(cb) {
+    var worker = fork(__dirname + '/parseJob.js', [this.filepath])
+
+    worker.on('message', function(msg) {
+        if (msg.name == 'SyntaxError' || msg.code) {
+            this.emit('error', msg);
+        } else {
+            this.hash = msg;
+            this.emit('end', null, msg)
+        }
+    }.bind(this));
+
+    if (cb) {
+        this.on('error', cb);
+        this.on('end', cb);
+    }
+
+    return this;
+}
+
+pbxProject.prototype.parseSync = function() {
+    var file_contents = fs.readFileSync(this.filepath, 'utf-8');
+
+    this.hash = parser.parse(file_contents);
+    return this;
+}
+
+pbxProject.prototype.writeSync = function() {
+    this.writer = new pbxWriter(this.hash);
+    return this.writer.writeSync();
+}
+
+pbxProject.prototype.allUuids = function() {
+    var sections = this.hash.project.objects,
+        uuids = [],
+        section;
+
+    for (key in sections) {
+        section = sections[key]
+        uuids = uuids.concat(Object.keys(section))
+    }
+
+    uuids = uuids.filter(function(str) {
+        return !COMMENT_KEY.test(str) && str.length == 24;
+    });
+
+    return uuids;
+}
+
+pbxProject.prototype.generateUuid = function() {
+    var id = uuid.v4()
+        .replace(/-/g, '')
+        .substr(0, 24)
+        .toUpperCase()
+
+    if (this.allUuids().indexOf(id) >= 0) {
+        return this.generateUuid();
+    } else {
+        return id;
+    }
+}
+
+pbxProject.prototype.addPluginFile = function(path, opt) {
+    var file = new pbxFile(path, opt);
+
+    file.plugin = true; // durr
+    correctForPluginsPath(file, this);
+
+    // null is better for early errors
+    if (this.hasFile(file.path)) return null;
+
+    file.fileRef = this.generateUuid();
+
+    this.addToPbxFileReferenceSection(file);    // PBXFileReference
+    this.addToPluginsPbxGroup(file);            // PBXGroup
+
+    return file;
+}
+
+pbxProject.prototype.removePluginFile = function(path, opt) {
+    var file = new pbxFile(path, opt);
+    correctForPluginsPath(file, this);
+
+    this.removeFromPbxFileReferenceSection(file);    // PBXFileReference
+    this.removeFromPluginsPbxGroup(file);            // PBXGroup
+
+    return file;
+}
+
+pbxProject.prototype.addProductFile = function(targetPath, opt) {
+    var file = new pbxFile(targetPath, opt);
+
+    file.includeInIndex = 0;
+    file.fileRef = this.generateUuid();
+    file.target = opt ? opt.target : undefined;
+    file.group = opt ? opt.group : undefined;
+    file.uuid = this.generateUuid();
+    file.path = file.basename;
+
+    this.addToPbxFileReferenceSection(file);
+    this.addToProductsPbxGroup(file);                // PBXGroup
+
+    return file;
+}
+
+pbxProject.prototype.removeProductFile = function(path, opt) {
+    var file = new pbxFile(path, opt);
+
+    this.removeFromProductsPbxGroup(file);           // PBXGroup
+
+    return file;
+}
+
+/**
+ *
+ * @param path {String}
+ * @param opt {Object} see pbxFile for avail options
+ * @param group {String} group key
+ * @returns {Object} file; see pbxFile
+ */
+pbxProject.prototype.addSourceFile = function (path, opt, group) {
+    var file;
+    if (group) {
+        file = this.addFile(path, group, opt);
+    }
+    else {
+        file = this.addPluginFile(path, opt);
+    }
+
+    if (!file) return false;
+
+    file.target = opt ? opt.target : undefined;
+    file.uuid = this.generateUuid();
+
+    this.addToPbxBuildFileSection(file);        // PBXBuildFile
+    this.addToPbxSourcesBuildPhase(file);       // PBXSourcesBuildPhase
+
+    return file;
+}
+
+/**
+ *
+ * @param path {String}
+ * @param opt {Object} see pbxFile for avail options
+ * @param group {String} group key
+ * @returns {Object} file; see pbxFile
+ */
+pbxProject.prototype.removeSourceFile = function (path, opt, group) {
+    var file;
+    if (group) {
+        file = this.removeFile(path, group, opt);
+    }
+    else {
+        file = this.removePluginFile(path, opt);
+    }
+    file.target = opt ? opt.target : undefined;
+    this.removeFromPbxBuildFileSection(file);        // PBXBuildFile
+    this.removeFromPbxSourcesBuildPhase(file);       // PBXSourcesBuildPhase
+
+    return file;
+}
+
+/**
+ *
+ * @param path {String}
+ * @param opt {Object} see pbxFile for avail options
+ * @param group {String} group key
+ * @returns {Object} file; see pbxFile
+ */
+pbxProject.prototype.addHeaderFile = function (path, opt, group) {
+    if (group) {
+        return this.addFile(path, group, opt);
+    }
+    else {
+        return this.addPluginFile(path, opt);
+    }
+}
+
+/**
+ *
+ * @param path {String}
+ * @param opt {Object} see pbxFile for avail options
+ * @param group {String} group key
+ * @returns {Object} file; see pbxFile
+ */
+pbxProject.prototype.removeHeaderFile = function (path, opt, group) {
+    if (group) {
+        return this.removeFile(path, group, opt);
+    }
+    else {
+        return this.removePluginFile(path, opt);
+    }
+}
+
+pbxProject.prototype.addResourceFile = function(path, opt) {
+    opt = opt || {};
+
+    var file;
+
+    if (opt.plugin) {
+        file = this.addPluginFile(path, opt);
+        if (!file) return false;
+    } else {
+        file = new pbxFile(path, opt);
+        if (this.hasFile(file.path)) return false;
+    }
+
+    file.uuid = this.generateUuid();
+    file.target = opt ? opt.target : undefined;
+
+    if (!opt.plugin) {
+        correctForResourcesPath(file, this);
+        file.fileRef = this.generateUuid();
+    }
+
+    this.addToPbxBuildFileSection(file);        // PBXBuildFile
+    this.addToPbxResourcesBuildPhase(file);     // PBXResourcesBuildPhase
+
+    if (!opt.plugin) {
+        this.addToPbxFileReferenceSection(file);    // PBXFileReference
+        this.addToResourcesPbxGroup(file);          // PBXGroup
+    }
+
+    return file;
+}
+
+pbxProject.prototype.removeResourceFile = function(path, opt) {
+    var file = new pbxFile(path, opt);
+    file.target = opt ? opt.target : undefined;
+
+    correctForResourcesPath(file, this);
+
+    this.removeFromPbxBuildFileSection(file);        // PBXBuildFile
+    this.removeFromPbxFileReferenceSection(file);    // PBXFileReference
+    this.removeFromResourcesPbxGroup(file);          // PBXGroup
+    this.removeFromPbxResourcesBuildPhase(file);     // PBXResourcesBuildPhase
+
+    return file;
+}
+
+pbxProject.prototype.addFramework = function(fpath, opt) {
+
+    var file = new pbxFile(fpath, opt);
+
+    file.uuid = this.generateUuid();
+    file.fileRef = this.generateUuid();
+    file.target = opt ? opt.target : undefined;
+
+    if (this.hasFile(file.path)) return false;
+
+    this.addToPbxBuildFileSection(file);        // PBXBuildFile
+    this.addToPbxFileReferenceSection(file);    // PBXFileReference
+    this.addToFrameworksPbxGroup(file);         // PBXGroup
+    this.addToPbxFrameworksBuildPhase(file);    // PBXFrameworksBuildPhase
+
+    if (opt && opt.customFramework == true) {
+        this.addToFrameworkSearchPaths(file);
+    }
+
+    return file;
+}
+
+pbxProject.prototype.removeFramework = function(fpath, opt) {
+    var file = new pbxFile(fpath, opt);
+    file.target = opt ? opt.target : undefined;
+
+    this.removeFromPbxBuildFileSection(file);        // PBXBuildFile
+    this.removeFromPbxFileReferenceSection(file);    // PBXFileReference
+    this.removeFromFrameworksPbxGroup(file);         // PBXGroup
+    this.removeFromPbxFrameworksBuildPhase(file);    // PBXFrameworksBuildPhase
+
+    if (opt && opt.customFramework) {
+        this.removeFromFrameworkSearchPaths(path.dirname(fpath));
+    }
+
+    return file;
+}
+
+
+pbxProject.prototype.addCopyfile = function(fpath, opt) {
+    var file = new pbxFile(fpath, opt);
+
+    // catch duplicates
+    if (this.hasFile(file.path)) {
+        file = this.hasFile(file.path);
+    }
+
+    file.fileRef = file.uuid = this.generateUuid();
+    file.target = opt ? opt.target : undefined;
+
+    this.addToPbxBuildFileSection(file);        // PBXBuildFile
+    this.addToPbxFileReferenceSection(file);    // PBXFileReference
+    this.addToPbxCopyfilesBuildPhase(file);     // PBXCopyFilesBuildPhase
+
+    return file;
+}
+
+pbxProject.prototype.pbxCopyfilesBuildPhaseObj = function(target) {
+    return this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Copy Files', target);
+}
+
+pbxProject.prototype.addToPbxCopyfilesBuildPhase = function(file) {
+    var sources = this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Copy Files', file.target);
+    sources.files.push(pbxBuildPhaseObj(file));
+}
+
+pbxProject.prototype.removeCopyfile = function(fpath, opt) {
+    var file = new pbxFile(fpath, opt);
+    file.target = opt ? opt.target : undefined;
+
+    this.removeFromPbxBuildFileSection(file);        // PBXBuildFile
+    this.removeFromPbxFileReferenceSection(file);    // PBXFileReference
+    this.removeFromPbxCopyfilesBuildPhase(file);    // PBXFrameworksBuildPhase
+
+    return file;
+}
+
+pbxProject.prototype.removeFromPbxCopyfilesBuildPhase = function(file) {
+    var sources = this.pbxCopyfilesBuildPhaseObj(file.target);
+    for (i in sources.files) {
+        if (sources.files[i].comment == longComment(file)) {
+            sources.files.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addStaticLibrary = function(path, opt) {
+    opt = opt || {};
+
+    var file;
+
+    if (opt.plugin) {
+        file = this.addPluginFile(path, opt);
+        if (!file) return false;
+    } else {
+        file = new pbxFile(path, opt);
+        if (this.hasFile(file.path)) return false;
+    }
+
+    file.uuid = this.generateUuid();
+    file.target = opt ? opt.target : undefined;
+
+    if (!opt.plugin) {
+        file.fileRef = this.generateUuid();
+        this.addToPbxFileReferenceSection(file);    // PBXFileReference
+    }
+
+    this.addToPbxBuildFileSection(file);        // PBXBuildFile
+    this.addToPbxFrameworksBuildPhase(file);    // PBXFrameworksBuildPhase
+    this.addToLibrarySearchPaths(file);        // make sure it gets built!
+
+    return file;
+}
+
+// helper addition functions
+pbxProject.prototype.addToPbxBuildFileSection = function(file) {
+    var commentKey = f("%s_comment", file.uuid);
+
+    this.pbxBuildFileSection()[file.uuid] = pbxBuildFileObj(file);
+    this.pbxBuildFileSection()[commentKey] = pbxBuildFileComment(file);
+}
+
+pbxProject.prototype.removeFromPbxBuildFileSection = function(file) {
+    var uuid;
+
+    for (uuid in this.pbxBuildFileSection()) {
+        if (this.pbxBuildFileSection()[uuid].fileRef_comment == file.basename) {
+            file.uuid = uuid;
+            delete this.pbxBuildFileSection()[uuid];
+        }
+    }
+    var commentKey = f("%s_comment", file.uuid);
+    delete this.pbxBuildFileSection()[commentKey];
+}
+
+pbxProject.prototype.addPbxGroup = function(filePathsArray, name, path, sourceTree) {
+    var groups = this.hash.project.objects['PBXGroup'],
+        pbxGroupUuid = this.generateUuid(),
+        commentKey = f("%s_comment", pbxGroupUuid),
+        pbxGroup = {
+            isa: 'PBXGroup',
+            children: [],
+            name: name,
+            path: path,
+            sourceTree: sourceTree ? sourceTree : '"<group>"'
+        },
+        fileReferenceSection = this.pbxFileReferenceSection(),
+        filePathToReference = {};
+
+    for (var key in fileReferenceSection) {
+        // only look for comments
+        if (!COMMENT_KEY.test(key)) continue;
+
+        var fileReferenceKey = key.split(COMMENT_KEY)[0],
+            fileReference = fileReferenceSection[fileReferenceKey];
+
+        filePathToReference[fileReference.path] = { fileRef: fileReferenceKey, basename: fileReferenceSection[key] };
+    }
+
+    for (var index = 0; index < filePathsArray.length; index++) {
+        var filePath = filePathsArray[index],
+            filePathQuoted = "\"" + filePath + "\"";
+        if (filePathToReference[filePath]) {
+            pbxGroup.children.push(pbxGroupChild(filePathToReference[filePath]));
+            continue;
+        } else if (filePathToReference[filePathQuoted]) {
+            pbxGroup.children.push(pbxGroupChild(filePathToReference[filePathQuoted]));
+            continue;
+        }
+
+        var file = new pbxFile(filePath);
+        file.uuid = this.generateUuid();
+        file.fileRef = this.generateUuid();
+        this.addToPbxFileReferenceSection(file);    // PBXFileReference
+        this.addToPbxBuildFileSection(file);        // PBXBuildFile
+        pbxGroup.children.push(pbxGroupChild(file));
+    }
+
+    if (groups) {
+        groups[pbxGroupUuid] = pbxGroup;
+        groups[commentKey] = name;
+    }
+
+    return { uuid: pbxGroupUuid, pbxGroup: pbxGroup };
+}
+
+pbxProject.prototype.addToPbxProjectSection = function(target) {
+
+    var newTarget = {
+            value: target.uuid,
+            comment: pbxNativeTargetComment(target.pbxNativeTarget)
+        };
+
+    this.pbxProjectSection()[this.getFirstProject()['uuid']]['targets'].push(newTarget);
+}
+
+pbxProject.prototype.addToPbxNativeTargetSection = function(target) {
+    var commentKey = f("%s_comment", target.uuid);
+
+    this.pbxNativeTargetSection()[target.uuid] = target.pbxNativeTarget;
+    this.pbxNativeTargetSection()[commentKey] = target.pbxNativeTarget.name;
+}
+
+pbxProject.prototype.addToPbxFileReferenceSection = function(file) {
+    var commentKey = f("%s_comment", file.fileRef);
+
+    this.pbxFileReferenceSection()[file.fileRef] = pbxFileReferenceObj(file);
+    this.pbxFileReferenceSection()[commentKey] = pbxFileReferenceComment(file);
+}
+
+pbxProject.prototype.removeFromPbxFileReferenceSection = function(file) {
+
+    var i;
+    var refObj = pbxFileReferenceObj(file);
+    for (i in this.pbxFileReferenceSection()) {
+        if (this.pbxFileReferenceSection()[i].name == refObj.name ||
+            ('"' + this.pbxFileReferenceSection()[i].name + '"') == refObj.name ||
+            this.pbxFileReferenceSection()[i].path == refObj.path ||
+            ('"' + this.pbxFileReferenceSection()[i].path + '"') == refObj.path) {
+            file.fileRef = file.uuid = i;
+            delete this.pbxFileReferenceSection()[i];
+            break;
+        }
+    }
+    var commentKey = f("%s_comment", file.fileRef);
+    if (this.pbxFileReferenceSection()[commentKey] != undefined) {
+        delete this.pbxFileReferenceSection()[commentKey];
+    }
+
+    return file;
+}
+
+pbxProject.prototype.addToPluginsPbxGroup = function(file) {
+    var pluginsGroup = this.pbxGroupByName('Plugins');
+    pluginsGroup.children.push(pbxGroupChild(file));
+}
+
+pbxProject.prototype.removeFromPluginsPbxGroup = function(file) {
+    var pluginsGroupChildren = this.pbxGroupByName('Plugins').children, i;
+    for (i in pluginsGroupChildren) {
+        if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
+            pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) {
+            pluginsGroupChildren.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addToResourcesPbxGroup = function(file) {
+    var pluginsGroup = this.pbxGroupByName('Resources');
+    pluginsGroup.children.push(pbxGroupChild(file));
+}
+
+pbxProject.prototype.removeFromResourcesPbxGroup = function(file) {
+    var pluginsGroupChildren = this.pbxGroupByName('Resources').children, i;
+    for (i in pluginsGroupChildren) {
+        if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
+            pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) {
+            pluginsGroupChildren.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addToFrameworksPbxGroup = function(file) {
+    var pluginsGroup = this.pbxGroupByName('Frameworks');
+    pluginsGroup.children.push(pbxGroupChild(file));
+}
+
+pbxProject.prototype.removeFromFrameworksPbxGroup = function(file) {
+    var pluginsGroupChildren = this.pbxGroupByName('Frameworks').children;
+
+    for (i in pluginsGroupChildren) {
+        if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
+            pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) {
+            pluginsGroupChildren.splice(i, 1);
+            break;
+        }
+    }
+}
+
+
+pbxProject.prototype.addToProductsPbxGroup = function(file) {
+    var productsGroup = this.pbxGroupByName('Products');
+    productsGroup.children.push(pbxGroupChild(file));
+}
+
+pbxProject.prototype.removeFromProductsPbxGroup = function(file) {
+    var productsGroupChildren = this.pbxGroupByName('Products').children, i;
+    for (i in productsGroupChildren) {
+        if (pbxGroupChild(file).value == productsGroupChildren[i].value &&
+            pbxGroupChild(file).comment == productsGroupChildren[i].comment) {
+            productsGroupChildren.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addToPbxSourcesBuildPhase = function(file) {
+    var sources = this.pbxSourcesBuildPhaseObj(file.target);
+    sources.files.push(pbxBuildPhaseObj(file));
+}
+
+pbxProject.prototype.removeFromPbxSourcesBuildPhase = function(file) {
+
+    var sources = this.pbxSourcesBuildPhaseObj(file.target), i;
+    for (i in sources.files) {
+        if (sources.files[i].comment == longComment(file)) {
+            sources.files.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addToPbxResourcesBuildPhase = function(file) {
+    var sources = this.pbxResourcesBuildPhaseObj(file.target);
+    sources.files.push(pbxBuildPhaseObj(file));
+}
+
+pbxProject.prototype.removeFromPbxResourcesBuildPhase = function(file) {
+    var sources = this.pbxResourcesBuildPhaseObj(file.target), i;
+
+    for (i in sources.files) {
+        if (sources.files[i].comment == longComment(file)) {
+            sources.files.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addToPbxFrameworksBuildPhase = function(file) {
+    var sources = this.pbxFrameworksBuildPhaseObj(file.target);
+    sources.files.push(pbxBuildPhaseObj(file));
+}
+
+pbxProject.prototype.removeFromPbxFrameworksBuildPhase = function(file) {
+    var sources = this.pbxFrameworksBuildPhaseObj(file.target);
+    for (i in sources.files) {
+        if (sources.files[i].comment == longComment(file)) {
+            sources.files.splice(i, 1);
+            break;
+        }
+    }
+}
+
+pbxProject.prototype.addXCConfigurationList = function(configurationObjectsArray, defaultConfigurationName, comment) {
+    var pbxBuildConfigurationSection = this.pbxXCBuildConfigurationSection(),
+        pbxXCConfigurationListSection = this.pbxXCConfigurationList(),
+        xcConfigurationListUuid = this.generateUuid(),
+        commentKey = f("%s_comment", xcConfigurationListUuid),
+        xcConfigurationList = {
+            isa: 'XCConfigurationList',
+            buildConfigurations: [],
+            defaultConfigurationIsVisible: 0,
+            defaultConfigurationName: defaultConfigurationName
+        };
+
+    for (var index = 0; index < configurationObjectsArray.length; index++) {
+        var configuration = configurationObjectsArray[index],
+            configurationUuid = this.generateUuid(),
+            configurationCommentKey = f("%s_comment", configurationUuid);
+
+        pbxBuildConfigurationSection[configurationUuid] = configuration;
+        pbxBuildConfigurationSection[configurationCommentKey] = configuration.name;
+        xcConfigurationList.buildConfigurations.push({ value: configurationUuid, comment: configuration.name });
+    }
+
+    if (pbxXCConfigurationListSection) {
+        pbxXCConfigurationListSection[xcConfigurationListUuid] = xcConfigurationList;
+        pbxXCConfigurationListSection[commentKey] = comment;
+    }
+
+    return { uuid: xcConfigurationListUuid, xcConfigurationList: xcConfigurationList };
+}
+
+pbxProject.prototype.addTargetDependency = function(target, dependencyTargets) {
+    if (!target)
+        return undefined;
+
+    var nativeTargets = this.pbxNativeTargetSection();
+
+    if (typeof nativeTargets[target] == "undefined")
+        throw new Error("Invalid target: " + target);
+
+    for (var index = 0; index < dependencyTargets.length; index++) {
+        var dependencyTarget = dependencyTargets[index];
+        if (typeof nativeTargets[dependencyTarget] == "undefined")
+            throw new Error("Invalid target: " + dependencyTarget);
+        }
+
+    var pbxTargetDependency = 'PBXTargetDependency',
+        pbxContainerItemProxy = 'PBXContainerItemProxy',
+        pbxTargetDependencySection = this.hash.project.objects[pbxTargetDependency],
+        pbxContainerItemProxySection = this.hash.project.objects[pbxContainerItemProxy];
+
+    for (var index = 0; index < dependencyTargets.length; index++) {
+        var dependencyTargetUuid = dependencyTargets[index],
+            dependencyTargetCommentKey = f("%s_comment", dependencyTargetUuid),
+            targetDependencyUuid = this.generateUuid(),
+            targetDependencyCommentKey = f("%s_comment", targetDependencyUuid),
+            itemProxyUuid = this.generateUuid(),
+            itemProxyCommentKey = f("%s_comment", itemProxyUuid),
+            itemProxy = {
+                isa: pbxContainerItemProxy,
+                containerPortal: this.hash.project['rootObject'],
+                containerPortal_comment: this.hash.project['rootObject_comment'],
+                proxyType: 1,
+                remoteGlobalIDString: dependencyTargetUuid,
+                remoteInfo: nativeTargets[dependencyTargetUuid].name
+            },
+            targetDependency = {
+                isa: pbxTargetDependency,
+                target: dependencyTargetUuid,
+                target_comment: nativeTargets[dependencyTargetCommentKey],
+                targetProxy: itemProxyUuid,
+                targetProxy_comment: pbxContainerItemProxy
+            };
+
+        if (pbxContainerItemProxySection && pbxTargetDependencySection) {
+            pbxContainerItemProxySection[itemProxyUuid] = itemProxy;
+            pbxContainerItemProxySection[itemProxyCommentKey] = pbxContainerItemProxy;
+            pbxTargetDependencySection[targetDependencyUuid] = targetDependency;
+            pbxTargetDependencySection[targetDependencyCommentKey] = pbxTargetDependency;
+            nativeTargets[target].dependencies.push({ value: targetDependencyUuid, comment: pbxTargetDependency })
+        }
+    }
+
+    return { uuid: target, target: nativeTargets[target] };
+}
+
+pbxProject.prototype.addBuildPhase = function(filePathsArray, buildPhaseType, comment, target, folderType, subfolderPath) {
+    var buildPhaseSection,
+        fileReferenceSection = this.pbxFileReferenceSection(),
+        buildFileSection = this.pbxBuildFileSection(),
+        buildPhaseUuid = this.generateUuid(),
+        buildPhaseTargetUuid = target || this.getFirstTarget().uuid,
+        commentKey = f("%s_comment", buildPhaseUuid),
+        buildPhase = {
+            isa: buildPhaseType,
+            buildActionMask: 2147483647,
+            files: [],
+            runOnlyForDeploymentPostprocessing: 0
+        },
+        filePathToBuildFile = {};
+
+    if (buildPhaseType === 'PBXCopyFilesBuildPhase') {
+        buildPhase = pbxCopyFilesBuildPhaseObj(buildPhase, folderType, subfolderPath, comment);
+    }
+
+    if (!this.hash.project.objects[buildPhaseType]) {
+        this.hash.project.objects[buildPhaseType] = new Object();
+    }
+
+    if (!this.hash.project.objects[buildPhaseType][buildPhaseUuid]) {
+        this.hash.project.objects[buildPhaseType][buildPhaseUuid] = buildPhase;
+        this.hash.project.objects[buildPhaseType][commentKey] = comment;
+    }
+
+    if (this.hash.project.objects['PBXNativeTarget'][buildPhaseTargetUuid]['buildPhases']) {
+        this.hash.project.objects['PBXNativeTarget'][buildPhaseTargetUuid]['buildPhases'].push({
+            value: buildPhaseUuid,
+            comment: comment
+        })
+
+    }
+
+
+    for (var key in buildFileSection) {
+        // only look for comments
+        if (!COMMENT_KEY.test(key)) continue;
+
+        var buildFileKey = key.split(COMMENT_KEY)[0],
+            buildFile = buildFileSection[buildFileKey];
+        fileReference = fileReferenceSection[buildFile.fileRef];
+
+        if (!fileReference) continue;
+
+        var pbxFileObj = new pbxFile(fileReference.path);
+
+        filePathToBuildFile[fileReference.path] = { uuid: buildFileKey, basename: pbxFileObj.basename, group: pbxFileObj.group };
+    }
+
+    for (var index = 0; index < filePathsArray.length; index++) {
+        var filePath = filePathsArray[index],
+            filePathQuoted = "\"" + filePath + "\"",
+            file = new pbxFile(filePath);
+
+        if (filePathToBuildFile[filePath]) {
+            buildPhase.files.push(pbxBuildPhaseObj(filePathToBuildFile[filePath]));
+            continue;
+        } else if (filePathToBuildFile[filePathQuoted]) {
+            buildPhase.files.push(pbxBuildPhaseObj(filePathToBuildFile[filePathQuoted]));
+            continue;
+        }
+
+        file.uuid = this.generateUuid();
+        file.fileRef = this.generateUuid();
+        this.addToPbxFileReferenceSection(file);    // PBXFileReference
+        this.addToPbxBuildFileSection(file);        // PBXBuildFile
+        buildPhase.files.push(pbxBuildPhaseObj(file));
+    }
+
+    if (buildPhaseSection) {
+        buildPhaseSection[buildPhaseUuid] = buildPhase;
+        buildPhaseSection[commentKey] = comment;
+    }
+
+    return { uuid: buildPhaseUuid, buildPhase: buildPhase };
+}
+
+// helper access functions
+pbxProject.prototype.pbxProjectSection = function() {
+    return this.hash.project.objects['PBXProject'];
+}
+pbxProject.prototype.pbxBuildFileSection = function() {
+    return this.hash.project.objects['PBXBuildFile'];
+}
+
+pbxProject.prototype.pbxXCBuildConfigurationSection = function() {
+    return this.hash.project.objects['XCBuildConfiguration'];
+}
+
+pbxProject.prototype.pbxFileReferenceSection = function() {
+    return this.hash.project.objects['PBXFileReference'];
+}
+
+pbxProject.prototype.pbxNativeTargetSection = function() {
+    return this.hash.project.objects['PBXNativeTarget'];
+}
+
+pbxProject.prototype.pbxXCConfigurationList = function() {
+    return this.hash.project.objects['XCConfigurationList'];
+}
+
+pbxProject.prototype.pbxGroupByName = function(name) {
+    var groups = this.hash.project.objects['PBXGroup'],
+        key, groupKey;
+
+    for (key in groups) {
+        // only look for comments
+        if (!COMMENT_KEY.test(key)) continue;
+
+        if (groups[key] == name) {
+            groupKey = key.split(COMMENT_KEY)[0];
+            return groups[groupKey];
+        }
+    }
+
+    return null;
+}
+
+pbxProject.prototype.pbxTargetByName = function(name) {
+    return this.pbxItemByComment(name, 'PBXNativeTarget');
+}
+
+pbxProject.prototype.pbxItemByComment = function(name, pbxSectionName) {
+    var section = this.hash.project.objects[pbxSectionName],
+        key, itemKey;
+
+    for (key in section) {
+        // only look for comments
+        if (!COMMENT_KEY.test(key)) continue;
+
+        if (section[key] == name) {
+            itemKey = key.split(COMMENT_KEY)[0];
+            return section[itemKey];
+        }
+    }
+
+    return null;
+}
+
+pbxProject.prototype.pbxSourcesBuildPhaseObj = function(target) {
+    return this.buildPhaseObject('PBXSourcesBuildPhase', 'Sources', target);
+}
+
+pbxProject.prototype.pbxResourcesBuildPhaseObj = function(target) {
+    return this.buildPhaseObject('PBXResourcesBuildPhase', 'Resources', target);
+}
+
+pbxProject.prototype.pbxFrameworksBuildPhaseObj = function(target) {
+    return this.buildPhaseObject('PBXFrameworksBuildPhase', 'Frameworks', target);
+}
+
+// Find Build Phase from group/target
+pbxProject.prototype.buildPhase = function(group, target) {
+
+    if (!target)
+        return undefined;
+
+    var nativeTargets = this.pbxNativeTargetSection();
+     if (typeof nativeTargets[target] == "undefined")
+        throw new Error("Invalid target: " + target);
+
+    var nativeTarget = nativeTargets[target];
+    var buildPhases = nativeTarget.buildPhases;
+     for(var i in buildPhases)
+     {
+        var buildPhase = buildPhases[i];
+        if (buildPhase.comment==group)
+            return buildPhase.value + "_comment";
+        }
+    }
+
+pbxProject.prototype.buildPhaseObject = function(name, group, target) {
+    var section = this.hash.project.objects[name],
+        obj, sectionKey, key;
+    var buildPhase = this.buildPhase(group, target);
+
+    for (key in section) {
+
+        // only look for comments
+        if (!COMMENT_KEY.test(key)) continue;
+
+        // select the proper buildPhase
+        if (buildPhase && buildPhase!=key)
+            continue;
+        if (section[key] == group) {
+            sectionKey = key.split(COMMENT_KEY)[0];
+            return section[sectionKey];
+        }
+    }
+    return null;
+}
+
+pbxProject.prototype.addBuildProperty = function(prop, value, build_name) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        key, configuration;
+
+    for (key in configurations){
+        configuration = configurations[key];
+        if (!build_name || configuration.name === build_name){
+            configuration.buildSettings[prop] = value;
+        }
+    }
+}
+
+pbxProject.prototype.removeBuildProperty = function(prop, build_name) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        key, configuration;
+
+    for (key in configurations){
+        configuration = configurations[key];
+        if (configuration.buildSettings[prop] &&
+            !build_name || configuration.name === build_name){
+            delete configuration.buildSettings[prop];
+        }
+    }
+}
+
+/**
+ *
+ * @param prop {String}
+ * @param value {String|Array|Object|Number|Boolean}
+ * @param build {String} Release or Debug
+ */
+pbxProject.prototype.updateBuildProperty = function(prop, value, build) {
+    var configs = this.pbxXCBuildConfigurationSection();
+    for (var configName in configs) {
+        if (!COMMENT_KEY.test(configName)) {
+            var config = configs[configName];
+            if ( (build && config.name === build) || (!build) ) {
+                config.buildSettings[prop] = value;
+            }
+        }
+    }
+}
+
+pbxProject.prototype.updateProductName = function(name) {
+    this.updateBuildProperty('PRODUCT_NAME', '"' + name + '"');
+}
+
+pbxProject.prototype.removeFromFrameworkSearchPaths = function(file) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        INHERITED = '"$(inherited)"',
+        SEARCH_PATHS = 'FRAMEWORK_SEARCH_PATHS',
+        config, buildSettings, searchPaths;
+    var new_path = searchPathForFile(file, this);
+
+    for (config in configurations) {
+        buildSettings = configurations[config].buildSettings;
+
+        if (unquote(buildSettings['PRODUCT_NAME']) != this.productName)
+            continue;
+
+        searchPaths = buildSettings[SEARCH_PATHS];
+
+        if (searchPaths) {
+            var matches = searchPaths.filter(function(p) {
+                return p.indexOf(new_path) > -1;
+            });
+            matches.forEach(function(m) {
+                var idx = searchPaths.indexOf(m);
+                searchPaths.splice(idx, 1);
+            });
+        }
+
+    }
+}
+
+pbxProject.prototype.addToFrameworkSearchPaths = function(file) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        INHERITED = '"$(inherited)"',
+        config, buildSettings, searchPaths;
+
+    for (config in configurations) {
+        buildSettings = configurations[config].buildSettings;
+
+        if (unquote(buildSettings['PRODUCT_NAME']) != this.productName)
+            continue;
+
+        if (!buildSettings['FRAMEWORK_SEARCH_PATHS']
+            || buildSettings['FRAMEWORK_SEARCH_PATHS'] === INHERITED) {
+            buildSettings['FRAMEWORK_SEARCH_PATHS'] = [INHERITED];
+        }
+
+        buildSettings['FRAMEWORK_SEARCH_PATHS'].push(searchPathForFile(file, this));
+    }
+}
+
+pbxProject.prototype.removeFromLibrarySearchPaths = function(file) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        INHERITED = '"$(inherited)"',
+        SEARCH_PATHS = 'LIBRARY_SEARCH_PATHS',
+        config, buildSettings, searchPaths;
+    var new_path = searchPathForFile(file, this);
+
+    for (config in configurations) {
+        buildSettings = configurations[config].buildSettings;
+
+        if (unquote(buildSettings['PRODUCT_NAME']) != this.productName)
+            continue;
+
+        searchPaths = buildSettings[SEARCH_PATHS];
+
+        if (searchPaths) {
+            var matches = searchPaths.filter(function(p) {
+                return p.indexOf(new_path) > -1;
+            });
+            matches.forEach(function(m) {
+                var idx = searchPaths.indexOf(m);
+                searchPaths.splice(idx, 1);
+            });
+        }
+
+    }
+}
+
+pbxProject.prototype.addToLibrarySearchPaths = function(file) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        INHERITED = '"$(inherited)"',
+        config, buildSettings, searchPaths;
+
+    for (config in configurations) {
+        buildSettings = configurations[config].buildSettings;
+
+        if (unquote(buildSettings['PRODUCT_NAME']) != this.productName)
+            continue;
+
+        if (!buildSettings['LIBRARY_SEARCH_PATHS']
+            || buildSettings['LIBRARY_SEARCH_PATHS'] === INHERITED) {
+            buildSettings['LIBRARY_SEARCH_PATHS'] = [INHERITED];
+        }
+
+        if (typeof file === 'string') {
+            buildSettings['LIBRARY_SEARCH_PATHS'].push(file);
+        } else {
+            buildSettings['LIBRARY_SEARCH_PATHS'].push(searchPathForFile(file, this));
+        }
+    }
+}
+
+pbxProject.prototype.removeFromHeaderSearchPaths = function(file) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        INHERITED = '"$(inherited)"',
+        SEARCH_PATHS = 'HEADER_SEARCH_PATHS',
+        config, buildSettings, searchPaths;
+    var new_path = searchPathForFile(file, this);
+
+    for (config in configurations) {
+        buildSettings = configurations[config].buildSettings;
+
+        if (unquote(buildSettings['PRODUCT_NAME']) != this.productName)
+            continue;
+
+        if (buildSettings[SEARCH_PATHS]) {
+            var matches = buildSettings[SEARCH_PATHS].filter(function(p) {
+                return p.indexOf(new_path) > -1;
+            });
+            matches.forEach(function(m) {
+                var idx = buildSettings[SEARCH_PATHS].indexOf(m);
+                buildSettings[SEARCH_PATHS].splice(idx, 1);
+            });
+        }
+
+    }
+}
+pbxProject.prototype.addToHeaderSearchPaths = function(file) {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        INHERITED = '"$(inherited)"',
+        config, buildSettings, searchPaths;
+
+    for (config in configurations) {
+        buildSettings = configurations[config].buildSettings;
+
+        if (unquote(buildSettings['PRODUCT_NAME']) != this.productName)
+            continue;
+
+        if (!buildSettings['HEADER_SEARCH_PATHS']) {
+            buildSettings['HEADER_SEARCH_PATHS'] = [INHERITED];
+        }
+
+        if (typeof file === 'string') {
+            buildSettings['HEADER_SEARCH_PATHS'].push(file);
+        } else {
+            buildSettings['HEADER_SEARCH_PATHS'].push(searchPathForFile(file, this));
+        }
+    }
+}
+// a JS getter. hmmm
+pbxProject.prototype.__defineGetter__("productName", function() {
+    var configurations = nonComments(this.pbxXCBuildConfigurationSection()),
+        config, productName;
+
+    for (config in configurations) {
+        productName = configurations[config].buildSettings['PRODUCT_NAME'];
+
+        if (productName) {
+            return unquote(productName);
+        }
+    }
+});
+
+// check if file is present
+pbxProject.prototype.hasFile = function(filePath) {
+    var files = nonComments(this.pbxFileReferenceSection()),
+        file, id;
+    for (id in files) {
+        file = files[id];
+        if (file.path == filePath || file.path == ('"' + filePath + '"')) {
+            return file;
+        }
+    }
+
+    return false;
+}
+
+pbxProject.prototype.addTarget = function(name, type, subfolder) {
+
+    // Setup uuid and name of new target
+    var targetUuid = this.generateUuid(),
+        targetType = type,
+        targetSubfolder = subfolder || name,
+        targetName = name.trim();
+        
+    // Check type against list of allowed target types
+    if (!targetName) {
+        throw new Error("Target name missing.");
+    }    
+
+    // Check type against list of allowed target types
+    if (!targetType) {
+        throw new Error("Target type missing.");
+    } 
+
+    // Check type against list of allowed target types
+    if (!producttypeForTargettype(targetType)) {
+        throw new Error("Target type invalid: " + targetType);
+    }
+    
+    // Build Configuration: Create
+    var buildConfigurationsList = [
+        {
+            name: 'Debug',
+            isa: 'XCBuildConfiguration',
+            buildSettings: {
+                GCC_PREPROCESSOR_DEFINITIONS: ['"DEBUG=1"', '"$(inherited)"'],
+                INFOPLIST_FILE: '"' + path.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'),
+                LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"',
+                PRODUCT_NAME: '"' + targetName + '"',
+                SKIP_INSTALL: 'YES'
+            }
+        },
+        {
+            name: 'Release',
+            isa: 'XCBuildConfiguration',
+            buildSettings: {
+                INFOPLIST_FILE: '"' + path.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'),
+                LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"',
+                PRODUCT_NAME: '"' + targetName + '"',
+                SKIP_INSTALL: 'YES'
+            }
+        }
+    ];
+
+    // Build Configuration: Add
+    var buildConfigurations = this.addXCConfigurationList(buildConfigurationsList, 'Release', 'Build configuration list for PBXNativeTarget "' + targetName +'"');
+
+    // Product: Create
+    var productName = targetName,
+        productType = producttypeForTargettype(targetType),
+        productFileType = filetypeForProducttype(productType),
+        productFile = this.addProductFile(productName, { group: 'Copy Files', 'target': targetUuid, 'explicitFileType': productFileType}),
+        productFileName = productFile.basename;
+
+
+    // Product: Add to build file list
+    this.addToPbxBuildFileSection(productFile);
+
+    // Target: Create
+    var target = {
+            uuid: targetUuid,
+            pbxNativeTarget: {
+                isa: 'PBXNativeTarget',
+                name: '"' + targetName + '"',
+                productName: '"' + targetName + '"',
+                productReference: productFile.fileRef,
+                productType: '"' + producttypeForTargettype(targetType) + '"',
+                buildConfigurationList: buildConfigurations.uuid,
+                buildPhases: [],
+                buildRules: [],
+                dependencies: []
+            }
+    };
+
+    // Target: Add to PBXNativeTarget section
+    this.addToPbxNativeTargetSection(target)
+
+    // Product: Embed (only for "extension"-type targets)
+    if (targetType === 'app_extension') {
+
+        // Create CopyFiles phase in first target
+        this.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Copy Files', this.getFirstTarget().uuid,  targetType)
+
+        // Add product to CopyFiles phase
+        this.addToPbxCopyfilesBuildPhase(productFile)
+
+       // this.addBuildPhaseToTarget(newPhase.buildPhase, this.getFirstTarget().uuid)
+
+    };
+
+    // Target: Add uuid to root project
+    this.addToPbxProjectSection(target);
+
+    // Target: Add dependency for this target to first (main) target
+    this.addTargetDependency(this.getFirstTarget().uuid, [target.uuid]);
+
+
+    // Return target on success
+    return target;
+
+};
+
+// helper recursive prop search+replace
+function propReplace(obj, prop, value) {
+    var o = {};
+    for (var p in obj) {
+        if (o.hasOwnProperty.call(obj, p)) {
+            if (typeof obj[p] == 'object' && !Array.isArray(obj[p])) {
+                propReplace(obj[p], prop, value);
+            } else if (p == prop) {
+                obj[p] = value;
+            }
+        }
+    }
+}
+
+// helper object creation functions
+function pbxBuildFileObj(file) {
+    var obj = Object.create(null);
+
+    obj.isa = 'PBXBuildFile';
+    obj.fileRef = file.fileRef;
+    obj.fileRef_comment = file.basename;
+    if (file.settings) obj.settings = file.settings;
+
+    return obj;
+}
+
+function pbxFileReferenceObj(file) {
+    var fileObject = {
+        isa: "PBXFileReference",
+        name: "\"" + file.basename + "\"",
+        path: "\"" + file.path.replace(/\\/g, '/') + "\"",
+        sourceTree: file.sourceTree,
+        fileEncoding: file.fileEncoding,
+        lastKnownFileType: file.lastKnownFileType,
+        explicitFileType: file.explicitFileType,
+        includeInIndex: file.includeInIndex
+    };
+
+    return fileObject;
+}
+
+function pbxGroupChild(file) {
+    var obj = Object.create(null);
+
+    obj.value = file.fileRef;
+    obj.comment = file.basename;
+
+    return obj;
+}
+
+function pbxBuildPhaseObj(file) {
+    var obj = Object.create(null);
+
+    obj.value = file.uuid;
+    obj.comment = longComment(file);
+
+    return obj;
+}
+
+function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName){
+
+     // Add additional properties for 'CopyFiles' build phase
+    var DESTINATION_BY_TARGETTYPE = {
+        application: 'wrapper',
+        app_extension: 'plugins',
+        bundle: 'wrapper',
+        command_line_tool: 'wrapper',
+        dynamic_library: 'products_directory',
+        framework: 'shared_frameworks',
+        static_library: 'products_directory',
+        unit_test_bundle: 'wrapper',
+        watch_app: 'wrapper',
+        watch_extension: 'plugins'
+    }
+    var SUBFOLDERSPEC_BY_DESTINATION = {
+        absolute_path: 0,
+        executables: 6,
+        frameworks: 10,
+        java_resources: 15,
+        plugins: 13,
+        products_directory: 16,
+        resources: 7,
+        shared_frameworks: 11,
+        shared_support: 12,
+        wrapper: 1,
+        xpc_services: 0
+    }
+
+    obj.name = '"' + phaseName + '"';
+    obj.dstPath = subfolderPath || '""';
+    obj.dstSubfolderSpec = SUBFOLDERSPEC_BY_DESTINATION[DESTINATION_BY_TARGETTYPE[folderType]];
+
+    return obj;
+}
+
+function pbxBuildFileComment(file) {
+    return longComment(file);
+}
+
+function pbxFileReferenceComment(file) {
+    return file.basename || path.basename(file.path);
+}
+
+function pbxNativeTargetComment(target) {
+    return target.name;
+}
+
+function longComment(file) {
+    return f("%s in %s", file.basename, file.group);
+}
+
+// respect <group> path
+function correctForPluginsPath(file, project) {
+    return correctForPath(file, project, 'Plugins');
+}
+
+function correctForResourcesPath(file, project) {
+    return correctForPath(file, project, 'Resources');
+}
+
+function correctForFrameworksPath(file, project) {
+    return correctForPath(file, project, 'Frameworks');
+}
+
+function correctForPath(file, project, group) {
+    var r_group_dir = new RegExp('^' + group + '[\\\\/]');
+
+    if (project.pbxGroupByName(group).path)
+        file.path = file.path.replace(r_group_dir, '');
+
+    return file;
+}
+
+function searchPathForFile(file, proj) {
+    var plugins = proj.pbxGroupByName('Plugins'),
+        pluginsPath = plugins ? plugins.path : null,
+        fileDir = path.dirname(file.path);
+
+    if (fileDir == '.') {
+        fileDir = '';
+    } else {
+        fileDir = '/' + fileDir;
+    }
+
+    if (file.plugin && pluginsPath) {
+        return '"\\"$(SRCROOT)/' + unquote(pluginsPath) + '\\""';
+    } else if (file.customFramework && file.dirname) {
+        return '"\\"' + file.dirname + '\\""';
+    } else {
+        return '"\\"$(SRCROOT)/' + proj.productName + fileDir + '\\""';
+    }
+}
+
+function nonComments(obj) {
+    var keys = Object.keys(obj),
+        newObj = {}, i = 0;
+
+    for (i; i < keys.length; i++) {
+        if (!COMMENT_KEY.test(keys[i])) {
+            newObj[keys[i]] = obj[keys[i]];
+        }
+    }
+
+    return newObj;
+}
+
+function unquote(str) {
+    if (str) return str.replace(/^"(.*)"$/, "$1");
+}
+
+
+function buildPhaseNameForIsa (isa) {
+
+    BUILDPHASENAME_BY_ISA = {
+        PBXCopyFilesBuildPhase: 'Copy Files',
+        PBXResourcesBuildPhase: 'Resources',
+        PBXSourcesBuildPhase: 'Sources',
+        PBXFrameworksBuildPhase: 'Frameworks'
+    }
+
+    return BUILDPHASENAME_BY_ISA[isa]
+}
+
+function producttypeForTargettype (targetType) {
+
+    PRODUCTTYPE_BY_TARGETTYPE = {
+            application: 'com.apple.product-type.application',
+            app_extension: 'com.apple.product-type.app-extension',
+            bundle: 'com.apple.product-type.bundle',
+            command_line_tool: 'com.apple.product-type.tool',
+            dynamic_library: 'com.apple.product-type.library.dynamic',
+            framework: 'com.apple.product-type.framework',
+            static_library: 'com.apple.product-type.library.static',
+            unit_test_bundle: 'com.apple.product-type.bundle.unit-test',
+            watch_app: 'com.apple.product-type.application.watchapp',
+            watch_extension: 'com.apple.product-type.watchkit-extension'
+        };
+
+    return PRODUCTTYPE_BY_TARGETTYPE[targetType]
+}
+
+function filetypeForProducttype (productType) {
+
+    FILETYPE_BY_PRODUCTTYPE = {
+            'com.apple.product-type.application': '"wrapper.application"',
+            'com.apple.product-type.app-extension': '"wrapper.app-extension"',
+            'com.apple.product-type.bundle': '"wrapper.plug-in"',
+            'com.apple.product-type.tool': '"compiled.mach-o.dylib"',
+            'com.apple.product-type.library.dynamic': '"compiled.mach-o.dylib"',
+            'com.apple.product-type.framework': '"wrapper.framework"',
+            'com.apple.product-type.library.static': '"archive.ar"',
+            'com.apple.product-type.bundle.unit-test': '"wrapper.cfbundle"',
+            'com.apple.product-type.application.watchapp': '"wrapper.application"',
+            'com.apple.product-type.watchkit-extension': '"wrapper.app-extension"'
+        };
+
+    return FILETYPE_BY_PRODUCTTYPE[productType]
+}
+
+pbxProject.prototype.getFirstProject = function() {
+
+    // Get pbxProject container
+    var pbxProjectContainer = this.pbxProjectSection();
+
+    // Get first pbxProject UUID
+    var firstProjectUuid = Object.keys(pbxProjectContainer)[0];
+
+    // Get first pbxProject
+    var firstProject = pbxProjectContainer[firstProjectUuid];
+
+     return {
+        uuid: firstProjectUuid,
+        firstProject: firstProject
+    }
+}
+
+pbxProject.prototype.getFirstTarget = function() {
+
+    // Get first targets UUID
+    var firstTargetUuid = this.getFirstProject()['firstProject']['targets'][0].value;
+
+    // Get first pbxNativeTarget
+    var firstTarget = this.pbxNativeTargetSection()[firstTargetUuid];
+
+    return {
+        uuid: firstTargetUuid,
+        firstTarget: firstTarget
+    }
+}
+
+/*** NEW ***/
+
+pbxProject.prototype.addToPbxGroup = function (file, groupKey) {
+    var group = this.getPBXGroupByKey(groupKey);
+    if (group && group.children !== undefined) {
+        if (typeof file === 'string') {
+            //Group Key
+            var childGroup = {
+                value:file,
+                comment: this.getPBXGroupByKey(file).name
+            };
+
+            group.children.push(childGroup);
+        }
+        else {
+            //File Object
+            group.children.push(pbxGroupChild(file));
+        }
+    }
+}
+
+pbxProject.prototype.removeFromPbxGroup = function (file, groupKey) {
+    var group = this.getPBXGroupByKey(groupKey);
+    if (group) {
+        var groupChildren = group.children, i;
+        for(i in groupChildren) {
+            if(pbxGroupChild(file).value == groupChildren[i].value &&
+                pbxGroupChild(file).comment == groupChildren[i].comment) {
+                groupChildren.splice(i, 1);
+                break;
+            }
+        }
+    }
+}
+
+pbxProject.prototype.getPBXGroupByKey = function(key) {
+    return this.hash.project.objects['PBXGroup'][key];
+};
+
+pbxProject.prototype.findPBXGroupKey = function(criteria) {
+    var groups = this.hash.project.objects['PBXGroup'];
+    var target;
+
+    for (var key in groups) {
+        // only look for comments
+        if (COMMENT_KEY.test(key)) continue;
+
+        var group = groups[key];
+        if (criteria && criteria.path && criteria.name) {
+            if (criteria.path === group.path && criteria.name === group.name) {
+                target = key;
+                break
+            }
+        }
+        else if (criteria && criteria.path) {
+            if (criteria.path === group.path) {
+                target = key;
+                break
+            }
+        }
+        else if (criteria && criteria.name) {
+            if (criteria.name === group.name) {
+                target = key;
+                break
+            }
+        }
+    }
+
+    return target;
+}
+
+pbxProject.prototype.pbxCreateGroup = function(name, pathName) {
+
+    //Create object
+    var model = {
+        isa:"PBXGroup",
+        children: [],
+        name: name,
+        path: pathName,
+        sourceTree: '"<group>"'
+    };
+    var key = this.generateUuid();
+
+    //Create comment
+    var commendId = key + '_comment';
+
+    //add obj and commentObj to groups;
+    var groups = this.hash.project.objects['PBXGroup'];
+    groups[commendId] = name;
+    groups[key] = model;
+
+    return key;
+}
+
+
+pbxProject.prototype.getPBXObject = function(name) {
+    return this.hash.project.objects[name];
+}
+
+
+
+pbxProject.prototype.addFile = function (path, group, opt) {
+    var file = new pbxFile(path, opt);
+
+    // null is better for early errors
+    if (this.hasFile(file.path)) return null;
+
+    file.fileRef = this.generateUuid();
+
+    this.addToPbxFileReferenceSection(file);    // PBXFileReference
+    this.addToPbxGroup(file, group);            // PBXGroup
+
+    return file;
+}
+
+pbxProject.prototype.removeFile = function (path, group, opt) {
+    var file = new pbxFile(path, opt);
+
+    this.removeFromPbxFileReferenceSection(file);    // PBXFileReference
+    this.removeFromPbxGroup(file, group);            // PBXGroup
+
+    return file;
+}
+
+
+
+pbxProject.prototype.getBuildProperty = function(prop, build) {
+    var target;
+    var configs = this.pbxXCBuildConfigurationSection();
+    for (var configName in configs) {
+        if (!COMMENT_KEY.test(configName)) {
+            var config = configs[configName];
+            if ( (build && config.name === build) || (build === undefined) ) {
+                if (config.buildSettings[prop] !== undefined) {
+                    target = config.buildSettings[prop];
+                }
+            }
+        }
+    }
+    return target;
+}
+
+pbxProject.prototype.getBuildConfigByName = function(name) {
+    var target = {};
+    var configs = this.pbxXCBuildConfigurationSection();
+    for (var configName in configs) {
+        if (!COMMENT_KEY.test(configName)) {
+            var config = configs[configName];
+            if (config.name === name)  {
+                target[configName] = config;
+            }
+        }
+    }
+    return target;
+}
+
+
+module.exports = pbxProject;

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/lib/pbxWriter.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/lib/pbxWriter.js b/bin/node_modules/xcode/lib/pbxWriter.js
new file mode 100644
index 0000000..a65bcf1
--- /dev/null
+++ b/bin/node_modules/xcode/lib/pbxWriter.js
@@ -0,0 +1,282 @@
+var pbxProj = require('./pbxProject'),
+    util = require('util'),
+    f = util.format,
+    INDENT = '\t',
+    COMMENT_KEY = /_comment$/,
+    QUOTED = /^"(.*)"$/,
+    EventEmitter = require('events').EventEmitter
+
+// indentation
+function i(x) {
+    if (x <=0)
+        return '';
+    else
+        return INDENT + i(x-1);
+}
+
+function comment(key, parent) {
+    var text = parent[key + '_comment'];
+
+    if (text)
+        return text;
+    else
+        return null;
+}
+
+// copied from underscore
+function isObject(obj) {
+    return obj === Object(obj)
+}
+
+function isArray(obj) {
+    return Array.isArray(obj)
+}
+
+function pbxWriter(contents) {
+    this.contents = contents;
+    this.sync = false;
+    this.indentLevel = 0;
+}
+
+util.inherits(pbxWriter, EventEmitter);
+
+pbxWriter.prototype.write = function (str) {
+    var fmt = f.apply(null, arguments);
+
+    if (this.sync) {
+        this.buffer += f("%s%s", i(this.indentLevel), fmt);
+    } else {
+        // do stream write
+    }
+}
+
+pbxWriter.prototype.writeFlush = function (str) {
+    var oldIndent = this.indentLevel;
+
+    this.indentLevel = 0;
+
+    this.write.apply(this, arguments)
+
+    this.indentLevel = oldIndent;
+}
+
+pbxWriter.prototype.writeSync = function () {
+    this.sync = true;
+    this.buffer = "";
+
+    this.writeHeadComment();
+    this.writeProject();
+
+    return this.buffer;
+}
+
+pbxWriter.prototype.writeHeadComment = function () {
+    if (this.contents.headComment) {
+        this.write("// %s\n", this.contents.headComment)
+    }
+}
+
+pbxWriter.prototype.writeProject = function () {
+    var proj = this.contents.project,
+        key, cmt, obj;
+
+    this.write("{\n")
+
+    if (proj) {
+        this.indentLevel++;
+
+        for (key in proj) {
+            // skip comments
+            if (COMMENT_KEY.test(key)) continue;
+
+            cmt = comment(key, proj);
+            obj = proj[key];
+
+            if (isArray(obj)) {
+                this.writeArray(obj, key)
+            } else if (isObject(obj)) {
+                this.write("%s = {\n", key);
+                this.indentLevel++;
+
+                if (key === 'objects') {
+                    this.writeObjectsSections(obj)
+                } else {
+                    this.writeObject(obj)
+                }
+
+                this.indentLevel--;
+                this.write("};\n");
+            } else if (cmt) {
+                this.write("%s = %s /* %s */;\n", key, obj, cmt)
+            } else {
+                this.write("%s = %s;\n", key, obj)
+            }
+        }
+
+        this.indentLevel--;
+    }
+
+    this.write("}\n")
+}
+
+pbxWriter.prototype.writeObject = function (object) {
+    var key, obj, cmt;
+
+    for (key in object) {
+        if (COMMENT_KEY.test(key)) continue;
+
+        cmt = comment(key, object);
+        obj = object[key];
+
+        if (isArray(obj)) {
+            this.writeArray(obj, key)
+        } else if (isObject(obj)) {
+            this.write("%s = {\n", key);
+            this.indentLevel++;
+
+            this.writeObject(obj)
+
+            this.indentLevel--;
+            this.write("};\n");
+        } else {
+            if (cmt) {
+                this.write("%s = %s /* %s */;\n", key, obj, cmt)
+            } else {
+                this.write("%s = %s;\n", key, obj)
+            }
+        }
+    }
+}
+
+pbxWriter.prototype.writeObjectsSections = function (objects) {
+    var first = true,
+        key, obj;
+
+    for (key in objects) {
+        if (!first) {
+            this.writeFlush("\n")
+        } else {
+            first = false;
+        }
+
+        obj = objects[key];
+
+        if (isObject(obj)) {
+            this.writeSectionComment(key, true);
+
+            this.writeSection(obj);
+
+            this.writeSectionComment(key, false);
+        }
+    }
+}
+
+pbxWriter.prototype.writeArray = function (arr, name) {
+    var i, entry;
+
+    this.write("%s = (\n", name);
+    this.indentLevel++;
+
+    for (i=0; i < arr.length; i++) {
+        entry = arr[i]
+
+        if (entry.value && entry.comment) {
+            this.write('%s /* %s */,\n', entry.value, entry.comment);
+        } else if (isObject(entry)) {
+            this.write('{\n');
+            this.indentLevel++;
+            
+            this.writeObject(entry);
+
+            this.indentLevel--;
+            this.write('},\n');
+        } else {
+            this.write('%s,\n', entry);
+        }
+    }
+
+    this.indentLevel--;
+    this.write(");\n");
+}
+
+pbxWriter.prototype.writeSectionComment = function (name, begin) {
+    if (begin) {
+        this.writeFlush("/* Begin %s section */\n", name)
+    } else { // end
+        this.writeFlush("/* End %s section */\n", name)
+    }
+}
+
+pbxWriter.prototype.writeSection = function (section) {
+    var key, obj, cmt;
+
+    // section should only contain objects
+    for (key in section) {
+        if (COMMENT_KEY.test(key)) continue;
+
+        cmt = comment(key, section);
+        obj = section[key]
+
+        if (obj.isa == 'PBXBuildFile' || obj.isa == 'PBXFileReference') {
+            this.writeInlineObject(key, cmt, obj);
+        } else {
+            if (cmt) {
+                this.write("%s /* %s */ = {\n", key, cmt);
+            } else {
+                this.write("%s = {\n", key);
+            }
+
+            this.indentLevel++
+
+            this.writeObject(obj)
+
+            this.indentLevel--
+            this.write("};\n");
+        }
+    }
+}
+
+pbxWriter.prototype.writeInlineObject = function (n, d, r) {
+    var output = [];
+
+    var inlineObjectHelper = function (name, desc, ref) {
+        var key, cmt, obj;
+
+        if (desc) {
+            output.push(f("%s /* %s */ = {", name, desc));
+        } else {
+            output.push(f("%s = {", name));
+        }
+
+        for (key in ref) {
+            if (COMMENT_KEY.test(key)) continue;
+
+            cmt = comment(key, ref);
+            obj = ref[key];
+
+            if (isArray(obj)) {
+                output.push(f("%s = (", key));
+                
+                for (var i=0; i < obj.length; i++) {
+                    output.push(f("%s, ", obj[i]))
+                }
+
+                output.push("); ");
+            } else if (isObject(obj)) {
+                inlineObjectHelper(key, cmt, obj)
+            } else if (cmt) {
+                output.push(f("%s = %s /* %s */; ", key, obj, cmt))
+            } else {
+                output.push(f("%s = %s; ", key, obj))
+            }
+        }
+
+        output.push("}; ");
+    }
+
+    inlineObjectHelper(n, d, r);
+
+    this.write("%s\n", output.join('').trim());
+}
+
+module.exports = pbxWriter;

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/.bin/pegjs
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/.bin/pegjs b/bin/node_modules/xcode/node_modules/.bin/pegjs
new file mode 100644
index 0000000..67b7cec
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/.bin/pegjs
@@ -0,0 +1 @@
+../pegjs/bin/pegjs
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/.npmignore
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/.npmignore b/bin/node_modules/xcode/node_modules/node-uuid/.npmignore
new file mode 100644
index 0000000..fd4f2b0
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/.npmignore
@@ -0,0 +1,2 @@
+node_modules
+.DS_Store

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/LICENSE.md
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/LICENSE.md b/bin/node_modules/xcode/node_modules/node-uuid/LICENSE.md
new file mode 100644
index 0000000..bcdddf9
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/LICENSE.md
@@ -0,0 +1,3 @@
+Copyright (c) 2010 Robert Kieffer
+
+Dual licensed under the [MIT](http://en.wikipedia.org/wiki/MIT_License) and [GPL](http://en.wikipedia.org/wiki/GNU_General_Public_License) licenses.

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/README.md
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/README.md b/bin/node_modules/xcode/node_modules/node-uuid/README.md
new file mode 100644
index 0000000..a44d9a7
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/README.md
@@ -0,0 +1,199 @@
+# node-uuid
+
+Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.
+
+Features:
+
+* Generate RFC4122 version 1 or version 4 UUIDs
+* Runs in node.js and all browsers.
+* Cryptographically strong random # generation on supporting platforms
+* 1.1K minified and gzip'ed  (Want something smaller?  Check this [crazy shit](https://gist.github.com/982883) out! )
+* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)
+
+## Getting Started
+
+Install it in your browser:
+
+```html
+<script src="uuid.js"></script>
+```
+
+Or in node.js:
+
+```
+npm install node-uuid
+```
+
+```javascript
+var uuid = require('node-uuid');
+```
+
+Then create some ids ...
+
+```javascript
+// Generate a v1 (time-based) id
+uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
+
+// Generate a v4 (random) id
+uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
+```
+
+## API
+
+### uuid.v1([`options` [, `buffer` [, `offset`]]])
+
+Generate and return a RFC4122 v1 (timestamp-based) UUID.
+
+* `options` - (Object) Optional uuid state to apply. Properties may include:
+
+  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomnly generated ID.  See note 1.
+  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.
+  * `msecs` - (Number | Date) Time in milliseconds since unix Epoch.  Default: The current time is used.
+  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.
+
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
+* `offset` - (Number) Starting index in `buffer` at which to begin writing.
+
+Returns `buffer`, if specified, otherwise the string form of the UUID
+
+Notes:
+
+1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)
+
+Example: Generate string UUID with fully-specified options
+
+```javascript
+uuid.v1({
+  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
+  clockseq: 0x1234,
+  msecs: new Date('2011-11-01').getTime(),
+  nsecs: 5678
+});   // -> "710b962e-041c-11e1-9234-0123456789ab"
+```
+
+Example: In-place generation of two binary IDs
+
+```javascript
+// Generate two ids in an array
+var arr = new Array(32); // -> []
+uuid.v1(null, arr, 0);   // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
+uuid.v1(null, arr, 16);  // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
+
+// Optionally use uuid.unparse() to get stringify the ids
+uuid.unparse(buffer);    // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'
+uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'
+```
+
+### uuid.v4([`options` [, `buffer` [, `offset`]]])
+
+Generate and return a RFC4122 v4 UUID.
+
+* `options` - (Object) Optional uuid state to apply. Properties may include:
+
+  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values
+  * `rng` - (Function) Random # generator to use.  Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.
+
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
+* `offset` - (Number) Starting index in `buffer` at which to begin writing.
+
+Returns `buffer`, if specified, otherwise the string form of the UUID
+
+Example: Generate string UUID with fully-specified options
+
+```javascript
+uuid.v4({
+  random: [
+    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,
+    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36
+  ]
+});
+// -> "109156be-c4fb-41ea-b1b4-efe1671c5836"
+```
+
+Example: Generate two IDs in a single buffer
+
+```javascript
+var buffer = new Array(32); // (or 'new Buffer' in node.js)
+uuid.v4(null, buffer, 0);
+uuid.v4(null, buffer, 16);
+```
+
+### uuid.parse(id[, buffer[, offset]])
+### uuid.unparse(buffer[, offset])
+
+Parse and unparse UUIDs
+
+  * `id` - (String) UUID(-like) string
+  * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used
+  * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0
+
+Example parsing and unparsing a UUID string
+
+```javascript
+var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>
+var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'
+```
+
+### uuid.noConflict()
+
+(Browsers only) Set `uuid` property back to it's previous value.
+
+Returns the node-uuid object.
+
+Example:
+
+```javascript
+var myUuid = uuid.noConflict();
+myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
+```
+
+## Deprecated APIs
+
+Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.
+
+### uuid([format [, buffer [, offset]]])
+
+uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).
+
+### uuid.BufferClass
+
+The class of container created when generating binary uuid data if no buffer argument is specified.  This is expected to go away, with no replacement API.
+
+## Testing
+
+In node.js
+
+```
+> cd test
+> node uuid.js
+```
+
+In Browser
+
+```
+open test/test.html
+```
+
+### Benchmarking
+
+Requires node.js
+
+```
+npm install uuid uuid-js
+node test/benchmark.js
+```
+
+For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)
+
+For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).
+
+## Release notes
+
+v1.3.2:
+* Improve tests and handling of v1() options (Issue #24)
+* Expose RNG option to allow for perf testing with different generators
+
+v1.3:
+* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!
+* Support for node.js crypto API
+* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/benchmark/README.md
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/benchmark/README.md b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/README.md
new file mode 100644
index 0000000..aaeb2ea
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/README.md
@@ -0,0 +1,53 @@
+# node-uuid Benchmarks
+
+### Results
+
+To see the results of our benchmarks visit https://github.com/broofa/node-uuid/wiki/Benchmark
+
+### Run them yourself
+
+node-uuid comes with some benchmarks to measure performance of generating UUIDs. These can be run using node.js. node-uuid is being benchmarked against some other uuid modules, that are available through npm namely `uuid` and `uuid-js`.
+
+To prepare and run the benchmark issue;
+
+```
+npm install uuid uuid-js
+node benchmark/benchmark.js
+```
+
+You'll see an output like this one:
+
+```
+# v4
+nodeuuid.v4(): 854700 uuids/second
+nodeuuid.v4('binary'): 788643 uuids/second
+nodeuuid.v4('binary', buffer): 1336898 uuids/second
+uuid(): 479386 uuids/second
+uuid('binary'): 582072 uuids/second
+uuidjs.create(4): 312304 uuids/second
+
+# v1
+nodeuuid.v1(): 938086 uuids/second
+nodeuuid.v1('binary'): 683060 uuids/second
+nodeuuid.v1('binary', buffer): 1644736 uuids/second
+uuidjs.create(1): 190621 uuids/second
+```
+
+* The `uuid()` entries are for Nikhil Marathe's [uuid module](https://bitbucket.org/nikhilm/uuidjs) which is a wrapper around the native libuuid library.
+* The `uuidjs()` entries are for Patrick Negri's [uuid-js module](https://github.com/pnegri/uuid-js) which is a pure javascript implementation based on [UUID.js](https://github.com/LiosK/UUID.js) by LiosK.
+
+If you want to get more reliable results you can run the benchmark multiple times and write the output into a log file:
+
+```
+for i in {0..9}; do node benchmark/benchmark.js >> benchmark/bench_0.4.12.log; done;
+```
+
+If you're interested in how performance varies between different node versions, you can issue the above command multiple times.
+
+You can then use the shell script `bench.sh` provided in this directory to calculate the averages over all benchmark runs and draw a nice plot:
+
+```
+(cd benchmark/ && ./bench.sh)
+```
+
+This assumes you have [gnuplot](http://www.gnuplot.info/) and [ImageMagick](http://www.imagemagick.org/) installed. You'll find a nice `bench.png` graph in the `benchmark/` directory then.

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.gnu
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.gnu b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.gnu
new file mode 100644
index 0000000..a342fbb
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.gnu
@@ -0,0 +1,174 @@
+#!/opt/local/bin/gnuplot -persist
+#
+#    
+#    	G N U P L O T
+#    	Version 4.4 patchlevel 3
+#    	last modified March 2011
+#    	System: Darwin 10.8.0
+#    
+#    	Copyright (C) 1986-1993, 1998, 2004, 2007-2010
+#    	Thomas Williams, Colin Kelley and many others
+#    
+#    	gnuplot home:     http://www.gnuplot.info
+#    	faq, bugs, etc:   type "help seeking-assistance"
+#    	immediate help:   type "help"
+#    	plot window:      hit 'h'
+set terminal postscript eps noenhanced defaultplex \
+ leveldefault color colortext \
+ solid linewidth 1.2 butt noclip \
+ palfuncparam 2000,0.003 \
+ "Helvetica" 14 
+set output 'bench.eps'
+unset clip points
+set clip one
+unset clip two
+set bar 1.000000 front
+set border 31 front linetype -1 linewidth 1.000
+set xdata
+set ydata
+set zdata
+set x2data
+set y2data
+set timefmt x "%d/%m/%y,%H:%M"
+set timefmt y "%d/%m/%y,%H:%M"
+set timefmt z "%d/%m/%y,%H:%M"
+set timefmt x2 "%d/%m/%y,%H:%M"
+set timefmt y2 "%d/%m/%y,%H:%M"
+set timefmt cb "%d/%m/%y,%H:%M"
+set boxwidth
+set style fill  empty border
+set style rectangle back fc lt -3 fillstyle   solid 1.00 border lt -1
+set style circle radius graph 0.02, first 0, 0 
+set dummy x,y
+set format x "% g"
+set format y "% g"
+set format x2 "% g"
+set format y2 "% g"
+set format z "% g"
+set format cb "% g"
+set angles radians
+unset grid
+set key title ""
+set key outside left top horizontal Right noreverse enhanced autotitles columnhead nobox
+set key noinvert samplen 4 spacing 1 width 0 height 0 
+set key maxcolumns 2 maxrows 0
+unset label
+unset arrow
+set style increment default
+unset style line
+set style line 1  linetype 1 linewidth 2.000 pointtype 1 pointsize default pointinterval 0
+unset style arrow
+set style histogram clustered gap 2 title  offset character 0, 0, 0
+unset logscale
+set offsets graph 0.05, 0.15, 0, 0
+set pointsize 1.5
+set pointintervalbox 1
+set encoding default
+unset polar
+unset parametric
+unset decimalsign
+set view 60, 30, 1, 1
+set samples 100, 100
+set isosamples 10, 10
+set surface
+unset contour
+set clabel '%8.3g'
+set mapping cartesian
+set datafile separator whitespace
+unset hidden3d
+set cntrparam order 4
+set cntrparam linear
+set cntrparam levels auto 5
+set cntrparam points 5
+set size ratio 0 1,1
+set origin 0,0
+set style data points
+set style function lines
+set xzeroaxis linetype -2 linewidth 1.000
+set yzeroaxis linetype -2 linewidth 1.000
+set zzeroaxis linetype -2 linewidth 1.000
+set x2zeroaxis linetype -2 linewidth 1.000
+set y2zeroaxis linetype -2 linewidth 1.000
+set ticslevel 0.5
+set mxtics default
+set mytics default
+set mztics default
+set mx2tics default
+set my2tics default
+set mcbtics default
+set xtics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
+set xtics  norangelimit
+set xtics   ()
+set ytics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
+set ytics autofreq  norangelimit
+set ztics border in scale 1,0.5 nomirror norotate  offset character 0, 0, 0
+set ztics autofreq  norangelimit
+set nox2tics
+set noy2tics
+set cbtics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
+set cbtics autofreq  norangelimit
+set title "" 
+set title  offset character 0, 0, 0 font "" norotate
+set timestamp bottom 
+set timestamp "" 
+set timestamp  offset character 0, 0, 0 font "" norotate
+set rrange [ * : * ] noreverse nowriteback  # (currently [8.98847e+307:-8.98847e+307] )
+set autoscale rfixmin
+set autoscale rfixmax
+set trange [ * : * ] noreverse nowriteback  # (currently [-5.00000:5.00000] )
+set autoscale tfixmin
+set autoscale tfixmax
+set urange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
+set autoscale ufixmin
+set autoscale ufixmax
+set vrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
+set autoscale vfixmin
+set autoscale vfixmax
+set xlabel "" 
+set xlabel  offset character 0, 0, 0 font "" textcolor lt -1 norotate
+set x2label "" 
+set x2label  offset character 0, 0, 0 font "" textcolor lt -1 norotate
+set xrange [ * : * ] noreverse nowriteback  # (currently [-0.150000:3.15000] )
+set autoscale xfixmin
+set autoscale xfixmax
+set x2range [ * : * ] noreverse nowriteback  # (currently [0.00000:3.00000] )
+set autoscale x2fixmin
+set autoscale x2fixmax
+set ylabel "" 
+set ylabel  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
+set y2label "" 
+set y2label  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
+set yrange [ 0.00000 : 1.90000e+06 ] noreverse nowriteback  # (currently [:] )
+set autoscale yfixmin
+set autoscale yfixmax
+set y2range [ * : * ] noreverse nowriteback  # (currently [0.00000:1.90000e+06] )
+set autoscale y2fixmin
+set autoscale y2fixmax
+set zlabel "" 
+set zlabel  offset character 0, 0, 0 font "" textcolor lt -1 norotate
+set zrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
+set autoscale zfixmin
+set autoscale zfixmax
+set cblabel "" 
+set cblabel  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
+set cbrange [ * : * ] noreverse nowriteback  # (currently [8.98847e+307:-8.98847e+307] )
+set autoscale cbfixmin
+set autoscale cbfixmax
+set zero 1e-08
+set lmargin  -1
+set bmargin  -1
+set rmargin  -1
+set tmargin  -1
+set pm3d explicit at s
+set pm3d scansautomatic
+set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean
+set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB 
+set palette rgbformulae 7, 5, 15
+set colorbox default
+set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault
+set loadpath 
+set fontpath 
+set fit noerrorvariables
+GNUTERM = "aqua"
+plot 'bench_results.txt' using 2:xticlabel(1) w lp lw 2, '' using 3:xticlabel(1) w lp lw 2, '' using 4:xticlabel(1) w lp lw 2, '' using 5:xticlabel(1) w lp lw 2, '' using 6:xticlabel(1) w lp lw 2, '' using 7:xticlabel(1) w lp lw 2, '' using 8:xticlabel(1) w lp lw 2, '' using 9:xticlabel(1) w lp lw 2
+#    EOF

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.sh
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.sh b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.sh
new file mode 100644
index 0000000..d870a0c
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/bench.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# for a given node version run:
+# for i in {0..9}; do node benchmark.js >> bench_0.6.2.log; done;
+
+PATTERNS=('nodeuuid.v1()' "nodeuuid.v1('binary'," 'nodeuuid.v4()' "nodeuuid.v4('binary'," "uuid()" "uuid('binary')" 'uuidjs.create(1)' 'uuidjs.create(4)' '140byte')
+FILES=(node_uuid_v1_string node_uuid_v1_buf node_uuid_v4_string node_uuid_v4_buf libuuid_v4_string libuuid_v4_binary uuidjs_v1_string uuidjs_v4_string 140byte_es)
+INDICES=(2 3 2 3 2 2 2 2 2)
+VERSIONS=$( ls bench_*.log | sed -e 's/^bench_\([0-9\.]*\)\.log/\1/' | tr "\\n" " " )
+TMPJOIN="tmp_join"
+OUTPUT="bench_results.txt"
+
+for I in ${!FILES[*]}; do
+  F=${FILES[$I]}
+  P=${PATTERNS[$I]}
+  INDEX=${INDICES[$I]}
+  echo "version $F" > $F
+  for V in $VERSIONS; do
+    (VAL=$( grep "$P" bench_$V.log | LC_ALL=en_US awk '{ sum += $'$INDEX' } END { print sum/NR }' ); echo $V $VAL) >> $F
+  done
+  if [ $I == 0 ]; then
+    cat $F > $TMPJOIN
+  else
+    join $TMPJOIN $F > $OUTPUT
+    cp $OUTPUT $TMPJOIN
+  fi
+  rm $F
+done
+
+rm $TMPJOIN
+
+gnuplot bench.gnu
+convert -density 200 -resize 800x560 -flatten bench.eps bench.png
+rm bench.eps

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark-native.c
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark-native.c b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark-native.c
new file mode 100644
index 0000000..dbfc75f
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark-native.c
@@ -0,0 +1,34 @@
+/*
+Test performance of native C UUID generation
+
+To Compile: cc -luuid benchmark-native.c -o benchmark-native
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <uuid/uuid.h>
+
+int main() {
+  uuid_t myid;
+  char buf[36+1];
+  int i;
+  struct timeval t;
+  double start, finish;
+
+  gettimeofday(&t, NULL);
+  start = t.tv_sec + t.tv_usec/1e6;
+
+  int n = 2e5;
+  for (i = 0; i < n; i++) {
+    uuid_generate(myid);
+    uuid_unparse(myid, buf);
+  }
+
+  gettimeofday(&t, NULL);
+  finish = t.tv_sec + t.tv_usec/1e6;
+  double dur = finish - start;
+
+  printf("%d uuids/sec", (int)(n/dur));
+  return 0;
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark.js b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark.js
new file mode 100644
index 0000000..40e6efb
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/benchmark/benchmark.js
@@ -0,0 +1,84 @@
+try {
+  var nodeuuid = require('../uuid');
+} catch (e) {
+  console.error('node-uuid require failed - skipping tests');
+}
+
+try {
+  var uuid = require('uuid');
+} catch (e) {
+  console.error('uuid require failed - skipping tests');
+}
+
+try {
+  var uuidjs = require('uuid-js');
+} catch (e) {
+  console.error('uuid-js require failed - skipping tests');
+}
+
+var N = 5e5;
+
+function rate(msg, t) {
+  console.log(msg + ': ' +
+    (N / (Date.now() - t) * 1e3 | 0) +
+    ' uuids/second');
+}
+
+console.log('# v4');
+
+// node-uuid - string form
+if (nodeuuid) {
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4();
+  rate('nodeuuid.v4() - using node.js crypto RNG', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4({rng: nodeuuid.mathRNG});
+  rate('nodeuuid.v4() - using Math.random() RNG', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary');
+  rate('nodeuuid.v4(\'binary\')', t);
+
+  var buffer = new nodeuuid.BufferClass(16);
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary', buffer);
+  rate('nodeuuid.v4(\'binary\', buffer)', t);
+}
+
+// libuuid - string form
+if (uuid) {
+  for (var i = 0, t = Date.now(); i < N; i++) uuid();
+  rate('uuid()', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) uuid('binary');
+  rate('uuid(\'binary\')', t);
+}
+
+// uuid-js - string form
+if (uuidjs) {
+  for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(4);
+  rate('uuidjs.create(4)', t);
+}
+
+// 140byte.es
+for (var i = 0, t = Date.now(); i < N; i++) 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(s,r){r=Math.random()*16|0;return (s=='x'?r:r&0x3|0x8).toString(16)});
+rate('140byte.es_v4', t);
+
+console.log('');
+console.log('# v1');
+
+// node-uuid - v1 string form
+if (nodeuuid) {
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1();
+  rate('nodeuuid.v1()', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary');
+  rate('nodeuuid.v1(\'binary\')', t);
+
+  var buffer = new nodeuuid.BufferClass(16);
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary', buffer);
+  rate('nodeuuid.v1(\'binary\', buffer)', t);
+}
+
+// uuid-js - v1 string form
+if (uuidjs) {
+  for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(1);
+  rate('uuidjs.create(1)', t);
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/package.json
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/package.json b/bin/node_modules/xcode/node_modules/node-uuid/package.json
new file mode 100644
index 0000000..9ec4d1b
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/package.json
@@ -0,0 +1,60 @@
+{
+  "name": "node-uuid",
+  "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
+  "url": "http://github.com/broofa/node-uuid",
+  "keywords": [
+    "uuid",
+    "guid",
+    "rfc4122"
+  ],
+  "author": {
+    "name": "Robert Kieffer",
+    "email": "robert@broofa.com"
+  },
+  "contributors": [
+    {
+      "name": "Christoph Tavan",
+      "email": "dev@tavan.de"
+    }
+  ],
+  "lib": ".",
+  "main": "./uuid.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/broofa/node-uuid.git"
+  },
+  "version": "1.3.3",
+  "_npmUser": {
+    "name": "broofa",
+    "email": "robert@broofa.com"
+  },
+  "_id": "node-uuid@1.3.3",
+  "dependencies": {},
+  "devDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "_engineSupported": true,
+  "_npmVersion": "1.0.106",
+  "_nodeVersion": "v0.4.6",
+  "_defaultsLoaded": true,
+  "dist": {
+    "shasum": "d3db4d7b56810d9e4032342766282af07391729b",
+    "tarball": "http://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz"
+  },
+  "maintainers": [
+    {
+      "name": "broofa",
+      "email": "robert@broofa.com"
+    }
+  ],
+  "directories": {},
+  "_shasum": "d3db4d7b56810d9e4032342766282af07391729b",
+  "_from": "node-uuid@1.3.3",
+  "_resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz",
+  "bugs": {
+    "url": "https://github.com/broofa/node-uuid/issues"
+  },
+  "readme": "ERROR: No README data found!",
+  "homepage": "https://github.com/broofa/node-uuid"
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/test/compare_v1.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/test/compare_v1.js b/bin/node_modules/xcode/node_modules/node-uuid/test/compare_v1.js
new file mode 100644
index 0000000..05af822
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/test/compare_v1.js
@@ -0,0 +1,63 @@
+var assert = require('assert'),
+    nodeuuid = require('../uuid'),
+    uuidjs = require('uuid-js'),
+    libuuid = require('uuid').generate,
+    util = require('util'),
+    exec = require('child_process').exec,
+    os = require('os');
+
+// On Mac Os X / macports there's only the ossp-uuid package that provides uuid
+// On Linux there's uuid-runtime which provides uuidgen
+var uuidCmd = os.type() === 'Darwin' ? 'uuid -1' : 'uuidgen -t';
+
+function compare(ids) {
+  console.log(ids);
+  for (var i = 0; i < ids.length; i++) {
+    var id = ids[i].split('-');
+    id = [id[2], id[1], id[0]].join('');
+    ids[i] = id;
+  }
+  var sorted = ([].concat(ids)).sort();
+
+  if (sorted.toString() !== ids.toString()) {
+    console.log('Warning: sorted !== ids');
+  } else {
+    console.log('everything in order!');
+  }
+}
+
+// Test time order of v1 uuids
+var ids = [];
+while (ids.length < 10e3) ids.push(nodeuuid.v1());
+
+var max = 10;
+console.log('node-uuid:');
+ids = [];
+for (var i = 0; i < max; i++) ids.push(nodeuuid.v1());
+compare(ids);
+
+console.log('');
+console.log('uuidjs:');
+ids = [];
+for (var i = 0; i < max; i++) ids.push(uuidjs.create(1).toString());
+compare(ids);
+
+console.log('');
+console.log('libuuid:');
+ids = [];
+var count = 0;
+var last = function() {
+  compare(ids);
+}
+var cb = function(err, stdout, stderr) {
+  ids.push(stdout.substring(0, stdout.length-1));
+  count++;
+  if (count < max) {
+    return next();
+  }
+  last();
+};
+var next = function() {
+  exec(uuidCmd, cb);
+};
+next();

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/26cca47e/bin/node_modules/xcode/node_modules/node-uuid/test/test.html
----------------------------------------------------------------------
diff --git a/bin/node_modules/xcode/node_modules/node-uuid/test/test.html b/bin/node_modules/xcode/node_modules/node-uuid/test/test.html
new file mode 100644
index 0000000..d80326e
--- /dev/null
+++ b/bin/node_modules/xcode/node_modules/node-uuid/test/test.html
@@ -0,0 +1,17 @@
+<html>
+  <head>
+    <style>
+      div {
+        font-family: monospace;
+        font-size: 8pt;
+      }
+      div.log {color: #444;}
+      div.warn {color: #550;}
+      div.error {color: #800; font-weight: bold;}
+    </style>
+    <script src="../uuid.js"></script>
+  </head>
+  <body>
+    <script src="./test.js"></script>
+  </body>
+</html>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org