You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by st...@apache.org on 2016/03/04 00:55:26 UTC
[46/59] [abbrv] [partial] mac commit: CB-10668 added node_modules
directory
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/rm.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/rm.js b/node_modules/cordova-common/node_modules/shelljs/src/rm.js
new file mode 100644
index 0000000..bd608cb
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/rm.js
@@ -0,0 +1,163 @@
+var common = require('./common');
+var fs = require('fs');
+
+// Recursively removes 'dir'
+// Adapted from https://github.com/ryanmcgrath/wrench-js
+//
+// Copyright (c) 2010 Ryan McGrath
+// Copyright (c) 2012 Artur Adib
+//
+// Licensed under the MIT License
+// http://www.opensource.org/licenses/mit-license.php
+function rmdirSyncRecursive(dir, force) {
+ var files;
+
+ files = fs.readdirSync(dir);
+
+ // Loop through and delete everything in the sub-tree after checking it
+ for(var i = 0; i < files.length; i++) {
+ var file = dir + "/" + files[i],
+ currFile = fs.lstatSync(file);
+
+ if(currFile.isDirectory()) { // Recursive function back to the beginning
+ rmdirSyncRecursive(file, force);
+ }
+
+ else if(currFile.isSymbolicLink()) { // Unlink symlinks
+ if (force || isWriteable(file)) {
+ try {
+ common.unlinkSync(file);
+ } catch (e) {
+ common.error('could not remove file (code '+e.code+'): ' + file, true);
+ }
+ }
+ }
+
+ else // Assume it's a file - perhaps a try/catch belongs here?
+ if (force || isWriteable(file)) {
+ try {
+ common.unlinkSync(file);
+ } catch (e) {
+ common.error('could not remove file (code '+e.code+'): ' + file, true);
+ }
+ }
+ }
+
+ // Now that we know everything in the sub-tree has been deleted, we can delete the main directory.
+ // Huzzah for the shopkeep.
+
+ var result;
+ try {
+ // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+ var start = Date.now();
+ while (true) {
+ try {
+ result = fs.rmdirSync(dir);
+ if (fs.existsSync(dir)) throw { code: "EAGAIN" }
+ break;
+ } catch(er) {
+ // In addition to error codes, also check if the directory still exists and loop again if true
+ if (process.platform === "win32" && (er.code === "ENOTEMPTY" || er.code === "EBUSY" || er.code === "EPERM" || er.code === "EAGAIN")) {
+ if (Date.now() - start > 1000) throw er;
+ } else if (er.code === "ENOENT") {
+ // Directory did not exist, deletion was successful
+ break;
+ } else {
+ throw er;
+ }
+ }
+ }
+ } catch(e) {
+ common.error('could not remove directory (code '+e.code+'): ' + dir, true);
+ }
+
+ return result;
+} // rmdirSyncRecursive
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow
+function isWriteable(file) {
+ var writePermission = true;
+ try {
+ var __fd = fs.openSync(file, 'a');
+ fs.closeSync(__fd);
+ } catch(e) {
+ writePermission = false;
+ }
+
+ return writePermission;
+}
+
+//@
+//@ ### rm([options ,] file [, file ...])
+//@ ### rm([options ,] file_array)
+//@ Available options:
+//@
+//@ + `-f`: force
+//@ + `-r, -R`: recursive
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ rm('-rf', '/tmp/*');
+//@ rm('some_file.txt', 'another_file.txt');
+//@ rm(['some_file.txt', 'another_file.txt']); // same as above
+//@ ```
+//@
+//@ Removes files. The wildcard `*` is accepted.
+function _rm(options, files) {
+ options = common.parseOptions(options, {
+ 'f': 'force',
+ 'r': 'recursive',
+ 'R': 'recursive'
+ });
+ if (!files)
+ common.error('no paths given');
+
+ if (typeof files === 'string')
+ files = [].slice.call(arguments, 1);
+ // if it's array leave it as it is
+
+ files = common.expand(files);
+
+ files.forEach(function(file) {
+ if (!fs.existsSync(file)) {
+ // Path does not exist, no force flag given
+ if (!options.force)
+ common.error('no such file or directory: '+file, true);
+
+ return; // skip file
+ }
+
+ // If here, path exists
+
+ var stats = fs.lstatSync(file);
+ if (stats.isFile() || stats.isSymbolicLink()) {
+
+ // Do not check for file writing permissions
+ if (options.force) {
+ common.unlinkSync(file);
+ return;
+ }
+
+ if (isWriteable(file))
+ common.unlinkSync(file);
+ else
+ common.error('permission denied: '+file, true);
+
+ return;
+ } // simple file
+
+ // Path is an existing directory, but no -r flag given
+ if (stats.isDirectory() && !options.recursive) {
+ common.error('path is a directory', true);
+ return; // skip path
+ }
+
+ // Recursively remove existing directory
+ if (stats.isDirectory() && options.recursive) {
+ rmdirSyncRecursive(file, options.force);
+ }
+ }); // forEach(file)
+} // rm
+module.exports = _rm;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/sed.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/sed.js b/node_modules/cordova-common/node_modules/shelljs/src/sed.js
new file mode 100644
index 0000000..65f7cb4
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/sed.js
@@ -0,0 +1,43 @@
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### sed([options ,] search_regex, replacement, file)
+//@ Available options:
+//@
+//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
+//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
+//@ ```
+//@
+//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input
+//@ using the given search regex and replacement string or function. Returns the new string after replacement.
+function _sed(options, regex, replacement, file) {
+ options = common.parseOptions(options, {
+ 'i': 'inplace'
+ });
+
+ if (typeof replacement === 'string' || typeof replacement === 'function')
+ replacement = replacement; // no-op
+ else if (typeof replacement === 'number')
+ replacement = replacement.toString(); // fallback
+ else
+ common.error('invalid replacement string');
+
+ if (!file)
+ common.error('no file given');
+
+ if (!fs.existsSync(file))
+ common.error('no such file or directory: ' + file);
+
+ var result = fs.readFileSync(file, 'utf8').replace(regex, replacement);
+ if (options.inplace)
+ fs.writeFileSync(file, result, 'utf8');
+
+ return common.ShellString(result);
+}
+module.exports = _sed;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/tempdir.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/tempdir.js b/node_modules/cordova-common/node_modules/shelljs/src/tempdir.js
new file mode 100644
index 0000000..45953c2
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/tempdir.js
@@ -0,0 +1,56 @@
+var common = require('./common');
+var os = require('os');
+var fs = require('fs');
+
+// Returns false if 'dir' is not a writeable directory, 'dir' otherwise
+function writeableDir(dir) {
+ if (!dir || !fs.existsSync(dir))
+ return false;
+
+ if (!fs.statSync(dir).isDirectory())
+ return false;
+
+ var testFile = dir+'/'+common.randomFileName();
+ try {
+ fs.writeFileSync(testFile, ' ');
+ common.unlinkSync(testFile);
+ return dir;
+ } catch (e) {
+ return false;
+ }
+}
+
+
+//@
+//@ ### tempdir()
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var tmp = tempdir(); // "/tmp" for most *nix platforms
+//@ ```
+//@
+//@ Searches and returns string containing a writeable, platform-dependent temporary directory.
+//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
+function _tempDir() {
+ var state = common.state;
+ if (state.tempDir)
+ return state.tempDir; // from cache
+
+ state.tempDir = writeableDir(os.tempDir && os.tempDir()) || // node 0.8+
+ writeableDir(process.env['TMPDIR']) ||
+ writeableDir(process.env['TEMP']) ||
+ writeableDir(process.env['TMP']) ||
+ writeableDir(process.env['Wimp$ScrapDir']) || // RiscOS
+ writeableDir('C:\\TEMP') || // Windows
+ writeableDir('C:\\TMP') || // Windows
+ writeableDir('\\TEMP') || // Windows
+ writeableDir('\\TMP') || // Windows
+ writeableDir('/tmp') ||
+ writeableDir('/var/tmp') ||
+ writeableDir('/usr/tmp') ||
+ writeableDir('.'); // last resort
+
+ return state.tempDir;
+}
+module.exports = _tempDir;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/test.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/test.js b/node_modules/cordova-common/node_modules/shelljs/src/test.js
new file mode 100644
index 0000000..8a4ac7d
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/test.js
@@ -0,0 +1,85 @@
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### test(expression)
+//@ Available expression primaries:
+//@
+//@ + `'-b', 'path'`: true if path is a block device
+//@ + `'-c', 'path'`: true if path is a character device
+//@ + `'-d', 'path'`: true if path is a directory
+//@ + `'-e', 'path'`: true if path exists
+//@ + `'-f', 'path'`: true if path is a regular file
+//@ + `'-L', 'path'`: true if path is a symboilc link
+//@ + `'-p', 'path'`: true if path is a pipe (FIFO)
+//@ + `'-S', 'path'`: true if path is a socket
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ if (test('-d', path)) { /* do something with dir */ };
+//@ if (!test('-f', path)) continue; // skip if it's a regular file
+//@ ```
+//@
+//@ Evaluates expression using the available primaries and returns corresponding value.
+function _test(options, path) {
+ if (!path)
+ common.error('no path given');
+
+ // hack - only works with unary primaries
+ options = common.parseOptions(options, {
+ 'b': 'block',
+ 'c': 'character',
+ 'd': 'directory',
+ 'e': 'exists',
+ 'f': 'file',
+ 'L': 'link',
+ 'p': 'pipe',
+ 'S': 'socket'
+ });
+
+ var canInterpret = false;
+ for (var key in options)
+ if (options[key] === true) {
+ canInterpret = true;
+ break;
+ }
+
+ if (!canInterpret)
+ common.error('could not interpret expression');
+
+ if (options.link) {
+ try {
+ return fs.lstatSync(path).isSymbolicLink();
+ } catch(e) {
+ return false;
+ }
+ }
+
+ if (!fs.existsSync(path))
+ return false;
+
+ if (options.exists)
+ return true;
+
+ var stats = fs.statSync(path);
+
+ if (options.block)
+ return stats.isBlockDevice();
+
+ if (options.character)
+ return stats.isCharacterDevice();
+
+ if (options.directory)
+ return stats.isDirectory();
+
+ if (options.file)
+ return stats.isFile();
+
+ if (options.pipe)
+ return stats.isFIFO();
+
+ if (options.socket)
+ return stats.isSocket();
+} // test
+module.exports = _test;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/to.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/to.js b/node_modules/cordova-common/node_modules/shelljs/src/to.js
new file mode 100644
index 0000000..f029999
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/to.js
@@ -0,0 +1,29 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+//@
+//@ ### 'string'.to(file)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ cat('input.txt').to('output.txt');
+//@ ```
+//@
+//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
+//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
+function _to(options, file) {
+ if (!file)
+ common.error('wrong arguments');
+
+ if (!fs.existsSync( path.dirname(file) ))
+ common.error('no such file or directory: ' + path.dirname(file));
+
+ try {
+ fs.writeFileSync(file, this.toString(), 'utf8');
+ } catch(e) {
+ common.error('could not write to file (code '+e.code+'): '+file, true);
+ }
+}
+module.exports = _to;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/toEnd.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/toEnd.js b/node_modules/cordova-common/node_modules/shelljs/src/toEnd.js
new file mode 100644
index 0000000..f6d099d
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/toEnd.js
@@ -0,0 +1,29 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+//@
+//@ ### 'string'.toEnd(file)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ cat('input.txt').toEnd('output.txt');
+//@ ```
+//@
+//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
+//@ those returned by `cat`, `grep`, etc).
+function _toEnd(options, file) {
+ if (!file)
+ common.error('wrong arguments');
+
+ if (!fs.existsSync( path.dirname(file) ))
+ common.error('no such file or directory: ' + path.dirname(file));
+
+ try {
+ fs.appendFileSync(file, this.toString(), 'utf8');
+ } catch(e) {
+ common.error('could not append to file (code '+e.code+'): '+file, true);
+ }
+}
+module.exports = _toEnd;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/node_modules/shelljs/src/which.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/node_modules/shelljs/src/which.js b/node_modules/cordova-common/node_modules/shelljs/src/which.js
new file mode 100644
index 0000000..2822ecf
--- /dev/null
+++ b/node_modules/cordova-common/node_modules/shelljs/src/which.js
@@ -0,0 +1,83 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+// Cross-platform method for splitting environment PATH variables
+function splitPath(p) {
+ for (i=1;i<2;i++) {}
+
+ if (!p)
+ return [];
+
+ if (common.platform === 'win')
+ return p.split(';');
+ else
+ return p.split(':');
+}
+
+function checkPath(path) {
+ return fs.existsSync(path) && fs.statSync(path).isDirectory() == false;
+}
+
+//@
+//@ ### which(command)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var nodeExec = which('node');
+//@ ```
+//@
+//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
+//@ Returns string containing the absolute path to the command.
+function _which(options, cmd) {
+ if (!cmd)
+ common.error('must specify command');
+
+ var pathEnv = process.env.path || process.env.Path || process.env.PATH,
+ pathArray = splitPath(pathEnv),
+ where = null;
+
+ // No relative/absolute paths provided?
+ if (cmd.search(/\//) === -1) {
+ // Search for command in PATH
+ pathArray.forEach(function(dir) {
+ if (where)
+ return; // already found it
+
+ var attempt = path.resolve(dir + '/' + cmd);
+ if (checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+
+ if (common.platform === 'win') {
+ var baseAttempt = attempt;
+ attempt = baseAttempt + '.exe';
+ if (checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+ attempt = baseAttempt + '.cmd';
+ if (checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+ attempt = baseAttempt + '.bat';
+ if (checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+ } // if 'win'
+ });
+ }
+
+ // Command not found anywhere?
+ if (!checkPath(cmd) && !where)
+ return null;
+
+ where = where || path.resolve(cmd);
+
+ return common.ShellString(where);
+}
+module.exports = _which;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/package.json
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/package.json b/node_modules/cordova-common/package.json
new file mode 100644
index 0000000..2ec1962
--- /dev/null
+++ b/node_modules/cordova-common/package.json
@@ -0,0 +1,119 @@
+{
+ "_args": [
+ [
+ "cordova-common@^1.0.0",
+ "/Users/steveng/repo/cordova/cordova-osx"
+ ]
+ ],
+ "_from": "cordova-common@>=1.0.0 <2.0.0",
+ "_id": "cordova-common@1.1.0",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/cordova-common",
+ "_nodeVersion": "4.2.3",
+ "_npmOperationalInternal": {
+ "host": "packages-5-east.internal.npmjs.com",
+ "tmp": "tmp/cordova-common-1.1.0.tgz_1455781889491_0.6937742941081524"
+ },
+ "_npmUser": {
+ "email": "kotikov.vladimir@gmail.com",
+ "name": "kotikov.vladimir"
+ },
+ "_npmVersion": "2.14.7",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "cordova-common",
+ "raw": "cordova-common@^1.0.0",
+ "rawSpec": "^1.0.0",
+ "scope": null,
+ "spec": ">=1.0.0 <2.0.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/"
+ ],
+ "_resolved": "http://registry.npmjs.org/cordova-common/-/cordova-common-1.1.0.tgz",
+ "_shasum": "8682721466ee354747ec6241f34f412b7e0ef636",
+ "_shrinkwrap": null,
+ "_spec": "cordova-common@^1.0.0",
+ "_where": "/Users/steveng/repo/cordova/cordova-osx",
+ "author": {
+ "name": "Apache Software Foundation"
+ },
+ "bugs": {
+ "email": "dev@cordova.apache.org",
+ "url": "https://issues.apache.org/jira/browse/CB"
+ },
+ "contributors": [],
+ "dependencies": {
+ "ansi": "^0.3.1",
+ "bplist-parser": "^0.1.0",
+ "cordova-registry-mapper": "^1.1.8",
+ "elementtree": "^0.1.6",
+ "glob": "^5.0.13",
+ "osenv": "^0.1.3",
+ "plist": "^1.2.0",
+ "q": "^1.4.1",
+ "semver": "^5.0.1",
+ "shelljs": "^0.5.1",
+ "underscore": "^1.8.3",
+ "unorm": "^1.3.3"
+ },
+ "description": "Apache Cordova tools and platforms shared routines",
+ "devDependencies": {
+ "istanbul": "^0.3.17",
+ "jasmine-node": "^1.14.5",
+ "jshint": "^2.8.0"
+ },
+ "directories": {},
+ "dist": {
+ "shasum": "8682721466ee354747ec6241f34f412b7e0ef636",
+ "tarball": "http://registry.npmjs.org/cordova-common/-/cordova-common-1.1.0.tgz"
+ },
+ "engineStrict": true,
+ "engines": {
+ "node": ">=0.9.9"
+ },
+ "license": "Apache-2.0",
+ "main": "cordova-common.js",
+ "maintainers": [
+ {
+ "name": "bowserj",
+ "email": "bowserj@apache.org"
+ },
+ {
+ "name": "kotikov.vladimir",
+ "email": "kotikov.vladimir@gmail.com"
+ },
+ {
+ "name": "purplecabbage",
+ "email": "purplecabbage@gmail.com"
+ },
+ {
+ "name": "shazron",
+ "email": "shazron@gmail.com"
+ },
+ {
+ "name": "stevegill",
+ "email": "stevengill97@gmail.com"
+ },
+ {
+ "name": "timbarham",
+ "email": "npmjs@barhams.info"
+ }
+ ],
+ "name": "cordova-common",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git://git-wip-us.apache.org/repos/asf/cordova-common.git"
+ },
+ "scripts": {
+ "cover": "node node_modules/istanbul/lib/cli.js cover --root src --print detail node_modules/jasmine-node/bin/jasmine-node -- spec",
+ "jasmine": "node node_modules/jasmine-node/bin/jasmine-node --captureExceptions --color spec",
+ "jshint": "node node_modules/jshint/bin/jshint src && node node_modules/jshint/bin/jshint spec",
+ "test": "npm run jshint && npm run jasmine"
+ },
+ "version": "1.1.0"
+}
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/.jshintrc
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/.jshintrc b/node_modules/cordova-common/src/.jshintrc
new file mode 100644
index 0000000..89a121c
--- /dev/null
+++ b/node_modules/cordova-common/src/.jshintrc
@@ -0,0 +1,10 @@
+{
+ "node": true
+ , "bitwise": true
+ , "undef": true
+ , "trailing": true
+ , "quotmark": true
+ , "indent": 4
+ , "unused": "vars"
+ , "latedef": "nofunc"
+}
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ActionStack.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ActionStack.js b/node_modules/cordova-common/src/ActionStack.js
new file mode 100644
index 0000000..5ef6f84
--- /dev/null
+++ b/node_modules/cordova-common/src/ActionStack.js
@@ -0,0 +1,85 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* jshint quotmark:false */
+
+var events = require('./events'),
+ Q = require('q');
+
+function ActionStack() {
+ this.stack = [];
+ this.completed = [];
+}
+
+ActionStack.prototype = {
+ createAction:function(handler, action_params, reverter, revert_params) {
+ return {
+ handler:{
+ run:handler,
+ params:action_params
+ },
+ reverter:{
+ run:reverter,
+ params:revert_params
+ }
+ };
+ },
+ push:function(tx) {
+ this.stack.push(tx);
+ },
+ // Returns a promise.
+ process:function(platform) {
+ events.emit('verbose', 'Beginning processing of action stack for ' + platform + ' project...');
+
+ while (this.stack.length) {
+ var action = this.stack.shift();
+ var handler = action.handler.run;
+ var action_params = action.handler.params;
+
+ try {
+ handler.apply(null, action_params);
+ } catch(e) {
+ events.emit('warn', 'Error during processing of action! Attempting to revert...');
+ this.stack.unshift(action);
+ var issue = 'Uh oh!\n';
+ // revert completed tasks
+ while(this.completed.length) {
+ var undo = this.completed.shift();
+ var revert = undo.reverter.run;
+ var revert_params = undo.reverter.params;
+
+ try {
+ revert.apply(null, revert_params);
+ } catch(err) {
+ events.emit('warn', 'Error during reversion of action! We probably really messed up your project now, sorry! D:');
+ issue += 'A reversion action failed: ' + err.message + '\n';
+ }
+ }
+ e.message = issue + e.message;
+ return Q.reject(e);
+ }
+ this.completed.push(action);
+ }
+ events.emit('verbose', 'Action stack processing complete.');
+
+ return Q();
+ }
+};
+
+module.exports = ActionStack;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ConfigChanges/ConfigChanges.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ConfigChanges/ConfigChanges.js b/node_modules/cordova-common/src/ConfigChanges/ConfigChanges.js
new file mode 100644
index 0000000..a914fc8
--- /dev/null
+++ b/node_modules/cordova-common/src/ConfigChanges/ConfigChanges.js
@@ -0,0 +1,323 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/*
+ * This module deals with shared configuration / dependency "stuff". That is:
+ * - XML configuration files such as config.xml, AndroidManifest.xml or WMAppManifest.xml.
+ * - plist files in iOS
+ * Essentially, any type of shared resources that we need to handle with awareness
+ * of how potentially multiple plugins depend on a single shared resource, should be
+ * handled in this module.
+ *
+ * The implementation uses an object as a hash table, with "leaves" of the table tracking
+ * reference counts.
+ */
+
+/* jshint sub:true */
+
+var fs = require('fs'),
+ path = require('path'),
+ et = require('elementtree'),
+ semver = require('semver'),
+ events = require('../events'),
+ ConfigKeeper = require('./ConfigKeeper');
+
+var mungeutil = require('./munge-util');
+
+exports.PlatformMunger = PlatformMunger;
+
+exports.process = function(plugins_dir, project_dir, platform, platformJson, pluginInfoProvider) {
+ var munger = new PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider);
+ munger.process(plugins_dir);
+ munger.save_all();
+};
+
+/******************************************************************************
+* PlatformMunger class
+*
+* Can deal with config file of a single project.
+* Parsed config files are cached in a ConfigKeeper object.
+******************************************************************************/
+function PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider) {
+ this.platform = platform;
+ this.project_dir = project_dir;
+ this.config_keeper = new ConfigKeeper(project_dir);
+ this.platformJson = platformJson;
+ this.pluginInfoProvider = pluginInfoProvider;
+}
+
+// Write out all unsaved files.
+PlatformMunger.prototype.save_all = PlatformMunger_save_all;
+function PlatformMunger_save_all() {
+ this.config_keeper.save_all();
+ this.platformJson.save();
+}
+
+// Apply a munge object to a single config file.
+// The remove parameter tells whether to add the change or remove it.
+PlatformMunger.prototype.apply_file_munge = PlatformMunger_apply_file_munge;
+function PlatformMunger_apply_file_munge(file, munge, remove) {
+ var self = this;
+
+ for (var selector in munge.parents) {
+ for (var xml_child in munge.parents[selector]) {
+ // this xml child is new, graft it (only if config file exists)
+ var config_file = self.config_keeper.get(self.project_dir, self.platform, file);
+ if (config_file.exists) {
+ if (remove) config_file.prune_child(selector, munge.parents[selector][xml_child]);
+ else config_file.graft_child(selector, munge.parents[selector][xml_child]);
+ }
+ }
+ }
+}
+
+
+PlatformMunger.prototype.remove_plugin_changes = remove_plugin_changes;
+function remove_plugin_changes(pluginInfo, is_top_level) {
+ var self = this;
+ var platform_config = self.platformJson.root;
+ var plugin_vars = is_top_level ?
+ platform_config.installed_plugins[pluginInfo.id] :
+ platform_config.dependent_plugins[pluginInfo.id];
+
+ // get config munge, aka how did this plugin change various config files
+ var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
+ // global munge looks at all plugins' changes to config files
+ var global_munge = platform_config.config_munge;
+ var munge = mungeutil.decrement_munge(global_munge, config_munge);
+
+ for (var file in munge.files) {
+ // CB-6976 Windows Universal Apps. Compatibility fix for existing plugins.
+ if (self.platform == 'windows' && file == 'package.appxmanifest' &&
+ !fs.existsSync(path.join(self.project_dir, 'package.appxmanifest'))) {
+ // New windows template separate manifest files for Windows10, Windows8.1 and WP8.1
+ var substs = ['package.phone.appxmanifest', 'package.windows.appxmanifest', 'package.windows10.appxmanifest'];
+ /* jshint loopfunc:true */
+ substs.forEach(function(subst) {
+ events.emit('verbose', 'Applying munge to ' + subst);
+ self.apply_file_munge(subst, munge.files[file], true);
+ });
+ /* jshint loopfunc:false */
+ }
+ self.apply_file_munge(file, munge.files[file], /* remove = */ true);
+ }
+
+ // Remove from installed_plugins
+ self.platformJson.removePlugin(pluginInfo.id, is_top_level);
+ return self;
+}
+
+
+PlatformMunger.prototype.add_plugin_changes = add_plugin_changes;
+function add_plugin_changes(pluginInfo, plugin_vars, is_top_level, should_increment) {
+ var self = this;
+ var platform_config = self.platformJson.root;
+
+ // get config munge, aka how should this plugin change various config files
+ var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
+ // global munge looks at all plugins' changes to config files
+
+ // TODO: The should_increment param is only used by cordova-cli and is going away soon.
+ // If should_increment is set to false, avoid modifying the global_munge (use clone)
+ // and apply the entire config_munge because it's already a proper subset of the global_munge.
+ var munge, global_munge;
+ if (should_increment) {
+ global_munge = platform_config.config_munge;
+ munge = mungeutil.increment_munge(global_munge, config_munge);
+ } else {
+ global_munge = mungeutil.clone_munge(platform_config.config_munge);
+ munge = config_munge;
+ }
+
+ for (var file in munge.files) {
+ // CB-6976 Windows Universal Apps. Compatibility fix for existing plugins.
+ if (self.platform == 'windows' && file == 'package.appxmanifest' &&
+ !fs.existsSync(path.join(self.project_dir, 'package.appxmanifest'))) {
+ var substs = ['package.phone.appxmanifest', 'package.windows.appxmanifest', 'package.windows10.appxmanifest'];
+ /* jshint loopfunc:true */
+ substs.forEach(function(subst) {
+ events.emit('verbose', 'Applying munge to ' + subst);
+ self.apply_file_munge(subst, munge.files[file]);
+ });
+ /* jshint loopfunc:false */
+ }
+ self.apply_file_munge(file, munge.files[file]);
+ }
+
+ // Move to installed/dependent_plugins
+ self.platformJson.addPlugin(pluginInfo.id, plugin_vars || {}, is_top_level);
+ return self;
+}
+
+
+// Load the global munge from platform json and apply all of it.
+// Used by cordova prepare to re-generate some config file from platform
+// defaults and the global munge.
+PlatformMunger.prototype.reapply_global_munge = reapply_global_munge ;
+function reapply_global_munge () {
+ var self = this;
+
+ var platform_config = self.platformJson.root;
+ var global_munge = platform_config.config_munge;
+ for (var file in global_munge.files) {
+ self.apply_file_munge(file, global_munge.files[file]);
+ }
+
+ return self;
+}
+
+
+// generate_plugin_config_munge
+// Generate the munge object from plugin.xml + vars
+PlatformMunger.prototype.generate_plugin_config_munge = generate_plugin_config_munge;
+function generate_plugin_config_munge(pluginInfo, vars) {
+ var self = this;
+
+ vars = vars || {};
+ var munge = { files: {} };
+ var changes = pluginInfo.getConfigFiles(self.platform);
+
+ // Demux 'package.appxmanifest' into relevant platform-specific appx manifests.
+ // Only spend the cycles if there are version-specific plugin settings
+ if (self.platform === 'windows' &&
+ changes.some(function(change) {
+ return ((typeof change.versions !== 'undefined') ||
+ (typeof change.deviceTarget !== 'undefined'));
+ }))
+ {
+ var manifests = {
+ 'windows': {
+ '8.1.0': 'package.windows.appxmanifest',
+ '10.0.0': 'package.windows10.appxmanifest'
+ },
+ 'phone': {
+ '8.1.0': 'package.phone.appxmanifest',
+ '10.0.0': 'package.windows10.appxmanifest'
+ },
+ 'all': {
+ '8.1.0': ['package.windows.appxmanifest', 'package.phone.appxmanifest'],
+ '10.0.0': 'package.windows10.appxmanifest'
+ }
+ };
+
+ var oldChanges = changes;
+ changes = [];
+
+ oldChanges.forEach(function(change, changeIndex) {
+ // Only support semver/device-target demux for package.appxmanifest
+ // Pass through in case something downstream wants to use it
+ if (change.target !== 'package.appxmanifest') {
+ changes.push(change);
+ return;
+ }
+
+ var hasVersion = (typeof change.versions !== 'undefined');
+ var hasTargets = (typeof change.deviceTarget !== 'undefined');
+
+ // No semver/device-target for this config-file, pass it through
+ if (!(hasVersion || hasTargets)) {
+ changes.push(change);
+ return;
+ }
+
+ var targetDeviceSet = hasTargets ? change.deviceTarget : 'all';
+ if (['windows', 'phone', 'all'].indexOf(targetDeviceSet) === -1) {
+ // target-device couldn't be resolved, fix it up here to a valid value
+ targetDeviceSet = 'all';
+ }
+ var knownWindowsVersionsForTargetDeviceSet = Object.keys(manifests[targetDeviceSet]);
+
+ // at this point, 'change' targets package.appxmanifest and has a version attribute
+ knownWindowsVersionsForTargetDeviceSet.forEach(function(winver) {
+ // This is a local function that creates the new replacement representing the
+ // mutation. Used to save code further down.
+ var createReplacement = function(manifestFile, originalChange) {
+ var replacement = {
+ target: manifestFile,
+ parent: originalChange.parent,
+ after: originalChange.after,
+ xmls: originalChange.xmls,
+ versions: originalChange.versions,
+ deviceTarget: originalChange.deviceTarget
+ };
+ return replacement;
+ };
+
+ // version doesn't satisfy, so skip
+ if (hasVersion && !semver.satisfies(winver, change.versions)) {
+ return;
+ }
+
+ var versionSpecificManifests = manifests[targetDeviceSet][winver];
+ if (versionSpecificManifests.constructor === Array) {
+ // e.g. all['8.1.0'] === ['pkg.windows.appxmanifest', 'pkg.phone.appxmanifest']
+ versionSpecificManifests.forEach(function(manifestFile) {
+ changes.push(createReplacement(manifestFile, change));
+ });
+ }
+ else {
+ // versionSpecificManifests is actually a single string
+ changes.push(createReplacement(versionSpecificManifests, change));
+ }
+ });
+ });
+ }
+
+ changes.forEach(function(change) {
+ change.xmls.forEach(function(xml) {
+ // 1. stringify each xml
+ var stringified = (new et.ElementTree(xml)).write({xml_declaration:false});
+ // interp vars
+ if (vars) {
+ Object.keys(vars).forEach(function(key) {
+ var regExp = new RegExp('\\$' + key, 'g');
+ stringified = stringified.replace(regExp, vars[key]);
+ });
+ }
+ // 2. add into munge
+ mungeutil.deep_add(munge, change.target, change.parent, { xml: stringified, count: 1, after: change.after });
+ });
+ });
+ return munge;
+}
+
+// Go over the prepare queue and apply the config munges for each plugin
+// that has been (un)installed.
+PlatformMunger.prototype.process = PlatformMunger_process;
+function PlatformMunger_process(plugins_dir) {
+ var self = this;
+ var platform_config = self.platformJson.root;
+
+ // Uninstallation first
+ platform_config.prepare_queue.uninstalled.forEach(function(u) {
+ var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
+ self.remove_plugin_changes(pluginInfo, u.topLevel);
+ });
+
+ // Now handle installation
+ platform_config.prepare_queue.installed.forEach(function(u) {
+ var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
+ self.add_plugin_changes(pluginInfo, u.vars, u.topLevel, true);
+ });
+
+ // Empty out installed/ uninstalled queues.
+ platform_config.prepare_queue.uninstalled = [];
+ platform_config.prepare_queue.installed = [];
+}
+/**** END of PlatformMunger ****/
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ConfigChanges/ConfigFile.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ConfigChanges/ConfigFile.js b/node_modules/cordova-common/src/ConfigChanges/ConfigFile.js
new file mode 100644
index 0000000..dd9ebbc
--- /dev/null
+++ b/node_modules/cordova-common/src/ConfigChanges/ConfigFile.js
@@ -0,0 +1,208 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+var fs = require('fs');
+var path = require('path');
+
+var bplist = require('bplist-parser');
+var et = require('elementtree');
+var glob = require('glob');
+var plist = require('plist');
+
+var plist_helpers = require('../util/plist-helpers');
+var xml_helpers = require('../util/xml-helpers');
+
+/******************************************************************************
+* ConfigFile class
+*
+* Can load and keep various types of config files. Provides some functionality
+* specific to some file types such as grafting XML children. In most cases it
+* should be instantiated by ConfigKeeper.
+*
+* For plugin.xml files use as:
+* plugin_config = self.config_keeper.get(plugin_dir, '', 'plugin.xml');
+*
+* TODO: Consider moving it out to a separate file and maybe partially with
+* overrides in platform handlers.
+******************************************************************************/
+function ConfigFile(project_dir, platform, file_tag) {
+ this.project_dir = project_dir;
+ this.platform = platform;
+ this.file_tag = file_tag;
+ this.is_changed = false;
+
+ this.load();
+}
+
+// ConfigFile.load()
+ConfigFile.prototype.load = ConfigFile_load;
+function ConfigFile_load() {
+ var self = this;
+
+ // config file may be in a place not exactly specified in the target
+ var filepath = self.filepath = resolveConfigFilePath(self.project_dir, self.platform, self.file_tag);
+
+ if ( !filepath || !fs.existsSync(filepath) ) {
+ self.exists = false;
+ return;
+ }
+ self.exists = true;
+ self.mtime = fs.statSync(self.filepath).mtime;
+
+ var ext = path.extname(filepath);
+ // Windows8 uses an appxmanifest, and wp8 will likely use
+ // the same in a future release
+ if (ext == '.xml' || ext == '.appxmanifest') {
+ self.type = 'xml';
+ self.data = xml_helpers.parseElementtreeSync(filepath);
+ } else {
+ // plist file
+ self.type = 'plist';
+ // TODO: isBinaryPlist() reads the file and then parse re-reads it again.
+ // We always write out text plist, not binary.
+ // Do we still need to support binary plist?
+ // If yes, use plist.parseStringSync() and read the file once.
+ self.data = isBinaryPlist(filepath) ?
+ bplist.parseBuffer(fs.readFileSync(filepath)) :
+ plist.parse(fs.readFileSync(filepath, 'utf8'));
+ }
+}
+
+ConfigFile.prototype.save = function ConfigFile_save() {
+ var self = this;
+ if (self.type === 'xml') {
+ fs.writeFileSync(self.filepath, self.data.write({indent: 4}), 'utf-8');
+ } else {
+ // plist
+ var regExp = new RegExp('<string>[ \t\r\n]+?</string>', 'g');
+ fs.writeFileSync(self.filepath, plist.build(self.data).replace(regExp, '<string></string>'));
+ }
+ self.is_changed = false;
+};
+
+ConfigFile.prototype.graft_child = function ConfigFile_graft_child(selector, xml_child) {
+ var self = this;
+ var filepath = self.filepath;
+ var result;
+ if (self.type === 'xml') {
+ var xml_to_graft = [et.XML(xml_child.xml)];
+ result = xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
+ if ( !result) {
+ throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
+ }
+ } else {
+ // plist file
+ result = plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
+ if ( !result ) {
+ throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
+ }
+ }
+ self.is_changed = true;
+};
+
+ConfigFile.prototype.prune_child = function ConfigFile_prune_child(selector, xml_child) {
+ var self = this;
+ var filepath = self.filepath;
+ var result;
+ if (self.type === 'xml') {
+ var xml_to_graft = [et.XML(xml_child.xml)];
+ result = xml_helpers.pruneXML(self.data, xml_to_graft, selector);
+ } else {
+ // plist file
+ result = plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
+ }
+ if (!result) {
+ var err_msg = 'Pruning at selector "' + selector + '" from "' + filepath + '" went bad.';
+ throw new Error(err_msg);
+ }
+ self.is_changed = true;
+};
+
+// Some config-file target attributes are not qualified with a full leading directory, or contain wildcards.
+// Resolve to a real path in this function.
+// TODO: getIOSProjectname is slow because of glob, try to avoid calling it several times per project.
+function resolveConfigFilePath(project_dir, platform, file) {
+ var filepath = path.join(project_dir, file);
+ var matches;
+
+ if (file.indexOf('*') > -1) {
+ // handle wildcards in targets using glob.
+ matches = glob.sync(path.join(project_dir, '**', file));
+ if (matches.length) filepath = matches[0];
+
+ // [CB-5989] multiple Info.plist files may exist. default to $PROJECT_NAME-Info.plist
+ if(matches.length > 1 && file.indexOf('-Info.plist')>-1){
+ var plistName = getIOSProjectname(project_dir)+'-Info.plist';
+ for (var i=0; i < matches.length; i++) {
+ if(matches[i].indexOf(plistName) > -1){
+ filepath = matches[i];
+ break;
+ }
+ }
+ }
+ return filepath;
+ }
+
+ // special-case config.xml target that is just "config.xml". This should be resolved to the real location of the file.
+ // TODO: move the logic that contains the locations of config.xml from cordova CLI into plugman.
+ if (file == 'config.xml') {
+ if (platform == 'ubuntu') {
+ filepath = path.join(project_dir, 'config.xml');
+ } else if (platform == 'ios') {
+ var iospath = getIOSProjectname(project_dir);
+ filepath = path.join(project_dir,iospath, 'config.xml');
+ } else if (platform == 'android') {
+ filepath = path.join(project_dir, 'res', 'xml', 'config.xml');
+ } else {
+ matches = glob.sync(path.join(project_dir, '**', 'config.xml'));
+ if (matches.length) filepath = matches[0];
+ }
+ return filepath;
+ }
+
+ // None of the special cases matched, returning project_dir/file.
+ return filepath;
+}
+
+// Find out the real name of an iOS project
+// TODO: glob is slow, need a better way or caching, or avoid using more than once.
+function getIOSProjectname(project_dir) {
+ var matches = glob.sync(path.join(project_dir, '*.xcodeproj'));
+ var iospath;
+ if (matches.length === 1) {
+ iospath = path.basename(matches[0],'.xcodeproj');
+ } else {
+ var msg;
+ if (matches.length === 0) {
+ msg = 'Does not appear to be an xcode project, no xcode project file in ' + project_dir;
+ } else {
+ msg = 'There are multiple *.xcodeproj dirs in ' + project_dir;
+ }
+ throw new Error(msg);
+ }
+ return iospath;
+}
+
+// determine if a plist file is binary
+function isBinaryPlist(filename) {
+ // I wish there was a synchronous way to read only the first 6 bytes of a
+ // file. This is wasteful :/
+ var buf = '' + fs.readFileSync(filename, 'utf8');
+ // binary plists start with a magic header, "bplist"
+ return buf.substring(0, 6) === 'bplist';
+}
+
+module.exports = ConfigFile;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ConfigChanges/ConfigKeeper.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ConfigChanges/ConfigKeeper.js b/node_modules/cordova-common/src/ConfigChanges/ConfigKeeper.js
new file mode 100644
index 0000000..894e922
--- /dev/null
+++ b/node_modules/cordova-common/src/ConfigChanges/ConfigKeeper.js
@@ -0,0 +1,65 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+/* jshint sub:true */
+
+var path = require('path');
+var ConfigFile = require('./ConfigFile');
+
+/******************************************************************************
+* ConfigKeeper class
+*
+* Used to load and store config files to avoid re-parsing and writing them out
+* multiple times.
+*
+* The config files are referred to by a fake path constructed as
+* project_dir/platform/file
+* where file is the name used for the file in config munges.
+******************************************************************************/
+function ConfigKeeper(project_dir, plugins_dir) {
+ this.project_dir = project_dir;
+ this.plugins_dir = plugins_dir;
+ this._cached = {};
+}
+
+ConfigKeeper.prototype.get = function ConfigKeeper_get(project_dir, platform, file) {
+ var self = this;
+
+ // This fixes a bug with older plugins - when specifying config xml instead of res/xml/config.xml
+ // https://issues.apache.org/jira/browse/CB-6414
+ if(file == 'config.xml' && platform == 'android'){
+ file = 'res/xml/config.xml';
+ }
+ var fake_path = path.join(project_dir, platform, file);
+
+ if (self._cached[fake_path]) {
+ return self._cached[fake_path];
+ }
+ // File was not cached, need to load.
+ var config_file = new ConfigFile(project_dir, platform, file);
+ self._cached[fake_path] = config_file;
+ return config_file;
+};
+
+
+ConfigKeeper.prototype.save_all = function ConfigKeeper_save_all() {
+ var self = this;
+ Object.keys(self._cached).forEach(function (fake_path) {
+ var config_file = self._cached[fake_path];
+ if (config_file.is_changed) config_file.save();
+ });
+};
+
+module.exports = ConfigKeeper;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ConfigChanges/munge-util.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ConfigChanges/munge-util.js b/node_modules/cordova-common/src/ConfigChanges/munge-util.js
new file mode 100644
index 0000000..307b3c1
--- /dev/null
+++ b/node_modules/cordova-common/src/ConfigChanges/munge-util.js
@@ -0,0 +1,160 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+/* jshint sub:true */
+
+var _ = require('underscore');
+
+// add the count of [key1][key2]...[keyN] to obj
+// return true if it didn't exist before
+exports.deep_add = function deep_add(obj, keys /* or key1, key2 .... */ ) {
+ if ( !Array.isArray(keys) ) {
+ keys = Array.prototype.slice.call(arguments, 1);
+ }
+
+ return exports.process_munge(obj, true/*createParents*/, function (parentArray, k) {
+ var found = _.find(parentArray, function(element) {
+ return element.xml == k.xml;
+ });
+ if (found) {
+ found.after = found.after || k.after;
+ found.count += k.count;
+ } else {
+ parentArray.push(k);
+ }
+ return !found;
+ }, keys);
+};
+
+// decrement the count of [key1][key2]...[keyN] from obj and remove if it reaches 0
+// return true if it was removed or not found
+exports.deep_remove = function deep_remove(obj, keys /* or key1, key2 .... */ ) {
+ if ( !Array.isArray(keys) ) {
+ keys = Array.prototype.slice.call(arguments, 1);
+ }
+
+ var result = exports.process_munge(obj, false/*createParents*/, function (parentArray, k) {
+ var index = -1;
+ var found = _.find(parentArray, function (element) {
+ index++;
+ return element.xml == k.xml;
+ });
+ if (found) {
+ found.count -= k.count;
+ if (found.count > 0) {
+ return false;
+ }
+ else {
+ parentArray.splice(index, 1);
+ }
+ }
+ return undefined;
+ }, keys);
+
+ return typeof result === 'undefined' ? true : result;
+};
+
+// search for [key1][key2]...[keyN]
+// return the object or undefined if not found
+exports.deep_find = function deep_find(obj, keys /* or key1, key2 .... */ ) {
+ if ( !Array.isArray(keys) ) {
+ keys = Array.prototype.slice.call(arguments, 1);
+ }
+
+ return exports.process_munge(obj, false/*createParents?*/, function (parentArray, k) {
+ return _.find(parentArray, function (element) {
+ return element.xml == (k.xml || k);
+ });
+ }, keys);
+};
+
+// Execute func passing it the parent array and the xmlChild key.
+// When createParents is true, add the file and parent items they are missing
+// When createParents is false, stop and return undefined if the file and/or parent items are missing
+
+exports.process_munge = function process_munge(obj, createParents, func, keys /* or key1, key2 .... */ ) {
+ if ( !Array.isArray(keys) ) {
+ keys = Array.prototype.slice.call(arguments, 1);
+ }
+ var k = keys[0];
+ if (keys.length == 1) {
+ return func(obj, k);
+ } else if (keys.length == 2) {
+ if (!obj.parents[k] && !createParents) {
+ return undefined;
+ }
+ obj.parents[k] = obj.parents[k] || [];
+ return exports.process_munge(obj.parents[k], createParents, func, keys.slice(1));
+ } else if (keys.length == 3){
+ if (!obj.files[k] && !createParents) {
+ return undefined;
+ }
+ obj.files[k] = obj.files[k] || { parents: {} };
+ return exports.process_munge(obj.files[k], createParents, func, keys.slice(1));
+ } else {
+ throw new Error('Invalid key format. Must contain at most 3 elements (file, parent, xmlChild).');
+ }
+};
+
+// All values from munge are added to base as
+// base[file][selector][child] += munge[file][selector][child]
+// Returns a munge object containing values that exist in munge
+// but not in base.
+exports.increment_munge = function increment_munge(base, munge) {
+ var diff = { files: {} };
+
+ for (var file in munge.files) {
+ for (var selector in munge.files[file].parents) {
+ for (var xml_child in munge.files[file].parents[selector]) {
+ var val = munge.files[file].parents[selector][xml_child];
+ // if node not in base, add it to diff and base
+ // else increment it's value in base without adding to diff
+ var newlyAdded = exports.deep_add(base, [file, selector, val]);
+ if (newlyAdded) {
+ exports.deep_add(diff, file, selector, val);
+ }
+ }
+ }
+ }
+ return diff;
+};
+
+// Update the base munge object as
+// base[file][selector][child] -= munge[file][selector][child]
+// nodes that reached zero value are removed from base and added to the returned munge
+// object.
+exports.decrement_munge = function decrement_munge(base, munge) {
+ var zeroed = { files: {} };
+
+ for (var file in munge.files) {
+ for (var selector in munge.files[file].parents) {
+ for (var xml_child in munge.files[file].parents[selector]) {
+ var val = munge.files[file].parents[selector][xml_child];
+ // if node not in base, add it to diff and base
+ // else increment it's value in base without adding to diff
+ var removed = exports.deep_remove(base, [file, selector, val]);
+ if (removed) {
+ exports.deep_add(zeroed, file, selector, val);
+ }
+ }
+ }
+ }
+ return zeroed;
+};
+
+// For better readability where used
+exports.clone_munge = function clone_munge(munge) {
+ return exports.increment_munge({}, munge);
+};
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ConfigParser/ConfigParser.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ConfigParser/ConfigParser.js b/node_modules/cordova-common/src/ConfigParser/ConfigParser.js
new file mode 100644
index 0000000..7abddf6
--- /dev/null
+++ b/node_modules/cordova-common/src/ConfigParser/ConfigParser.js
@@ -0,0 +1,499 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* jshint sub:true */
+
+var et = require('elementtree'),
+ xml= require('../util/xml-helpers'),
+ CordovaError = require('../CordovaError/CordovaError'),
+ fs = require('fs'),
+ events = require('../events');
+
+
+/** Wraps a config.xml file */
+function ConfigParser(path) {
+ this.path = path;
+ try {
+ this.doc = xml.parseElementtreeSync(path);
+ this.cdvNamespacePrefix = getCordovaNamespacePrefix(this.doc);
+ et.register_namespace(this.cdvNamespacePrefix, 'http://cordova.apache.org/ns/1.0');
+ } catch (e) {
+ console.error('Parsing '+path+' failed');
+ throw e;
+ }
+ var r = this.doc.getroot();
+ if (r.tag !== 'widget') {
+ throw new CordovaError(path + ' has incorrect root node name (expected "widget", was "' + r.tag + '")');
+ }
+}
+
+function getNodeTextSafe(el) {
+ return el && el.text && el.text.trim();
+}
+
+function findOrCreate(doc, name) {
+ var ret = doc.find(name);
+ if (!ret) {
+ ret = new et.Element(name);
+ doc.getroot().append(ret);
+ }
+ return ret;
+}
+
+function getCordovaNamespacePrefix(doc){
+ var rootAtribs = Object.getOwnPropertyNames(doc.getroot().attrib);
+ var prefix = 'cdv';
+ for (var j = 0; j < rootAtribs.length; j++ ) {
+ if(rootAtribs[j].indexOf('xmlns:') === 0 &&
+ doc.getroot().attrib[rootAtribs[j]] === 'http://cordova.apache.org/ns/1.0'){
+ var strings = rootAtribs[j].split(':');
+ prefix = strings[1];
+ break;
+ }
+ }
+ return prefix;
+}
+
+/**
+ * Finds the value of an element's attribute
+ * @param {String} attributeName Name of the attribute to search for
+ * @param {Array} elems An array of ElementTree nodes
+ * @return {String}
+ */
+function findElementAttributeValue(attributeName, elems) {
+
+ elems = Array.isArray(elems) ? elems : [ elems ];
+
+ var value = elems.filter(function (elem) {
+ return elem.attrib.name.toLowerCase() === attributeName.toLowerCase();
+ }).map(function (filteredElems) {
+ return filteredElems.attrib.value;
+ }).pop();
+
+ return value ? value : '';
+}
+
+ConfigParser.prototype = {
+ packageName: function(id) {
+ return this.doc.getroot().attrib['id'];
+ },
+ setPackageName: function(id) {
+ this.doc.getroot().attrib['id'] = id;
+ },
+ android_packageName: function() {
+ return this.doc.getroot().attrib['android-packageName'];
+ },
+ android_activityName: function() {
+ return this.doc.getroot().attrib['android-activityName'];
+ },
+ ios_CFBundleIdentifier: function() {
+ return this.doc.getroot().attrib['ios-CFBundleIdentifier'];
+ },
+ name: function() {
+ return getNodeTextSafe(this.doc.find('name'));
+ },
+ setName: function(name) {
+ var el = findOrCreate(this.doc, 'name');
+ el.text = name;
+ },
+ description: function() {
+ return getNodeTextSafe(this.doc.find('description'));
+ },
+ setDescription: function(text) {
+ var el = findOrCreate(this.doc, 'description');
+ el.text = text;
+ },
+ version: function() {
+ return this.doc.getroot().attrib['version'];
+ },
+ windows_packageVersion: function() {
+ return this.doc.getroot().attrib('windows-packageVersion');
+ },
+ android_versionCode: function() {
+ return this.doc.getroot().attrib['android-versionCode'];
+ },
+ ios_CFBundleVersion: function() {
+ return this.doc.getroot().attrib['ios-CFBundleVersion'];
+ },
+ setVersion: function(value) {
+ this.doc.getroot().attrib['version'] = value;
+ },
+ author: function() {
+ return getNodeTextSafe(this.doc.find('author'));
+ },
+ getGlobalPreference: function (name) {
+ return findElementAttributeValue(name, this.doc.findall('preference'));
+ },
+ setGlobalPreference: function (name, value) {
+ var pref = this.doc.find('preference[@name="' + name + '"]');
+ if (!pref) {
+ pref = new et.Element('preference');
+ pref.attrib.name = name;
+ this.doc.getroot().append(pref);
+ }
+ pref.attrib.value = value;
+ },
+ getPlatformPreference: function (name, platform) {
+ return findElementAttributeValue(name, this.doc.findall('platform[@name=\'' + platform + '\']/preference'));
+ },
+ getPreference: function(name, platform) {
+
+ var platformPreference = '';
+
+ if (platform) {
+ platformPreference = this.getPlatformPreference(name, platform);
+ }
+
+ return platformPreference ? platformPreference : this.getGlobalPreference(name);
+
+ },
+ /**
+ * Returns all resources for the platform specified.
+ * @param {String} platform The platform.
+ * @param {string} resourceName Type of static resources to return.
+ * "icon" and "splash" currently supported.
+ * @return {Array} Resources for the platform specified.
+ */
+ getStaticResources: function(platform, resourceName) {
+ var ret = [],
+ staticResources = [];
+ if (platform) { // platform specific icons
+ this.doc.findall('platform[@name=\'' + platform + '\']/' + resourceName).forEach(function(elt){
+ elt.platform = platform; // mark as platform specific resource
+ staticResources.push(elt);
+ });
+ }
+ // root level resources
+ staticResources = staticResources.concat(this.doc.findall(resourceName));
+ // parse resource elements
+ var that = this;
+ staticResources.forEach(function (elt) {
+ var res = {};
+ res.src = elt.attrib.src;
+ res.density = elt.attrib['density'] || elt.attrib[that.cdvNamespacePrefix+':density'] || elt.attrib['gap:density'];
+ res.platform = elt.platform || null; // null means icon represents default icon (shared between platforms)
+ res.width = +elt.attrib.width || undefined;
+ res.height = +elt.attrib.height || undefined;
+
+ // default icon
+ if (!res.width && !res.height && !res.density) {
+ ret.defaultResource = res;
+ }
+ ret.push(res);
+ });
+
+ /**
+ * Returns resource with specified width and/or height.
+ * @param {number} width Width of resource.
+ * @param {number} height Height of resource.
+ * @return {Resource} Resource object or null if not found.
+ */
+ ret.getBySize = function(width, height) {
+ return ret.filter(function(res) {
+ if (!res.width && !res.height) {
+ return false;
+ }
+ return ((!res.width || (width == res.width)) &&
+ (!res.height || (height == res.height)));
+ })[0] || null;
+ };
+
+ /**
+ * Returns resource with specified density.
+ * @param {string} density Density of resource.
+ * @return {Resource} Resource object or null if not found.
+ */
+ ret.getByDensity = function(density) {
+ return ret.filter(function(res) {
+ return res.density == density;
+ })[0] || null;
+ };
+
+ /** Returns default icons */
+ ret.getDefault = function() {
+ return ret.defaultResource;
+ };
+
+ return ret;
+ },
+
+ /**
+ * Returns all icons for specific platform.
+ * @param {string} platform Platform name
+ * @return {Resource[]} Array of icon objects.
+ */
+ getIcons: function(platform) {
+ return this.getStaticResources(platform, 'icon');
+ },
+
+ /**
+ * Returns all splash images for specific platform.
+ * @param {string} platform Platform name
+ * @return {Resource[]} Array of Splash objects.
+ */
+ getSplashScreens: function(platform) {
+ return this.getStaticResources(platform, 'splash');
+ },
+
+ /**
+ * Returns all hook scripts for the hook type specified.
+ * @param {String} hook The hook type.
+ * @param {Array} platforms Platforms to look for scripts into (root scripts will be included as well).
+ * @return {Array} Script elements.
+ */
+ getHookScripts: function(hook, platforms) {
+ var self = this;
+ var scriptElements = self.doc.findall('./hook');
+
+ if(platforms) {
+ platforms.forEach(function (platform) {
+ scriptElements = scriptElements.concat(self.doc.findall('./platform[@name="' + platform + '"]/hook'));
+ });
+ }
+
+ function filterScriptByHookType(el) {
+ return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
+ }
+
+ return scriptElements.filter(filterScriptByHookType);
+ },
+ /**
+ * Returns a list of plugin (IDs).
+ *
+ * This function also returns any plugin's that
+ * were defined using the legacy <feature> tags.
+ * @return {string[]} Array of plugin IDs
+ */
+ getPluginIdList: function () {
+ var plugins = this.doc.findall('plugin');
+ var result = plugins.map(function(plugin){
+ return plugin.attrib.name;
+ });
+ var features = this.doc.findall('feature');
+ features.forEach(function(element ){
+ var idTag = element.find('./param[@name="id"]');
+ if(idTag){
+ result.push(idTag.attrib.value);
+ }
+ });
+ return result;
+ },
+ getPlugins: function () {
+ return this.getPluginIdList().map(function (pluginId) {
+ return this.getPlugin(pluginId);
+ }, this);
+ },
+ /**
+ * Adds a plugin element. Does not check for duplicates.
+ * @name addPlugin
+ * @function
+ * @param {object} attributes name and spec are supported
+ * @param {Array|object} variables name, value or arbitary object
+ */
+ addPlugin: function (attributes, variables) {
+ if (!attributes && !attributes.name) return;
+ var el = new et.Element('plugin');
+ el.attrib.name = attributes.name;
+ if (attributes.spec) {
+ el.attrib.spec = attributes.spec;
+ }
+
+ // support arbitrary object as variables source
+ if (variables && typeof variables === 'object' && !Array.isArray(variables)) {
+ variables = Object.keys(variables)
+ .map(function (variableName) {
+ return {name: variableName, value: variables[variableName]};
+ });
+ }
+
+ if (variables) {
+ variables.forEach(function (variable) {
+ el.append(new et.Element('variable', { name: variable.name, value: variable.value }));
+ });
+ }
+ this.doc.getroot().append(el);
+ },
+ /**
+ * Retrives the plugin with the given id or null if not found.
+ *
+ * This function also returns any plugin's that
+ * were defined using the legacy <feature> tags.
+ * @name getPlugin
+ * @function
+ * @param {String} id
+ * @returns {object} plugin including any variables
+ */
+ getPlugin: function(id){
+ if(!id){
+ return undefined;
+ }
+ var pluginElement = this.doc.find('./plugin/[@name="' + id + '"]');
+ if (null === pluginElement) {
+ var legacyFeature = this.doc.find('./feature/param[@name="id"][@value="' + id + '"]/..');
+ if(legacyFeature){
+ events.emit('log', 'Found deprecated feature entry for ' + id +' in config.xml.');
+ return featureToPlugin(legacyFeature);
+ }
+ return undefined;
+ }
+ var plugin = {};
+
+ plugin.name = pluginElement.attrib.name;
+ plugin.spec = pluginElement.attrib.spec || pluginElement.attrib.src || pluginElement.attrib.version;
+ plugin.variables = {};
+ var variableElements = pluginElement.findall('variable');
+ variableElements.forEach(function(varElement){
+ var name = varElement.attrib.name;
+ var value = varElement.attrib.value;
+ if(name){
+ plugin.variables[name] = value;
+ }
+ });
+ return plugin;
+ },
+ /**
+ * Remove the plugin entry with give name (id).
+ *
+ * This function also operates on any plugin's that
+ * were defined using the legacy <feature> tags.
+ * @name removePlugin
+ * @function
+ * @param id name of the plugin
+ */
+ removePlugin: function(id){
+ if(id){
+ var plugins = this.doc.findall('./plugin/[@name="' + id + '"]')
+ .concat(this.doc.findall('./feature/param[@name="id"][@value="' + id + '"]/..'));
+ var children = this.doc.getroot().getchildren();
+ plugins.forEach(function (plugin) {
+ var idx = children.indexOf(plugin);
+ if (idx > -1) {
+ children.splice(idx, 1);
+ }
+ });
+ }
+ },
+
+ // Add any element to the root
+ addElement: function(name, attributes) {
+ var el = et.Element(name);
+ for (var a in attributes) {
+ el.attrib[a] = attributes[a];
+ }
+ this.doc.getroot().append(el);
+ },
+
+ /**
+ * Adds an engine. Does not check for duplicates.
+ * @param {String} name the engine name
+ * @param {String} spec engine source location or version (optional)
+ */
+ addEngine: function(name, spec){
+ if(!name) return;
+ var el = et.Element('engine');
+ el.attrib.name = name;
+ if(spec){
+ el.attrib.spec = spec;
+ }
+ this.doc.getroot().append(el);
+ },
+ /**
+ * Removes all the engines with given name
+ * @param {String} name the engine name.
+ */
+ removeEngine: function(name){
+ var engines = this.doc.findall('./engine/[@name="' +name+'"]');
+ for(var i=0; i < engines.length; i++){
+ var children = this.doc.getroot().getchildren();
+ var idx = children.indexOf(engines[i]);
+ if(idx > -1){
+ children.splice(idx,1);
+ }
+ }
+ },
+ getEngines: function(){
+ var engines = this.doc.findall('./engine');
+ return engines.map(function(engine){
+ var spec = engine.attrib.spec || engine.attrib.version;
+ return {
+ 'name': engine.attrib.name,
+ 'spec': spec ? spec : null
+ };
+ });
+ },
+ /* Get all the access tags */
+ getAccesses: function() {
+ var accesses = this.doc.findall('./access');
+ return accesses.map(function(access){
+ var minimum_tls_version = access.attrib['minimum-tls-version']; /* String */
+ var requires_forward_secrecy = access.attrib['requires-forward-secrecy']; /* Boolean */
+ return {
+ 'origin': access.attrib.origin,
+ 'minimum_tls_version': minimum_tls_version,
+ 'requires_forward_secrecy' : requires_forward_secrecy
+ };
+ });
+ },
+ /* Get all the allow-navigation tags */
+ getAllowNavigations: function() {
+ var allow_navigations = this.doc.findall('./allow-navigation');
+ return allow_navigations.map(function(allow_navigation){
+ var minimum_tls_version = allow_navigation.attrib['minimum-tls-version']; /* String */
+ var requires_forward_secrecy = allow_navigation.attrib['requires-forward-secrecy']; /* Boolean */
+ return {
+ 'href': allow_navigation.attrib.href,
+ 'minimum_tls_version': minimum_tls_version,
+ 'requires_forward_secrecy' : requires_forward_secrecy
+ };
+ });
+ },
+ write:function() {
+ fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
+ }
+};
+
+function featureToPlugin(featureElement) {
+ var plugin = {};
+ plugin.variables = [];
+ var pluginVersion,
+ pluginSrc;
+
+ var nodes = featureElement.findall('param');
+ nodes.forEach(function (element) {
+ var n = element.attrib.name;
+ var v = element.attrib.value;
+ if (n === 'id') {
+ plugin.name = v;
+ } else if (n === 'version') {
+ pluginVersion = v;
+ } else if (n === 'url' || n === 'installPath') {
+ pluginSrc = v;
+ } else {
+ plugin.variables[n] = v;
+ }
+ });
+
+ var spec = pluginSrc || pluginVersion;
+ if (spec) {
+ plugin.spec = spec;
+ }
+
+ return plugin;
+}
+module.exports = ConfigParser;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/ConfigParser/README.md
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/ConfigParser/README.md b/node_modules/cordova-common/src/ConfigParser/README.md
new file mode 100644
index 0000000..e5cd1bf
--- /dev/null
+++ b/node_modules/cordova-common/src/ConfigParser/README.md
@@ -0,0 +1,86 @@
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+
+# Cordova-Lib
+
+## ConfigParser
+
+wraps a valid cordova config.xml file
+
+### Usage
+
+### Include the ConfigParser module in a projet
+
+ var ConfigParser = require('cordova-lib').configparser;
+
+### Create a new ConfigParser
+
+ var config = new ConfigParser('path/to/config/xml/');
+
+### Utility Functions
+
+#### packageName(id)
+returns document root 'id' attribute value
+#### Usage
+
+ config.packageName: function(id)
+
+/*
+ * sets document root element 'id' attribute to @id
+ *
+ * @id - new id value
+ *
+ */
+#### setPackageName(id)
+set document root 'id' attribute to
+ function(id) {
+ this.doc.getroot().attrib['id'] = id;
+ },
+
+###
+ name: function() {
+ return getNodeTextSafe(this.doc.find('name'));
+ },
+ setName: function(name) {
+ var el = findOrCreate(this.doc, 'name');
+ el.text = name;
+ },
+
+### read the description element
+
+ config.description()
+
+ var text = "New and improved description of App"
+ setDescription(text)
+
+### version management
+ version()
+ android_versionCode()
+ ios_CFBundleVersion()
+ setVersion()
+
+### read author element
+
+ config.author();
+
+### read preference
+
+ config.getPreference(name);
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/CordovaError/CordovaError.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/CordovaError/CordovaError.js b/node_modules/cordova-common/src/CordovaError/CordovaError.js
new file mode 100644
index 0000000..7262448
--- /dev/null
+++ b/node_modules/cordova-common/src/CordovaError/CordovaError.js
@@ -0,0 +1,91 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* jshint proto:true */
+
+var EOL = require('os').EOL;
+
+/**
+ * A derived exception class. See usage example in cli.js
+ * Based on:
+ * stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/8460753#8460753
+ * @param {String} message Error message
+ * @param {Number} [code=0] Error code
+ * @param {CordovaExternalToolErrorContext} [context] External tool error context object
+ * @constructor
+ */
+function CordovaError(message, code, context) {
+ Error.captureStackTrace(this, this.constructor);
+ this.name = this.constructor.name;
+ this.message = message;
+ this.code = code || CordovaError.UNKNOWN_ERROR;
+ this.context = context;
+}
+CordovaError.prototype.__proto__ = Error.prototype;
+
+// TODO: Extend error codes according the projects specifics
+CordovaError.UNKNOWN_ERROR = 0;
+CordovaError.EXTERNAL_TOOL_ERROR = 1;
+
+/**
+ * Translates instance's error code number into error code name, e.g. 0 -> UNKNOWN_ERROR
+ * @returns {string} Error code string name
+ */
+CordovaError.prototype.getErrorCodeName = function() {
+ for(var key in CordovaError) {
+ if(CordovaError.hasOwnProperty(key)) {
+ if(CordovaError[key] === this.code) {
+ return key;
+ }
+ }
+ }
+};
+
+/**
+ * Converts CordovaError instance to string representation
+ * @param {Boolean} [isVerbose] Set up verbose mode. Used to provide more
+ * details including information about error code name and context
+ * @return {String} Stringified error representation
+ */
+CordovaError.prototype.toString = function(isVerbose) {
+ var message = '', codePrefix = '';
+
+ if(this.code !== CordovaError.UNKNOWN_ERROR) {
+ codePrefix = 'code: ' + this.code + (isVerbose ? (' (' + this.getErrorCodeName() + ')') : '') + ' ';
+ }
+
+ if(this.code === CordovaError.EXTERNAL_TOOL_ERROR) {
+ if(typeof this.context !== 'undefined') {
+ if(isVerbose) {
+ message = codePrefix + EOL + this.context.toString(isVerbose) + '\n failed with an error: ' +
+ this.message + EOL + 'Stack trace: ' + this.stack;
+ } else {
+ message = codePrefix + '\'' + this.context.toString(isVerbose) + '\' ' + this.message;
+ }
+ } else {
+ message = 'External tool failed with an error: ' + this.message;
+ }
+ } else {
+ message = isVerbose ? codePrefix + this.stack : codePrefix + this.message;
+ }
+
+ return message;
+};
+
+module.exports = CordovaError;
http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/42cbe9fd/node_modules/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js
----------------------------------------------------------------------
diff --git a/node_modules/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js b/node_modules/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js
new file mode 100644
index 0000000..ca9a4aa
--- /dev/null
+++ b/node_modules/cordova-common/src/CordovaError/CordovaExternalToolErrorContext.js
@@ -0,0 +1,48 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+/* jshint proto:true */
+
+var path = require('path');
+
+/**
+ * @param {String} cmd Command full path
+ * @param {String[]} args Command args
+ * @param {String} [cwd] Command working directory
+ * @constructor
+ */
+function CordovaExternalToolErrorContext(cmd, args, cwd) {
+ this.cmd = cmd;
+ // Helper field for readability
+ this.cmdShortName = path.basename(cmd);
+ this.args = args;
+ this.cwd = cwd;
+}
+
+CordovaExternalToolErrorContext.prototype.toString = function(isVerbose) {
+ if(isVerbose) {
+ return 'External tool \'' + this.cmdShortName + '\'' +
+ '\nCommand full path: ' + this.cmd + '\nCommand args: ' + this.args +
+ (typeof this.cwd !== 'undefined' ? '\nCommand cwd: ' + this.cwd : '');
+ }
+
+ return this.cmdShortName;
+};
+
+module.exports = CordovaExternalToolErrorContext;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org