From 400282282f21c07bda5527e4c2266810fe01da3f Mon Sep 17 00:00:00 2001 From: Vladimir Kotikov Date: Tue, 20 Oct 2015 10:30:31 +0300 Subject: [PATCH] CB-9782 Implements PlatformApi contract for Android platform. This closes #226 --- .travis.yml | 2 + bin/create | 105 +- bin/lib/check_reqs.js | 653 ++++++----- bin/lib/create.js | 663 +++++------ bin/lib/simpleargs.js | 32 - bin/node_modules/.bin/shjs | 1 - .../nopt/node_modules/abbrev/LICENSE | 23 - .../nopt/node_modules/abbrev/package.json | 31 - bin/node_modules/nopt/package.json | 41 - bin/node_modules/q/CONTRIBUTING.md | 40 - .../q/benchmark/compare-with-callbacks.js | 71 -- bin/node_modules/q/benchmark/scenarios.js | 36 - bin/node_modules/q/package.json | 93 -- bin/node_modules/shelljs/package.json | 48 - bin/node_modules/which/LICENSE | 23 - bin/node_modules/which/README.md | 5 - bin/node_modules/which/bin/which | 14 - bin/node_modules/which/package.json | 31 - bin/node_modules/which/which.js | 104 -- bin/templates/cordova/.jshintrc | 10 + bin/templates/cordova/Api.js | 492 ++++++++ bin/templates/cordova/build | 43 +- bin/templates/cordova/clean | 24 +- bin/templates/cordova/lib/Adb.js | 78 ++ bin/templates/cordova/lib/AndroidManifest.js | 161 +++ bin/templates/cordova/lib/AndroidProject.js | 184 +++ bin/templates/cordova/lib/ConsoleLogger.js | 75 ++ bin/templates/cordova/lib/appinfo.js | 48 - bin/templates/cordova/lib/build.js | 1017 +++++------------ .../cordova/lib/builders/AntBuilder.js | 141 +++ .../cordova/lib/builders/GenericBuilder.js | 138 +++ .../cordova/lib/builders/GradleBuilder.js | 213 ++++ .../cordova/lib/builders/builders.js | 47 + bin/templates/cordova/lib/device.js | 234 ++-- bin/templates/cordova/lib/emulator.js | 752 ++++++------ bin/templates/cordova/lib/exec.js | 68 -- bin/templates/cordova/lib/pluginHandlers.js | 252 ++++ bin/templates/cordova/lib/prepare.js | 364 ++++++ bin/templates/cordova/lib/retry.js | 6 +- bin/templates/cordova/lib/run.js | 80 +- bin/templates/cordova/lib/spawn.js | 50 - bin/templates/cordova/run | 42 +- bin/templates/cordova/version | 6 +- bin/update | 66 +- node_modules/elementtree/.npmignore | 1 + node_modules/elementtree/.travis.yml | 10 + node_modules/elementtree/CHANGES.md | 39 + node_modules/elementtree/LICENSE.txt | 203 ++++ node_modules/elementtree/Makefile | 21 + node_modules/elementtree/NOTICE | 5 + node_modules/elementtree/README.md | 141 +++ node_modules/elementtree/lib/constants.js | 20 + node_modules/elementtree/lib/elementpath.js | 343 ++++++ node_modules/elementtree/lib/elementtree.js | 611 ++++++++++ node_modules/elementtree/lib/errors.js | 31 + node_modules/elementtree/lib/parser.js | 33 + node_modules/elementtree/lib/parsers/index.js | 1 + node_modules/elementtree/lib/parsers/sax.js | 56 + node_modules/elementtree/lib/sprintf.js | 86 ++ node_modules/elementtree/lib/treebuilder.js | 60 + node_modules/elementtree/lib/utils.js | 72 ++ .../elementtree/node_modules/sax/AUTHORS | 9 + .../elementtree/node_modules/sax}/LICENSE | 0 .../elementtree/node_modules/sax/README.md | 213 ++++ .../elementtree/node_modules/sax/lib/sax.js | 1006 ++++++++++++++++ .../elementtree/node_modules/sax/package.json | 89 ++ node_modules/elementtree/package.json | 75 ++ node_modules/nopt/.npmignore | 1 + node_modules/nopt/.travis.yml | 9 + node_modules/nopt/LICENSE | 15 + node_modules/nopt/README.md | 211 ++++ node_modules/nopt/bin/nopt.js | 54 + .../nopt/lib/nopt.js | 0 .../nopt/node_modules/abbrev/.npmignore | 4 + .../nopt/node_modules/abbrev/.travis.yml | 5 + .../nopt/node_modules/abbrev/CONTRIBUTING.md | 3 + node_modules/nopt/node_modules/abbrev/LICENSE | 15 + .../nopt/node_modules/abbrev/README.md | 23 + .../nopt/node_modules/abbrev/abbrev.js | 0 .../nopt/node_modules/abbrev/package.json | 48 + node_modules/nopt/node_modules/abbrev/test.js | 47 + node_modules/nopt/package.json | 59 + .../properties-parser/README.markdown | 51 + node_modules/properties-parser/index.js | 420 +++++++ node_modules/properties-parser/package.json | 50 + node_modules/q/CHANGES.md | 786 +++++++++++++ {bin/node_modules => node_modules}/q/LICENSE | 3 +- .../node_modules => node_modules}/q/README.md | 88 +- node_modules/q/package.json | 120 ++ {bin/node_modules => node_modules}/q/q.js | 359 ++++-- {bin/node_modules => node_modules}/q/queue.js | 0 .../shelljs/.documentup.json | 0 .../shelljs/.jshintrc | 0 .../shelljs/.npmignore | 0 .../shelljs/.travis.yml | 3 +- .../shelljs/LICENSE | 0 .../shelljs/README.md | 53 +- node_modules/shelljs/RELEASE.md | 9 + .../shelljs/bin/shjs | 0 .../shelljs/global.js | 0 .../shelljs/make.js | 19 +- node_modules/shelljs/package.json | 64 ++ .../shelljs/scripts/generate-docs.js | 0 .../shelljs/scripts/run-tests.js | 0 .../shelljs/shell.js | 12 +- .../shelljs/src/cat.js | 0 .../shelljs/src/cd.js | 0 .../shelljs/src/chmod.js | 0 .../shelljs/src/common.js | 18 +- .../shelljs/src/cp.js | 8 +- .../shelljs/src/dirs.js | 0 .../shelljs/src/echo.js | 0 .../shelljs/src/error.js | 0 .../shelljs/src/exec.js | 71 +- .../shelljs/src/find.js | 0 .../shelljs/src/grep.js | 0 node_modules/shelljs/src/ln.js | 53 + .../shelljs/src/ls.js | 0 .../shelljs/src/mkdir.js | 0 .../shelljs/src/mv.js | 0 .../shelljs/src/popd.js | 0 .../shelljs/src/pushd.js | 0 .../shelljs/src/pwd.js | 0 .../shelljs/src/rm.js | 20 +- .../shelljs/src/sed.js | 6 +- .../shelljs/src/tempdir.js | 0 .../shelljs/src/test.js | 0 .../shelljs/src/to.js | 0 .../shelljs/src/toEnd.js | 0 .../shelljs/src/which.js | 14 +- package.json | 77 +- 131 files changed, 9482 insertions(+), 3048 deletions(-) delete mode 100644 bin/lib/simpleargs.js delete mode 120000 bin/node_modules/.bin/shjs delete mode 100644 bin/node_modules/nopt/node_modules/abbrev/LICENSE delete mode 100644 bin/node_modules/nopt/node_modules/abbrev/package.json delete mode 100644 bin/node_modules/nopt/package.json delete mode 100644 bin/node_modules/q/CONTRIBUTING.md delete mode 100644 bin/node_modules/q/benchmark/compare-with-callbacks.js delete mode 100644 bin/node_modules/q/benchmark/scenarios.js delete mode 100644 bin/node_modules/q/package.json delete mode 100644 bin/node_modules/shelljs/package.json delete mode 100644 bin/node_modules/which/LICENSE delete mode 100644 bin/node_modules/which/README.md delete mode 100755 bin/node_modules/which/bin/which delete mode 100644 bin/node_modules/which/package.json delete mode 100644 bin/node_modules/which/which.js create mode 100644 bin/templates/cordova/.jshintrc create mode 100644 bin/templates/cordova/Api.js create mode 100644 bin/templates/cordova/lib/Adb.js create mode 100644 bin/templates/cordova/lib/AndroidManifest.js create mode 100644 bin/templates/cordova/lib/AndroidProject.js create mode 100644 bin/templates/cordova/lib/ConsoleLogger.js delete mode 100644 bin/templates/cordova/lib/appinfo.js create mode 100644 bin/templates/cordova/lib/builders/AntBuilder.js create mode 100644 bin/templates/cordova/lib/builders/GenericBuilder.js create mode 100644 bin/templates/cordova/lib/builders/GradleBuilder.js create mode 100644 bin/templates/cordova/lib/builders/builders.js delete mode 100644 bin/templates/cordova/lib/exec.js create mode 100644 bin/templates/cordova/lib/pluginHandlers.js create mode 100644 bin/templates/cordova/lib/prepare.js delete mode 100644 bin/templates/cordova/lib/spawn.js create mode 100644 node_modules/elementtree/.npmignore create mode 100644 node_modules/elementtree/.travis.yml create mode 100644 node_modules/elementtree/CHANGES.md create mode 100644 node_modules/elementtree/LICENSE.txt create mode 100644 node_modules/elementtree/Makefile create mode 100644 node_modules/elementtree/NOTICE create mode 100644 node_modules/elementtree/README.md create mode 100644 node_modules/elementtree/lib/constants.js create mode 100644 node_modules/elementtree/lib/elementpath.js create mode 100644 node_modules/elementtree/lib/elementtree.js create mode 100644 node_modules/elementtree/lib/errors.js create mode 100644 node_modules/elementtree/lib/parser.js create mode 100644 node_modules/elementtree/lib/parsers/index.js create mode 100644 node_modules/elementtree/lib/parsers/sax.js create mode 100644 node_modules/elementtree/lib/sprintf.js create mode 100644 node_modules/elementtree/lib/treebuilder.js create mode 100644 node_modules/elementtree/lib/utils.js create mode 100644 node_modules/elementtree/node_modules/sax/AUTHORS rename {bin/node_modules/nopt => node_modules/elementtree/node_modules/sax}/LICENSE (100%) create mode 100644 node_modules/elementtree/node_modules/sax/README.md create mode 100644 node_modules/elementtree/node_modules/sax/lib/sax.js create mode 100644 node_modules/elementtree/node_modules/sax/package.json create mode 100644 node_modules/elementtree/package.json create mode 100644 node_modules/nopt/.npmignore create mode 100644 node_modules/nopt/.travis.yml create mode 100644 node_modules/nopt/LICENSE create mode 100644 node_modules/nopt/README.md create mode 100644 node_modules/nopt/bin/nopt.js rename {bin/node_modules => node_modules}/nopt/lib/nopt.js (100%) create mode 100644 node_modules/nopt/node_modules/abbrev/.npmignore create mode 100644 node_modules/nopt/node_modules/abbrev/.travis.yml create mode 100644 node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md create mode 100644 node_modules/nopt/node_modules/abbrev/LICENSE create mode 100644 node_modules/nopt/node_modules/abbrev/README.md rename {bin/node_modules => node_modules}/nopt/node_modules/abbrev/abbrev.js (100%) create mode 100644 node_modules/nopt/node_modules/abbrev/package.json create mode 100644 node_modules/nopt/node_modules/abbrev/test.js create mode 100644 node_modules/nopt/package.json create mode 100644 node_modules/properties-parser/README.markdown create mode 100644 node_modules/properties-parser/index.js create mode 100644 node_modules/properties-parser/package.json create mode 100644 node_modules/q/CHANGES.md rename {bin/node_modules => node_modules}/q/LICENSE (94%) rename {bin/node_modules => node_modules}/q/README.md (89%) create mode 100644 node_modules/q/package.json rename {bin/node_modules => node_modules}/q/q.js (86%) rename {bin/node_modules => node_modules}/q/queue.js (100%) rename {bin/node_modules => node_modules}/shelljs/.documentup.json (100%) rename {bin/node_modules => node_modules}/shelljs/.jshintrc (100%) rename {bin/node_modules => node_modules}/shelljs/.npmignore (100%) rename {bin/node_modules => node_modules}/shelljs/.travis.yml (77%) rename {bin/node_modules => node_modules}/shelljs/LICENSE (100%) rename {bin/node_modules => node_modules}/shelljs/README.md (92%) create mode 100644 node_modules/shelljs/RELEASE.md rename {bin/node_modules => node_modules}/shelljs/bin/shjs (100%) mode change 100755 => 100644 rename {bin/node_modules => node_modules}/shelljs/global.js (100%) rename {bin/node_modules => node_modules}/shelljs/make.js (69%) create mode 100644 node_modules/shelljs/package.json rename {bin/node_modules => node_modules}/shelljs/scripts/generate-docs.js (100%) mode change 100755 => 100644 rename {bin/node_modules => node_modules}/shelljs/scripts/run-tests.js (100%) mode change 100755 => 100644 rename {bin/node_modules => node_modules}/shelljs/shell.js (91%) rename {bin/node_modules => node_modules}/shelljs/src/cat.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/cd.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/chmod.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/common.js (88%) rename {bin/node_modules => node_modules}/shelljs/src/cp.js (95%) rename {bin/node_modules => node_modules}/shelljs/src/dirs.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/echo.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/error.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/exec.js (70%) rename {bin/node_modules => node_modules}/shelljs/src/find.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/grep.js (100%) create mode 100644 node_modules/shelljs/src/ln.js rename {bin/node_modules => node_modules}/shelljs/src/ls.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/mkdir.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/mv.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/popd.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/pushd.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/pwd.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/rm.js (82%) rename {bin/node_modules => node_modules}/shelljs/src/sed.js (81%) rename {bin/node_modules => node_modules}/shelljs/src/tempdir.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/test.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/to.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/toEnd.js (100%) rename {bin/node_modules => node_modules}/shelljs/src/which.js (86%) diff --git a/.travis.yml b/.travis.yml index 8ada6eb0..cbc8d681 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,8 @@ language: android sudo: false install: + - "(pushd .. && git clone https://github.com/apache/cordova-lib.git && popd)" + - npm link ../cordova-lib/cordova-common - npm install - echo y | android update sdk -u --filter android-23 script: diff --git a/bin/create b/bin/create index 670d1194..bdbbc80a 100755 --- a/bin/create +++ b/bin/create @@ -1,49 +1,56 @@ -#!/usr/bin/env node - -/* - 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. -*/ -var path = require('path'); -var create = require('./lib/create'); -var argv = require('nopt')({ - 'help' : Boolean, - 'cli' : Boolean, - 'shared' : Boolean, - 'link' : Boolean, - 'activity-name' : [String, undefined] -}); - -if (argv.help || argv.argv.remain.length === 0) { - console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' [] [--activity-name ] [--link]'); - console.log(' : Path to your new Cordova Android project'); - console.log(' : Package name, following reverse-domain style convention'); - console.log(' : Project name'); - console.log(' : Path to a custom application template to use'); - console.log(' --activity-name : Activity name'); - console.log(' --link will use the CordovaLib project directly instead of making a copy.'); - process.exit(1); -} - -var project_path = argv.argv.remain[0]; -var package_name = argv.argv.remain[1]; -var project_name = argv.argv.remain[2]; -var template_path = argv.argv.remain[3]; -var activity_name = argv['activity-name']; - -create.createProject(project_path, package_name, project_name, activity_name, template_path, argv.link || argv.shared, argv.cli).done(); - +#!/usr/bin/env node + +/* + 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. +*/ +var path = require('path'); +var ConfigParser = require('cordova-common').ConfigParser; +var Api = require('./templates/cordova/Api'); + +var argv = require('nopt')({ + 'help' : Boolean, + 'cli' : Boolean, + 'shared' : Boolean, + 'link' : Boolean, + 'activity-name' : [String, undefined] +}); + +if (argv.help || argv.argv.remain.length === 0) { + console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' [] [--activity-name ] [--link]'); + console.log(' : Path to your new Cordova Android project'); + console.log(' : Package name, following reverse-domain style convention'); + console.log(' : Project name'); + console.log(' : Path to a custom application template to use'); + console.log(' --activity-name : Activity name'); + console.log(' --link will use the CordovaLib project directly instead of making a copy.'); + process.exit(1); +} + +var config = new ConfigParser(path.resolve(__dirname, 'templates/project/res/xml/config.xml')); + +if (argv.argv.remain[1]) config.setPackageName(argv.argv.remain[1]); +if (argv.argv.remain[2]) config.setName(argv.argv.remain[2]); +if (argv['activity-name']) config.setName(argv['activity-name']); + +var options = { + link: argv.link || argv.shared, + customTemplate: argv.argv.remain[3], + activityName: argv['activity-name'] +}; + +Api.createPlatform(argv.argv.remain[0], config, options).done(); diff --git a/bin/lib/check_reqs.js b/bin/lib/check_reqs.js index 9d251596..57e1f47b 100644 --- a/bin/lib/check_reqs.js +++ b/bin/lib/check_reqs.js @@ -1,327 +1,326 @@ -#!/usr/bin/env node - -/* - 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 shelljs = require('shelljs'), - child_process = require('child_process'), - Q = require('q'), - path = require('path'), - fs = require('fs'), - which = require('which'), - ROOT = path.join(__dirname, '..', '..'); - -var isWindows = process.platform == 'win32'; - -function forgivingWhichSync(cmd) { - try { - // TODO: Should use shelljs.which() here to have one less dependency. - return fs.realpathSync(which.sync(cmd)); - } catch (e) { - return ''; - } -} - -function tryCommand(cmd, errMsg, catchStderr) { - var d = Q.defer(); - child_process.exec(cmd, function(err, stdout, stderr) { - if (err) d.reject(new Error(errMsg)); - // Sometimes it is necessary to return an stderr instead of stdout in case of success, since - // some commands prints theirs output to stderr instead of stdout. 'javac' is the example - else d.resolve((catchStderr ? stderr : stdout).trim()); - }); - return d.promise; -} - -// Get valid target from framework/project.properties -module.exports.get_target = function() { - function extractFromFile(filePath) { - var target = shelljs.grep(/\btarget=/, filePath); - if (!target) { - throw new Error('Could not find android target within: ' + filePath); - } - return target.split('=')[1].trim(); - } - if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) { - return extractFromFile(path.join(ROOT, 'framework', 'project.properties')); - } - if (fs.existsSync(path.join(ROOT, 'project.properties'))) { - // if no target found, we're probably in a project and project.properties is in ROOT. - return extractFromFile(path.join(ROOT, 'project.properties')); - } - throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties')); -}; - -// Returns a promise. Called only by build and clean commands. -module.exports.check_ant = function() { - return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.') - .then(function (output) { - // Parse Ant version from command output - return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1]; - }); -}; - -// Returns a promise. Called only by build and clean commands. -module.exports.check_gradle = function() { - var sdkDir = process.env['ANDROID_HOME']; - if (!sdkDir) - return Q.reject('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' + - 'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'); - - var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper'); - if (!fs.existsSync(wrapperDir)) { - return Q.reject(new Error('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' + - 'Looked here: ' + wrapperDir)); - } - return Q.when(); -}; - -// Returns a promise. -module.exports.check_java = function() { - var javacPath = forgivingWhichSync('javac'); - var hasJavaHome = !!process.env['JAVA_HOME']; - return Q().then(function() { - if (hasJavaHome) { - // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh). - if (!javacPath) { - process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin'); - } - } else { - if (javacPath) { - var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.'; - // OS X has a command for finding JAVA_HOME. - if (fs.existsSync('/usr/libexec/java_home')) { - return tryCommand('/usr/libexec/java_home', msg) - .then(function(stdout) { - process.env['JAVA_HOME'] = stdout.trim(); - }); - } else { - // See if we can derive it from javac's location. - // fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK - var maybeJavaHome = path.dirname(path.dirname(javacPath)); - if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) { - process.env['JAVA_HOME'] = maybeJavaHome; - } else { - throw new Error(msg); - } - } - } else if (isWindows) { - // Try to auto-detect java in the default install paths. - var oldSilent = shelljs.config.silent; - shelljs.config.silent = true; - var firstJdkDir = - shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] || - shelljs.ls('C:\\Program Files\\java\\jdk*')[0] || - shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0]; - shelljs.config.silent = oldSilent; - if (firstJdkDir) { - // shelljs always uses / in paths. - firstJdkDir = firstJdkDir.replace(/\//g, path.sep); - if (!javacPath) { - process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin'); - } - process.env['JAVA_HOME'] = firstJdkDir; - } - } - } - }).then(function() { - var msg = - 'Failed to run "java -version", make sure that you have a JDK installed.\n' + - 'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n'; - if (process.env['JAVA_HOME']) { - msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n'; - } - return tryCommand('java -version', msg) - .then(function() { - // We use tryCommand with catchStderr = true, because - // javac writes version info to stderr instead of stdout - return tryCommand('javac -version', msg, true); - }).then(function (output) { - var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1]; - return match && match[1]; - }); - }); -}; - -// Returns a promise. -module.exports.check_android = function() { - return Q().then(function() { - var androidCmdPath = forgivingWhichSync('android'); - var adbInPath = !!forgivingWhichSync('adb'); - var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']); - function maybeSetAndroidHome(value) { - if (!hasAndroidHome && fs.existsSync(value)) { - hasAndroidHome = true; - process.env['ANDROID_HOME'] = value; - } - } - if (!hasAndroidHome && !androidCmdPath) { - if (isWindows) { - // Android Studio 1.0 installer - maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk')); - maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk')); - // Android Studio pre-1.0 installer - maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk')); - maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk')); - // Stand-alone installer - maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk')); - maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk')); - } else if (process.platform == 'darwin') { - // Android Studio 1.0 installer - maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk')); - // Android Studio pre-1.0 installer - maybeSetAndroidHome('/Applications/Android Studio.app/sdk'); - // Stand-alone zip file that user might think to put under /Applications - maybeSetAndroidHome('/Applications/android-sdk-macosx'); - maybeSetAndroidHome('/Applications/android-sdk'); - } - if (process.env['HOME']) { - // Stand-alone zip file that user might think to put under their home directory - maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx')); - maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk')); - } - } - if (hasAndroidHome && !androidCmdPath) { - process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools'); - } - if (androidCmdPath && !hasAndroidHome) { - var parentDir = path.dirname(androidCmdPath); - var grandParentDir = path.dirname(parentDir); - if (path.basename(parentDir) == 'tools') { - process.env['ANDROID_HOME'] = path.dirname(parentDir); - hasAndroidHome = true; - } else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) { - process.env['ANDROID_HOME'] = grandParentDir; - hasAndroidHome = true; - } else { - throw new Error('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' + - 'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' + - 'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.'); - } - } - if (hasAndroidHome && !adbInPath) { - process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools'); - } - if (!process.env['ANDROID_HOME']) { - throw new Error('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' + - 'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.'); - } - if (!fs.existsSync(process.env['ANDROID_HOME'])) { - throw new Error('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] + - '\nTry update it manually to point to valid SDK directory.'); - } - }); -}; - -module.exports.getAbsoluteAndroidCmd = function() { - return forgivingWhichSync('android').replace(/(\s)/g, '\\$1'); -}; - -module.exports.check_android_target = function(valid_target) { - // valid_target can look like: - // android-19 - // android-L - // Google Inc.:Google APIs:20 - // Google Inc.:Glass Development Kit Preview:20 - if (!valid_target) valid_target = module.exports.get_target(); - var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.'; - return tryCommand('android list targets --compact', msg) - .then(function(output) { - var targets = output.split('\n'); - if (targets.indexOf(valid_target) >= 0) { - return targets; - } - - var androidCmd = module.exports.getAbsoluteAndroidCmd(); - throw new Error('Please install Android target: "' + valid_target + '".\n\n' + - 'Hint: Open the SDK manager by running: ' + androidCmd + '\n' + - 'You will require:\n' + - '1. "SDK Platform" for ' + valid_target + '\n' + - '2. "Android SDK Platform-tools (latest)\n' + - '3. "Android SDK Build-tools" (latest)'); - }); -}; - -// Returns a promise. -module.exports.run = function() { - return Q.all([this.check_java(), this.check_android().then(this.check_android_target)]) - .then(function() { - console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']); - console.log('JAVA_HOME=' + process.env['JAVA_HOME']); - }); -}; - -/** - * Object thar represents one of requirements for current platform. - * @param {String} id The unique identifier for this requirements. - * @param {String} name The name of requirements. Human-readable field. - * @param {String} version The version of requirement installed. In some cases could be an array of strings - * (for example, check_android_target returns an array of android targets installed) - * @param {Boolean} installed Indicates whether the requirement is installed or not - */ -var Requirement = function (id, name, version, installed) { - this.id = id; - this.name = name; - this.installed = installed || false; - this.metadata = { - version: version, - }; -}; - -/** - * Methods that runs all checks one by one and returns a result of checks - * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method - * - * @return Promise Array of requirements. Due to implementation, promise is always fulfilled. - */ -module.exports.check_all = function() { - - var requirements = [ - new Requirement('java', 'Java JDK'), - new Requirement('androidSdk', 'Android SDK'), - new Requirement('androidTarget', 'Android target'), - new Requirement('gradle', 'Gradle') - ]; - - var checkFns = [ - this.check_java, - this.check_android, - this.check_android_target, - this.check_gradle - ]; - - // Then execute requirement checks one-by-one - return checkFns.reduce(function (promise, checkFn, idx) { - // Update each requirement with results - var requirement = requirements[idx]; - return promise.then(checkFn) - .then(function (version) { - requirement.installed = true; - requirement.metadata.version = version; - }, function (err) { - requirement.metadata.reason = err instanceof Error ? err.message : err; - }); - }, Q()) - .then(function () { - // When chain is completed, return requirements array to upstream API - return requirements; - }); -}; +#!/usr/bin/env node + +/* + 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 shelljs = require('shelljs'), + child_process = require('child_process'), + Q = require('q'), + path = require('path'), + fs = require('fs'), + ROOT = path.join(__dirname, '..', '..'); +var CordovaError = require('cordova-common').CordovaError; + +var isWindows = process.platform == 'win32'; + +function forgivingWhichSync(cmd) { + try { + return fs.realpathSync(shelljs.which(cmd)); + } catch (e) { + return ''; + } +} + +function tryCommand(cmd, errMsg, catchStderr) { + var d = Q.defer(); + child_process.exec(cmd, function(err, stdout, stderr) { + if (err) d.reject(new CordovaError(errMsg)); + // Sometimes it is necessary to return an stderr instead of stdout in case of success, since + // some commands prints theirs output to stderr instead of stdout. 'javac' is the example + else d.resolve((catchStderr ? stderr : stdout).trim()); + }); + return d.promise; +} + +// Get valid target from framework/project.properties +module.exports.get_target = function() { + function extractFromFile(filePath) { + var target = shelljs.grep(/\btarget=/, filePath); + if (!target) { + throw new Error('Could not find android target within: ' + filePath); + } + return target.split('=')[1].trim(); + } + if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) { + return extractFromFile(path.join(ROOT, 'framework', 'project.properties')); + } + if (fs.existsSync(path.join(ROOT, 'project.properties'))) { + // if no target found, we're probably in a project and project.properties is in ROOT. + return extractFromFile(path.join(ROOT, 'project.properties')); + } + throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties')); +}; + +// Returns a promise. Called only by build and clean commands. +module.exports.check_ant = function() { + return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.') + .then(function (output) { + // Parse Ant version from command output + return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1]; + }); +}; + +// Returns a promise. Called only by build and clean commands. +module.exports.check_gradle = function() { + var sdkDir = process.env['ANDROID_HOME']; + if (!sdkDir) + return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' + + 'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.')); + + var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper'); + if (!fs.existsSync(wrapperDir)) { + return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' + + 'Looked here: ' + wrapperDir)); + } + return Q.when(); +}; + +// Returns a promise. +module.exports.check_java = function() { + var javacPath = forgivingWhichSync('javac'); + var hasJavaHome = !!process.env['JAVA_HOME']; + return Q().then(function() { + if (hasJavaHome) { + // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh). + if (!javacPath) { + process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin'); + } + } else { + if (javacPath) { + var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.'; + // OS X has a command for finding JAVA_HOME. + if (fs.existsSync('/usr/libexec/java_home')) { + return tryCommand('/usr/libexec/java_home', msg) + .then(function(stdout) { + process.env['JAVA_HOME'] = stdout.trim(); + }); + } else { + // See if we can derive it from javac's location. + // fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK + var maybeJavaHome = path.dirname(path.dirname(javacPath)); + if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) { + process.env['JAVA_HOME'] = maybeJavaHome; + } else { + throw new CordovaError(msg); + } + } + } else if (isWindows) { + // Try to auto-detect java in the default install paths. + var oldSilent = shelljs.config.silent; + shelljs.config.silent = true; + var firstJdkDir = + shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] || + shelljs.ls('C:\\Program Files\\java\\jdk*')[0] || + shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0]; + shelljs.config.silent = oldSilent; + if (firstJdkDir) { + // shelljs always uses / in paths. + firstJdkDir = firstJdkDir.replace(/\//g, path.sep); + if (!javacPath) { + process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin'); + } + process.env['JAVA_HOME'] = firstJdkDir; + } + } + } + }).then(function() { + var msg = + 'Failed to run "java -version", make sure that you have a JDK installed.\n' + + 'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n'; + if (process.env['JAVA_HOME']) { + msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n'; + } + return tryCommand('java -version', msg) + .then(function() { + // We use tryCommand with catchStderr = true, because + // javac writes version info to stderr instead of stdout + return tryCommand('javac -version', msg, true); + }).then(function (output) { + var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1]; + return match && match[1]; + }); + }); +}; + +// Returns a promise. +module.exports.check_android = function() { + return Q().then(function() { + var androidCmdPath = forgivingWhichSync('android'); + var adbInPath = !!forgivingWhichSync('adb'); + var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']); + function maybeSetAndroidHome(value) { + if (!hasAndroidHome && fs.existsSync(value)) { + hasAndroidHome = true; + process.env['ANDROID_HOME'] = value; + } + } + if (!hasAndroidHome && !androidCmdPath) { + if (isWindows) { + // Android Studio 1.0 installer + maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk')); + maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk')); + // Android Studio pre-1.0 installer + maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk')); + maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk')); + // Stand-alone installer + maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk')); + maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk')); + } else if (process.platform == 'darwin') { + // Android Studio 1.0 installer + maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk')); + // Android Studio pre-1.0 installer + maybeSetAndroidHome('/Applications/Android Studio.app/sdk'); + // Stand-alone zip file that user might think to put under /Applications + maybeSetAndroidHome('/Applications/android-sdk-macosx'); + maybeSetAndroidHome('/Applications/android-sdk'); + } + if (process.env['HOME']) { + // Stand-alone zip file that user might think to put under their home directory + maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx')); + maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk')); + } + } + if (hasAndroidHome && !androidCmdPath) { + process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools'); + } + if (androidCmdPath && !hasAndroidHome) { + var parentDir = path.dirname(androidCmdPath); + var grandParentDir = path.dirname(parentDir); + if (path.basename(parentDir) == 'tools') { + process.env['ANDROID_HOME'] = path.dirname(parentDir); + hasAndroidHome = true; + } else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) { + process.env['ANDROID_HOME'] = grandParentDir; + hasAndroidHome = true; + } else { + throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' + + 'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' + + 'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.'); + } + } + if (hasAndroidHome && !adbInPath) { + process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools'); + } + if (!process.env['ANDROID_HOME']) { + throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' + + 'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.'); + } + if (!fs.existsSync(process.env['ANDROID_HOME'])) { + throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] + + '\nTry update it manually to point to valid SDK directory.'); + } + }); +}; + +module.exports.getAbsoluteAndroidCmd = function() { + return forgivingWhichSync('android').replace(/(\s)/g, '\\$1'); +}; + +module.exports.check_android_target = function(valid_target) { + // valid_target can look like: + // android-19 + // android-L + // Google Inc.:Google APIs:20 + // Google Inc.:Glass Development Kit Preview:20 + if (!valid_target) valid_target = module.exports.get_target(); + var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.'; + return tryCommand('android list targets --compact', msg) + .then(function(output) { + var targets = output.split('\n'); + if (targets.indexOf(valid_target) >= 0) { + return targets; + } + + var androidCmd = module.exports.getAbsoluteAndroidCmd(); + throw new CordovaError('Please install Android target: "' + valid_target + '".\n\n' + + 'Hint: Open the SDK manager by running: ' + androidCmd + '\n' + + 'You will require:\n' + + '1. "SDK Platform" for ' + valid_target + '\n' + + '2. "Android SDK Platform-tools (latest)\n' + + '3. "Android SDK Build-tools" (latest)'); + }); +}; + +// Returns a promise. +module.exports.run = function() { + return Q.all([this.check_java(), this.check_android().then(this.check_android_target)]) + .then(function() { + console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']); + console.log('JAVA_HOME=' + process.env['JAVA_HOME']); + }); +}; + +/** + * Object thar represents one of requirements for current platform. + * @param {String} id The unique identifier for this requirements. + * @param {String} name The name of requirements. Human-readable field. + * @param {String} version The version of requirement installed. In some cases could be an array of strings + * (for example, check_android_target returns an array of android targets installed) + * @param {Boolean} installed Indicates whether the requirement is installed or not + */ +var Requirement = function (id, name, version, installed) { + this.id = id; + this.name = name; + this.installed = installed || false; + this.metadata = { + version: version, + }; +}; + +/** + * Methods that runs all checks one by one and returns a result of checks + * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method + * + * @return Promise Array of requirements. Due to implementation, promise is always fulfilled. + */ +module.exports.check_all = function() { + + var requirements = [ + new Requirement('java', 'Java JDK'), + new Requirement('androidSdk', 'Android SDK'), + new Requirement('androidTarget', 'Android target'), + new Requirement('gradle', 'Gradle') + ]; + + var checkFns = [ + this.check_java, + this.check_android, + this.check_android_target, + this.check_gradle + ]; + + // Then execute requirement checks one-by-one + return checkFns.reduce(function (promise, checkFn, idx) { + // Update each requirement with results + var requirement = requirements[idx]; + return promise.then(checkFn) + .then(function (version) { + requirement.installed = true; + requirement.metadata.version = version; + }, function (err) { + requirement.metadata.reason = err instanceof Error ? err.message : err; + }); + }, Q()) + .then(function () { + // When chain is completed, return requirements array to upstream API + return requirements; + }); +}; diff --git a/bin/lib/create.js b/bin/lib/create.js index e804b6e8..799836f0 100755 --- a/bin/lib/create.js +++ b/bin/lib/create.js @@ -1,331 +1,332 @@ -#!/usr/bin/env node - -/* - 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. -*/ - -var shell = require('shelljs'), - Q = require('q'), - path = require('path'), - fs = require('fs'), - check_reqs = require('./check_reqs'), - ROOT = path.join(__dirname, '..', '..'); - -function setShellFatal(value, func) { - var oldVal = shell.config.fatal; - shell.config.fatal = value; - func(); - shell.config.fatal = oldVal; -} - -function getFrameworkDir(projectPath, shared) { - return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib'); -} - -function copyJsAndLibrary(projectPath, shared, projectName) { - var nestedCordovaLibPath = getFrameworkDir(projectPath, false); - var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js'); - shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'assets', 'www', 'cordova.js')); - // Don't fail if there are no old jars. - setShellFatal(false, function() { - shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) { - console.log('Deleting ' + oldJar); - shell.rm('-f', oldJar); - }); - var wasSymlink = true; - try { - // Delete the symlink if it was one. - fs.unlinkSync(nestedCordovaLibPath); - } catch (e) { - wasSymlink = false; - } - // Delete old library project if it existed. - if (shared) { - shell.rm('-rf', nestedCordovaLibPath); - } else if (!wasSymlink) { - // Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted. - shell.rm('-rf', path.join(nestedCordovaLibPath, 'src')); - } - }); - if (shared) { - var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true)); - fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir'); - } else { - shell.mkdir('-p', nestedCordovaLibPath); - shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath); - shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath); - shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath); - shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath); - shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath); - } -} - -function extractSubProjectPaths(data) { - var ret = {}; - var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg; - var m; - while ((m = r.exec(data))) { - ret[m[1]] = 1; - } - return Object.keys(ret); -} - -function writeProjectProperties(projectPath, target_api) { - var dstPath = path.join(projectPath, 'project.properties'); - var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties'); - var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath; - var data = fs.readFileSync(srcPath, 'utf8'); - data = data.replace(/^target=.*/m, 'target=' + target_api); - var subProjects = extractSubProjectPaths(data); - subProjects = subProjects.filter(function(p) { - return !(/^CordovaLib$/m.exec(p) || - /[\\\/]cordova-android[\\\/]framework$/m.exec(p) || - /^(\.\.[\\\/])+framework$/m.exec(p) - ); - }); - subProjects.unshift('CordovaLib'); - data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, ''); - if (!/\n$/.exec(data)) { - data += '\n'; - } - for (var i = 0; i < subProjects.length; ++i) { - data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n'; - } - fs.writeFileSync(dstPath, data); -} - -function prepBuildFiles(projectPath) { - var buildModule = require(path.join(path.resolve(projectPath), 'cordova', 'lib', 'build')); - buildModule.prepBuildFiles(); -} - -function copyBuildRules(projectPath) { - var srcDir = path.join(ROOT, 'bin', 'templates', 'project'); - - shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath); -} - -function copyScripts(projectPath) { - var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova'); - var destScriptsDir = path.join(projectPath, 'cordova'); - // Delete old scripts directory if this is an update. - shell.rm('-rf', destScriptsDir); - // Copy in the new ones. - shell.cp('-r', srcScriptsDir, projectPath); - shell.cp('-r', path.join(ROOT, 'bin', 'node_modules'), destScriptsDir); - shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir); - shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js')); - shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version')); - shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js')); -} - -/** - * Test whether a package name is acceptable for use as an android project. - * Returns a promise, fulfilled if the package name is acceptable; rejected - * otherwise. - */ -function validatePackageName(package_name) { - //Make the package conform to Java package types - //http://developer.android.com/guide/topics/manifest/manifest-element.html#package - //Enforce underscore limitation - if (!/^[a-zA-Z][a-zA-Z0-9_]+(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.test(package_name)) { - return Q.reject('Package name must look like: com.company.Name'); - } - - //Class is a reserved word - if(/\b[Cc]lass\b/.test(package_name)) { - return Q.reject('class is a reserved word'); - } - - return Q.resolve(); -} - -/** - * Test whether a project name is acceptable for use as an android class. - * Returns a promise, fulfilled if the project name is acceptable; rejected - * otherwise. - */ -function validateProjectName(project_name) { - //Make sure there's something there - if (project_name === '') { - return Q.reject('Project name cannot be empty'); - } - - //Enforce stupid name error - if (project_name === 'CordovaActivity') { - return Q.reject('Project name cannot be CordovaActivity'); - } - - //Classes in Java don't begin with numbers - if (/^[0-9]/.test(project_name)) { - return Q.reject('Project name must not begin with a number'); - } - - return Q.resolve(); -} - -/** - * $ create [options] - * - * Creates an android application with the given options. - * - * Options: - * - * - `project_path` {String} Path to the new Cordova android project. - * - `package_name`{String} Package name, following reverse-domain style convention. - * - `project_name` {String} Project name. - * - `activity_name` {String} Name for the activity - * - 'project_template_dir' {String} Path to project template (override). - * - * Returns a promise. - */ - -exports.createProject = function(project_path, package_name, project_name, activity_name, project_template_dir, use_shared_project, use_cli_template) { - // Set default values for path, package and name - project_path = typeof project_path !== 'undefined' ? project_path : 'CordovaExample'; - project_path = path.relative(process.cwd(), project_path); - package_name = typeof package_name !== 'undefined' ? package_name : 'my.cordova.project'; - project_name = typeof project_name !== 'undefined' ? project_name : 'CordovaExample'; - project_template_dir = typeof project_template_dir !== 'undefined' ? - project_template_dir : - path.join(ROOT, 'bin', 'templates', 'project'); - - var package_as_path = package_name.replace(/\./g, path.sep); - var activity_dir = path.join(project_path, 'src', package_as_path); - var safe_activity_name = typeof activity_name !== 'undefined' ? activity_name : 'MainActivity'; - var activity_path = path.join(activity_dir, safe_activity_name + '.java'); - var target_api = check_reqs.get_target(); - var manifest_path = path.join(project_path, 'AndroidManifest.xml'); - - // Check if project already exists - if(fs.existsSync(project_path)) { - return Q.reject('Project already exists! Delete and recreate'); - } - - //Make the package conform to Java package types - return validatePackageName(package_name) - .then(function() { - validateProjectName(project_name); - }).then(function() { - // Log the given values for the project - console.log('Creating Cordova project for the Android platform:'); - console.log('\tPath: ' + project_path); - console.log('\tPackage: ' + package_name); - console.log('\tName: ' + project_name); - console.log('\tActivity: ' + safe_activity_name); - console.log('\tAndroid target: ' + target_api); - - console.log('Copying template files...'); - - setShellFatal(true, function() { - // copy project template - shell.cp('-r', path.join(project_template_dir, 'assets'), project_path); - shell.cp('-r', path.join(project_template_dir, 'res'), project_path); - shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore')); - - // Manually create directories that would be empty within the template (since git doesn't track directories). - shell.mkdir(path.join(project_path, 'libs')); - - // copy cordova.js, cordova.jar - copyJsAndLibrary(project_path, use_shared_project, safe_activity_name); - - // interpolate the activity name and package - shell.mkdir('-p', activity_dir); - shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path); - shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path); - shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml')); - shell.sed('-i', /__ID__/, package_name, activity_path); - - shell.cp('-f', path.join(project_template_dir, 'AndroidManifest.xml'), manifest_path); - shell.sed('-i', /__ACTIVITY__/, safe_activity_name, manifest_path); - shell.sed('-i', /__PACKAGE__/, package_name, manifest_path); - shell.sed('-i', /__APILEVEL__/, target_api.split('-')[1], manifest_path); - copyScripts(project_path); - copyBuildRules(project_path); - }); - // Link it to local android install. - writeProjectProperties(project_path, target_api); - prepBuildFiles(project_path); - console.log(generateDoneMessage('create', use_shared_project)); - }); -}; - -function generateDoneMessage(type, link) { - var pkg = require('../../package'); - var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version; - if (link) { - msg += ' and has a linked CordovaLib'; - } - return msg; -} - -// Attribute removed in Cordova 4.4 (CB-5447). -function removeDebuggableFromManifest(projectPath) { - var manifestPath = path.join(projectPath, 'AndroidManifest.xml'); - shell.sed('-i', /\s*android:debuggable="true"/, '', manifestPath); -} - -function extractProjectNameFromManifest(projectPath) { - var manifestPath = path.join(projectPath, 'AndroidManifest.xml'); - var manifestData = fs.readFileSync(manifestPath, 'utf8'); - var m = //platform_www/ + // The www dir is nuked on each prepare so we keep cordova.js in platform_www + shell.mkdir('-p', path.join(projectPath, 'platform_www')); + shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'platform_www')); + + // Copy cordova-js-src directory into platform_www directory. + // We need these files to build cordova.js if using browserify method. + shell.cp('-rf', path.join(ROOT, 'cordova-js-src'), path.join(projectPath, 'platform_www')); + + // Don't fail if there are no old jars. + setShellFatal(false, function() { + shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) { + console.log('Deleting ' + oldJar); + shell.rm('-f', oldJar); + }); + var wasSymlink = true; + try { + // Delete the symlink if it was one. + fs.unlinkSync(nestedCordovaLibPath); + } catch (e) { + wasSymlink = false; + } + // Delete old library project if it existed. + if (shared) { + shell.rm('-rf', nestedCordovaLibPath); + } else if (!wasSymlink) { + // Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted. + shell.rm('-rf', path.join(nestedCordovaLibPath, 'src')); + } + }); + if (shared) { + var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true)); + fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir'); + } else { + shell.mkdir('-p', nestedCordovaLibPath); + shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath); + shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath); + shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath); + shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath); + shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath); + } +} + +function extractSubProjectPaths(data) { + var ret = {}; + var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg; + var m; + while ((m = r.exec(data))) { + ret[m[1]] = 1; + } + return Object.keys(ret); +} + +function writeProjectProperties(projectPath, target_api) { + var dstPath = path.join(projectPath, 'project.properties'); + var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties'); + var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath; + + var data = fs.readFileSync(srcPath, 'utf8'); + data = data.replace(/^target=.*/m, 'target=' + target_api); + var subProjects = extractSubProjectPaths(data); + subProjects = subProjects.filter(function(p) { + return !(/^CordovaLib$/m.exec(p) || + /[\\\/]cordova-android[\\\/]framework$/m.exec(p) || + /^(\.\.[\\\/])+framework$/m.exec(p) + ); + }); + subProjects.unshift('CordovaLib'); + data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, ''); + if (!/\n$/.exec(data)) { + data += '\n'; + } + for (var i = 0; i < subProjects.length; ++i) { + data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n'; + } + fs.writeFileSync(dstPath, data); +} + +function prepBuildFiles(projectPath) { + var buildModule = require(path.join(path.resolve(projectPath), 'cordova', 'lib', 'build')); + buildModule.prepBuildFiles(); +} + +function copyBuildRules(projectPath) { + var srcDir = path.join(ROOT, 'bin', 'templates', 'project'); + + shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath); +} + +function copyScripts(projectPath) { + var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova'); + var destScriptsDir = path.join(projectPath, 'cordova'); + // Delete old scripts directory if this is an update. + shell.rm('-rf', destScriptsDir); + // Copy in the new ones. + shell.cp('-r', srcScriptsDir, projectPath); + shell.cp('-r', path.join(ROOT, 'node_modules'), destScriptsDir); + shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir); + shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js')); + shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version')); + shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js')); +} + +/** + * Test whether a package name is acceptable for use as an android project. + * Returns a promise, fulfilled if the package name is acceptable; rejected + * otherwise. + */ +function validatePackageName(package_name) { + //Make the package conform to Java package types + //http://developer.android.com/guide/topics/manifest/manifest-element.html#package + //Enforce underscore limitation + var msg = 'Error validating package name. '; + if (!/^[a-zA-Z][a-zA-Z0-9_]+(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.test(package_name)) { + return Q.reject(new CordovaError(msg + 'Package name must look like: com.company.Name')); + } + + //Class is a reserved word + if(/\b[Cc]lass\b/.test(package_name)) { + return Q.reject(new CordovaError(msg + '"class" is a reserved word')); + } + + return Q.resolve(); +} + +/** + * Test whether a project name is acceptable for use as an android class. + * Returns a promise, fulfilled if the project name is acceptable; rejected + * otherwise. + */ +function validateProjectName(project_name) { + var msg = 'Error validating project name. '; + //Make sure there's something there + if (project_name === '') { + return Q.reject(new CordovaError(msg + 'Project name cannot be empty')); + } + + //Enforce stupid name error + if (project_name === 'CordovaActivity') { + return Q.reject(new CordovaError(msg + 'Project name cannot be CordovaActivity')); + } + + //Classes in Java don't begin with numbers + if (/^[0-9]/.test(project_name)) { + return Q.reject(new CordovaError(msg + 'Project name must not begin with a number')); + } + + return Q.resolve(); +} + +/** + * Creates an android application with the given options. + * + * @param {String} project_path Path to the new Cordova android project. + * @param {ConfigParser} config Instance of ConfigParser to retrieve basic + * project properties. + * @param {Object} [options={}] Various options + * @param {String} [options.activityName='MainActivity'] Name for the + * activity + * @param {Boolean} [options.link=false] Specifies whether javascript files + * and CordovaLib framework will be symlinked to created application. + * @param {String} [options.customTemplate] Path to project template + * (override) + * @param {EventEmitter} [events] An EventEmitter instance for logging + * events + * + * @return {Promise} Directory where application has been created + */ +exports.create = function(project_path, config, options, events) { + + options = options || {}; + + // Set default values for path, package and name + project_path = path.relative(process.cwd(), (project_path || 'CordovaExample')); + // Check if project already exists + if(fs.existsSync(project_path)) { + return Q.reject(new CordovaError('Project already exists! Delete and recreate')); + } + + var package_name = config.packageName() || 'my.cordova.project'; + var project_name = config.name() ? + config.name().replace(/[^\w.]/g,'_') : 'CordovaExample'; + + var safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity'; + var target_api = check_reqs.get_target(); + + //Make the package conform to Java package types + return validatePackageName(package_name) + .then(function() { + validateProjectName(project_name); + }).then(function() { + // Log the given values for the project + events.emit('log', 'Creating Cordova project for the Android platform:'); + events.emit('log', '\tPath: ' + project_path); + events.emit('log', '\tPackage: ' + package_name); + events.emit('log', '\tName: ' + project_name); + events.emit('log', '\tActivity: ' + safe_activity_name); + events.emit('log', '\tAndroid target: ' + target_api); + + events.emit('verbose', 'Copying template files...'); + + setShellFatal(true, function() { + var project_template_dir = options.customTemplate || path.join(ROOT, 'bin', 'templates', 'project'); + // copy project template + shell.cp('-r', path.join(project_template_dir, 'assets'), project_path); + shell.cp('-r', path.join(project_template_dir, 'res'), project_path); + shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore')); + + // Manually create directories that would be empty within the template (since git doesn't track directories). + shell.mkdir(path.join(project_path, 'libs')); + + // copy cordova.js, cordova.jar + copyJsAndLibrary(project_path, options.link, safe_activity_name); + + // interpolate the activity name and package + var packagePath = package_name.replace(/\./g, path.sep); + var activity_dir = path.join(project_path, 'src', packagePath); + var activity_path = path.join(activity_dir, safe_activity_name + '.java'); + shell.mkdir('-p', activity_dir); + shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path); + shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path); + shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml')); + shell.sed('-i', /__ID__/, package_name, activity_path); + + var manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml')); + manifest.setPackageId(package_name) + .setTargetSdkVersion(target_api.split('-')[1]) + .getActivity().setName(safe_activity_name); + + var manifest_path = path.join(project_path, 'AndroidManifest.xml'); + manifest.write(manifest_path); + + copyScripts(project_path); + copyBuildRules(project_path); + }); + // Link it to local android install. + writeProjectProperties(project_path, target_api); + prepBuildFiles(project_path); + events.emit('log', generateDoneMessage('create', options.link)); + }).thenResolve(project_path); +}; + +function generateDoneMessage(type, link) { + var pkg = require('../../package'); + var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version; + if (link) { + msg += ' and has a linked CordovaLib'; + } + return msg; +} + +// Returns a promise. +exports.update = function(projectPath, options, events) { + options = options || {}; + + return Q() + .then(function() { + + var manifest = new AndroidManifest(path.join(projectPath, 'AndroidManifest.xml')); + + if (Number(manifest.getMinSdkVersion()) < MIN_SDK_VERSION) { + events.emit('verbose', 'Updating minSdkVersion to ' + MIN_SDK_VERSION + ' in AndroidManifest.xml'); + manifest.setMinSDKVersion(MIN_SDK_VERSION); + } + + manifest.setDebuggable(false).write(); + + var projectName = manifest.getActivity().getName(); + var target_api = check_reqs.get_target(); + + copyJsAndLibrary(projectPath, options.link, projectName); + copyScripts(projectPath); + copyBuildRules(projectPath); + writeProjectProperties(projectPath, target_api); + prepBuildFiles(projectPath); + events.emit('log', generateDoneMessage('update', options.link)); + }).thenResolve(projectPath); +}; + + +// For testing +exports.validatePackageName = validatePackageName; +exports.validateProjectName = validateProjectName; diff --git a/bin/lib/simpleargs.js b/bin/lib/simpleargs.js deleted file mode 100644 index 8e89b8f0..00000000 --- a/bin/lib/simpleargs.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - 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. -*/ - -exports.getArgs = function(argv) { - var ret = {}; - var posArgs = []; - for (var i = 2, arg; (arg = argv[i] || i < argv.length); ++i) { - if (/^--/.exec(arg)) { - ret[arg] = true; - } else { - posArgs.push(arg); - } - } - ret._ = posArgs; - return ret; -}; diff --git a/bin/node_modules/.bin/shjs b/bin/node_modules/.bin/shjs deleted file mode 120000 index a0449975..00000000 --- a/bin/node_modules/.bin/shjs +++ /dev/null @@ -1 +0,0 @@ -../shelljs/bin/shjs \ No newline at end of file diff --git a/bin/node_modules/nopt/node_modules/abbrev/LICENSE b/bin/node_modules/nopt/node_modules/abbrev/LICENSE deleted file mode 100644 index 05a40109..00000000 --- a/bin/node_modules/nopt/node_modules/abbrev/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright 2009, 2010, 2011 Isaac Z. Schlueter. -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/bin/node_modules/nopt/node_modules/abbrev/package.json b/bin/node_modules/nopt/node_modules/abbrev/package.json deleted file mode 100644 index 91f1dd9c..00000000 --- a/bin/node_modules/nopt/node_modules/abbrev/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "abbrev", - "version": "1.0.5", - "description": "Like ruby's abbrev module, but in js", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me" - }, - "main": "abbrev.js", - "scripts": { - "test": "node test.js" - }, - "repository": { - "type": "git", - "url": "http://github.com/isaacs/abbrev-js" - }, - "license": { - "type": "MIT", - "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE" - }, - "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/isaacs/abbrev-js/issues" - }, - "homepage": "https://github.com/isaacs/abbrev-js", - "_id": "abbrev@1.0.5", - "_shasum": "5d8257bd9ebe435e698b2fa431afde4fe7b10b03", - "_from": "abbrev@1", - "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" -} diff --git a/bin/node_modules/nopt/package.json b/bin/node_modules/nopt/package.json deleted file mode 100644 index 62d0fe84..00000000 --- a/bin/node_modules/nopt/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "nopt", - "version": "3.0.1", - "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "main": "lib/nopt.js", - "scripts": { - "test": "tap test/*.js" - }, - "repository": { - "type": "git", - "url": "http://github.com/isaacs/nopt" - }, - "bin": { - "nopt": "./bin/nopt.js" - }, - "license": { - "type": "MIT", - "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" - }, - "dependencies": { - "abbrev": "1" - }, - "devDependencies": { - "tap": "~0.4.8" - }, - "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk -fp # unknown opts are ok.\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null. When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/isaacs/nopt/issues" - }, - "homepage": "https://github.com/isaacs/nopt", - "_id": "nopt@3.0.1", - "_shasum": "bce5c42446a3291f47622a370abbf158fbbacbfd", - "_from": "nopt@", - "_resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz" -} diff --git a/bin/node_modules/q/CONTRIBUTING.md b/bin/node_modules/q/CONTRIBUTING.md deleted file mode 100644 index 500ab17b..00000000 --- a/bin/node_modules/q/CONTRIBUTING.md +++ /dev/null @@ -1,40 +0,0 @@ - -For pull requests: - -- Be consistent with prevalent style and design decisions. -- Add a Jasmine spec to `specs/q-spec.js`. -- Use `npm test` to avoid regressions. -- Run tests in `q-spec/run.html` in as many supported browsers as you - can find the will to deal with. -- Do not build minified versions; we do this each release. -- If you would be so kind, add a note to `CHANGES.md` in an - appropriate section: - - - `Next Major Version` if it introduces backward incompatibilities - to code in the wild using documented features. - - `Next Minor Version` if it adds a new feature. - - `Next Patch Version` if it fixes a bug. - -For releases: - -- Run `npm test`. -- Run tests in `q-spec/run.html` in a representative sample of every - browser under the sun. -- Run `npm run cover` and make sure you're happy with the results. -- Run `npm run minify` and be sure to commit the resulting `q.min.js`. -- Note the Gzipped size output by the previous command, and update - `README.md` if it has changed to 1 significant digit. -- Stash any local changes. -- Update `CHANGES.md` to reflect all changes in the differences - between `HEAD` and the previous tagged version. Give credit where - credit is due. -- Update `README.md` to address all new, non-experimental features. -- Update the API reference on the Wiki to reflect all non-experimental - features. -- Use `npm version major|minor|patch` to update `package.json`, - commit, and tag the new version. -- Use `npm publish` to send up a new release. -- Send an email to the q-continuum mailing list announcing the new - release and the notes from the change log. This helps folks - maintaining other package ecosystems. - diff --git a/bin/node_modules/q/benchmark/compare-with-callbacks.js b/bin/node_modules/q/benchmark/compare-with-callbacks.js deleted file mode 100644 index 97f12989..00000000 --- a/bin/node_modules/q/benchmark/compare-with-callbacks.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; - -var Q = require("../q"); -var fs = require("fs"); - -suite("A single simple async operation", function () { - bench("with an immediately-fulfilled promise", function (done) { - Q().then(done); - }); - - bench("with direct setImmediate usage", function (done) { - setImmediate(done); - }); - - bench("with direct setTimeout(…, 0)", function (done) { - setTimeout(done, 0); - }); -}); - -suite("A fs.readFile", function () { - var denodeified = Q.denodeify(fs.readFile); - - set("iterations", 1000); - set("delay", 1000); - - bench("directly, with callbacks", function (done) { - fs.readFile(__filename, done); - }); - - bench("with Q.nfcall", function (done) { - Q.nfcall(fs.readFile, __filename).then(done); - }); - - bench("with a Q.denodeify'ed version", function (done) { - denodeified(__filename).then(done); - }); - - bench("with manual usage of deferred.makeNodeResolver", function (done) { - var deferred = Q.defer(); - fs.readFile(__filename, deferred.makeNodeResolver()); - deferred.promise.then(done); - }); -}); - -suite("1000 operations in parallel", function () { - function makeCounter(desiredCount, ultimateCallback) { - var soFar = 0; - return function () { - if (++soFar === desiredCount) { - ultimateCallback(); - } - }; - } - var numberOfOps = 1000; - - bench("with immediately-fulfilled promises", function (done) { - var counter = makeCounter(numberOfOps, done); - - for (var i = 0; i < numberOfOps; ++i) { - Q().then(counter); - } - }); - - bench("with direct setImmediate usage", function (done) { - var counter = makeCounter(numberOfOps, done); - - for (var i = 0; i < numberOfOps; ++i) { - setImmediate(counter); - } - }); -}); diff --git a/bin/node_modules/q/benchmark/scenarios.js b/bin/node_modules/q/benchmark/scenarios.js deleted file mode 100644 index 7c18564c..00000000 --- a/bin/node_modules/q/benchmark/scenarios.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; - -var Q = require("../q"); - -suite("Chaining", function () { - var numberToChain = 1000; - - bench("Chaining many already-fulfilled promises together", function (done) { - var currentPromise = Q(); - for (var i = 0; i < numberToChain; ++i) { - currentPromise = currentPromise.then(function () { - return Q(); - }); - } - - currentPromise.then(done); - }); - - bench("Chaining and then fulfilling the end of the chain", function (done) { - var deferred = Q.defer(); - - var currentPromise = deferred.promise; - for (var i = 0; i < numberToChain; ++i) { - (function () { - var promiseToReturn = currentPromise; - currentPromise = Q().then(function () { - return promiseToReturn; - }); - }()); - } - - currentPromise.then(done); - - deferred.resolve(); - }); -}); diff --git a/bin/node_modules/q/package.json b/bin/node_modules/q/package.json deleted file mode 100644 index 2ef94364..00000000 --- a/bin/node_modules/q/package.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "name": "q", - "version": "0.9.7", - "description": "A library for promises (CommonJS/Promises/A,B,D)", - "homepage": "https://github.com/kriskowal/q", - "author": { - "name": "Kris Kowal", - "email": "kris@cixar.com", - "url": "https://github.com/kriskowal" - }, - "keywords": [ - "q", - "promise", - "promises", - "promises-a", - "promises-aplus", - "deferred", - "future", - "async", - "flow control", - "fluent", - "browser", - "node" - ], - "contributors": [ - { - "name": "Kris Kowal", - "email": "kris@cixar.com", - "url": "https://github.com/kriskowal" - }, - { - "name": "Irakli Gozalishvili", - "email": "rfobic@gmail.com", - "url": "http://jeditoolkit.com" - }, - { - "name": "Domenic Denicola", - "email": "domenic@domenicdenicola.com", - "url": "http://domenicdenicola.com" - } - ], - "bugs": { - "url": "http://github.com/kriskowal/q/issues" - }, - "license": { - "type": "MIT", - "url": "http://github.com/kriskowal/q/raw/master/LICENSE" - }, - "main": "q.js", - "repository": { - "type": "git", - "url": "git://github.com/kriskowal/q.git" - }, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - }, - "dependencies": {}, - "devDependencies": { - "jshint": "~2.1.9", - "cover": "*", - "jasmine-node": "1.11.0", - "opener": "*", - "promises-aplus-tests": "1.x", - "grunt": "~0.4.1", - "grunt-cli": "~0.1.9", - "grunt-contrib-uglify": "~0.2.2", - "matcha": "~0.2.0" - }, - "scripts": { - "test": "jasmine-node spec && promises-aplus-tests spec/aplus-adapter", - "test-browser": "opener spec/q-spec.html", - "benchmark": "matcha", - "lint": "jshint q.js", - "cover": "cover run node_modules/jasmine-node/bin/jasmine-node spec && cover report html && opener cover_html/index.html", - "minify": "grunt", - "prepublish": "grunt" - }, - "overlay": { - "teleport": { - "dependencies": { - "system": ">=0.0.4" - } - } - }, - "directories": { - "test": "./spec" - }, - "readme": "[![Build Status](https://secure.travis-ci.org/kriskowal/q.png?branch=master)](http://travis-ci.org/kriskowal/q)\n\n\n \"Promises/A+\n\n\nIf a function cannot return a value or throw an exception without\nblocking, it can return a promise instead. A promise is an object\nthat represents the return value or the thrown exception that the\nfunction may eventually provide. A promise can also be used as a\nproxy for a [remote object][Q-Connection] to overcome latency.\n\n[Q-Connection]: https://github.com/kriskowal/q-connection\n\nOn the first pass, promises can mitigate the “[Pyramid of\nDoom][POD]”: the situation where code marches to the right faster\nthan it marches forward.\n\n[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/\n\n```javascript\nstep1(function (value1) {\n step2(value1, function(value2) {\n step3(value2, function(value3) {\n step4(value3, function(value4) {\n // Do something with value4\n });\n });\n });\n});\n```\n\nWith a promise library, you can flatten the pyramid.\n\n```javascript\nQ.fcall(promisedStep1)\n.then(promisedStep2)\n.then(promisedStep3)\n.then(promisedStep4)\n.then(function (value4) {\n // Do something with value4\n})\n.catch(function (error) {\n // Handle any error from all above steps\n})\n.done();\n```\n\nWith this approach, you also get implicit error propagation, just like `try`,\n`catch`, and `finally`. An error in `promisedStep1` will flow all the way to\nthe `catch` function, where it’s caught and handled. (Here `promisedStepN` is\na version of `stepN` that returns a promise.)\n\nThe callback approach is called an “inversion of control”.\nA function that accepts a callback instead of a return value\nis saying, “Don’t call me, I’ll call you.”. Promises\n[un-invert][IOC] the inversion, cleanly separating the input\narguments from control flow arguments. This simplifies the\nuse and creation of API’s, particularly variadic,\nrest and spread arguments.\n\n[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript\n\n\n## Getting Started\n\nThe Q module can be loaded as:\n\n- A ``