You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ka...@apache.org on 2014/06/06 03:25:09 UTC
git commit: CB-6024: Use nopt instead of optimist in cli
Repository: cordova-cli
Updated Branches:
refs/heads/master 903f737de -> b5b4a14a2
CB-6024: Use nopt instead of optimist in cli
Why:
- Optimist was killed by the author (he recommends minimist as replacement)
- We already use nopt in plugman cli
- Make cli parsing cleaner
Changes:
- No more manual parsing of the args array
- cli vars for plugin add passed down as part of opts, not part of targets
- cli is now a regular function rather than a class, it was never properly
used as a class.
- Flags to be passed to platform run scripts are parsed by nopt.
- To pass arbitrary flags unknown to cli down to platform scripts,
they must be separated by " -- " from other args, for example:
cordova compile ios -- -d --foo=bar
anything after " -- " will not be interpreted by the cli.
Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/b5b4a14a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/b5b4a14a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/b5b4a14a
Branch: refs/heads/master
Commit: b5b4a14a2f8bdf43fcf098884ea70af109d596a2
Parents: 903f737
Author: Mark Koudritsky <ka...@gmail.com>
Authored: Thu Jun 5 18:37:04 2014 -0400
Committer: Mark Koudritsky <ka...@gmail.com>
Committed: Thu Jun 5 18:37:04 2014 -0400
----------------------------------------------------------------------
bin/cordova | 8 +-
package.json | 2 +-
spec/cli.spec.js | 28 +++---
src/cli.js | 273 ++++++++++++++++++++++++++++++--------------------
4 files changed, 186 insertions(+), 125 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b5b4a14a/bin/cordova
----------------------------------------------------------------------
diff --git a/bin/cordova b/bin/cordova
index b75655d..bab9b88 100755
--- a/bin/cordova
+++ b/bin/cordova
@@ -7,9 +7,9 @@
// 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
@@ -37,6 +37,6 @@ if (0) {
}
addTs('start');
-var CLI = require('../src/cli');
-new CLI(process.argv);
+var cli = require('../src/cli');
+cli(process.argv);
addTs('end');
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b5b4a14a/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index aea1eff..61ff55d 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"dependencies": {
"cordova-lib": "0.21.3",
"q": "~0.9",
- "optimist": "0.6.0",
+ "nopt": "~2",
"underscore":"1.4.4"
},
"devDependencies": {
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b5b4a14a/spec/cli.spec.js
----------------------------------------------------------------------
diff --git a/spec/cli.spec.js b/spec/cli.spec.js
index 5720ed2..9b6e8de 100644
--- a/spec/cli.spec.js
+++ b/spec/cli.spec.js
@@ -17,7 +17,7 @@
under the License.
*/
-var CLI = require("../src/cli"),
+var cli = require("../src/cli"),
Q = require('q'),
cordova_lib = require('cordova-lib'),
plugman = cordova_lib.plugman,
@@ -41,17 +41,17 @@ describe("cordova cli", function () {
});
it("will spit out the version with -v", function () {
- new CLI(["node", "cordova", "-v"]);
+ cli(["node", "cordova", "-v"]);
expect(console.log).toHaveBeenCalledWith(version);
});
it("will spit out the version with --version", function () {
- new CLI(["node", "cordova", "--version"]);
+ cli(["node", "cordova", "--version"]);
expect(console.log).toHaveBeenCalledWith(version);
});
it("will spit out the version with -v anywher", function () {
- new CLI(["node", "cordova", "one", "-v", "three"]);
+ cli(["node", "cordova", "one", "-v", "three"]);
expect(console.log).toHaveBeenCalledWith(version);
});
});
@@ -63,32 +63,32 @@ describe("cordova cli", function () {
});
it("will call command with all arguments passed through", function () {
- new CLI(["node", "cordova", "build", "blackberry10", "-k", "abcd1234"]);
+ cli(["node", "cordova", "build", "blackberry10", "--", "-k", "abcd1234"]);
expect(cordova.raw.build).toHaveBeenCalledWith({verbose: false, silent: false, platforms: ["blackberry10"], options: ["-k", "abcd1234"]});
});
it("will consume the first instance of -d", function () {
- new CLI(["node", "cordova", "-d", "build", "blackberry10", "-k", "abcd1234", "-d"]);
+ cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]);
expect(cordova.raw.build).toHaveBeenCalledWith({verbose: true, silent: false, platforms: ["blackberry10"], options: ["-k", "abcd1234", "-d"]});
});
it("will consume the first instance of --verbose", function () {
- new CLI(["node", "cordova", "--verbose", "build", "blackberry10", "-k", "abcd1234", "--verbose"]);
+ cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]);
expect(cordova.raw.build).toHaveBeenCalledWith({verbose: true, silent: false, platforms: ["blackberry10"], options: ["-k", "abcd1234", "--verbose"]});
});
it("will consume the first instance of either --verbose of -d", function () {
- new CLI(["node", "cordova", "--verbose", "build", "blackberry10", "-k", "abcd1234", "-d"]);
+ cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]);
expect(cordova.raw.build).toHaveBeenCalledWith({verbose: true, silent: false, platforms: ["blackberry10"], options: ["-k", "abcd1234", "-d"]});
});
it("will consume the first instance of either --verbose of -d", function () {
- new CLI(["node", "cordova", "-d", "build", "blackberry10", "-k", "abcd1234", "--verbose"]);
+ cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]);
expect(cordova.raw.build).toHaveBeenCalledWith({verbose: true, silent: false, platforms: ["blackberry10"], options: ["-k", "abcd1234", "--verbose"]});
});
it("will consume the first instance of --silent", function () {
- new CLI(["node", "cordova", "--silent", "build", "blackberry10", "-k", "abcd1234", "--silent"]);
+ cli(["node", "cordova", "--silent", "build", "blackberry10", "--", "-k", "abcd1234", "--silent"]);
expect(cordova.raw.build).toHaveBeenCalledWith({verbose: false, silent: true, platforms: ["blackberry10"], options: ["-k", "abcd1234", "--silent"]});
});
});
@@ -98,13 +98,15 @@ describe("cordova cli", function () {
spyOn(cordova.raw, "plugin").andReturn(Q());
});
- it("will call command with all arguments passed through", function () {
- new CLI(["node", "cordova", "plugin", "add", "facebook", "--variable", "FOO=foo"]);
+ it("will pass variables", function () {
+ cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "FOO=foo"]);
expect(cordova.raw.plugin).toHaveBeenCalledWith(
"add",
- ["facebook", "--variable", "FOO=foo"],
+ ["facebook"],
jasmine.any(Object)
);
+ var opts = cordova.raw.plugin.calls[0].args[2];
+ expect(opts.cli_variables.FOO).toBe('foo');
});
});
});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b5b4a14a/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index c088802..805af26 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -17,60 +17,73 @@
under the License.
*/
-var path = require('path'),
- optimist, // required in try-catch below to print a nice error message if it's not installed.
- help = require('./help'),
- _;
+/* jshint node:true, laxcomma:true, asi:true, strict:false, trailing:true, unused:vars */
-module.exports = function CLI(inputArgs) {
+
+var path = require('path')
+ , help = require('./help')
+
+// nopt and underscore are require()d in try-catch below to print a nice error
+// message if one of them is not installed.
+var nopt, _
+
+
+module.exports = cli
+function cli(inputArgs) {
try {
- optimist = require('optimist');
+ nopt = require('nopt');
_ = require('underscore');
} catch (e) {
- console.error("Please run npm install from this directory:\n\t" +
- path.dirname(__dirname));
+ console.error(
+ 'Please run npm install from this directory:\n\t' +
+ path.dirname(__dirname)
+ );
process.exit(2);
}
- var cordova_lib = require('cordova-lib'),
- CordovaError = cordova_lib.CordovaError,
- cordova = cordova_lib.cordova,
- plugman = cordova_lib.plugman;
+
+ // When changing command line arguments, update doc/help.txt accordingly.
+ var knownOpts =
+ { 'verbose' : Boolean
+ , 'version' : Boolean
+ , 'help' : Boolean
+ , 'silent' : Boolean
+ , 'experimental' : Boolean
+ , 'noregistry' : Boolean
+ , 'shrinkwrap' : Boolean
+ , 'usenpm' : Boolean
+ , 'copy-from' : String
+ , 'link-to' : path
+ , 'searchpath' : String
+ , 'variable' : Array
+ // Flags to be passed to `cordova run`
+ , 'debug' : Boolean
+ , 'release' : Boolean
+ , 'device' : Boolean
+ , 'emulator': Boolean
+ , 'target' : String
+ }
+
+ var shortHands =
+ { 'd' : '--verbose'
+ , 'v' : '--version'
+ , 'h' : '--help'
+ , 'src' : '--copy-from'
+ }
// If no inputArgs given, use process.argv.
- var tokens;
- if (inputArgs) {
- tokens = inputArgs.slice(2);
- } else {
- tokens = process.argv.slice(2);
- }
+ inputArgs = inputArgs || process.argv
+ var args = nopt(knownOpts, shortHands, inputArgs)
- // When changing command line arguments, update doc/help.txt accordingly.
- var args = optimist(tokens)
- .boolean('d')
- .boolean('verbose')
- .boolean('v')
- .boolean('version')
- .boolean('silent')
- .boolean('experimental')
- .boolean('noregistry')
- .boolean('shrinkwrap')
- .boolean('usenpm')
- .string('copy-from')
- .alias('copy-from', 'src')
- .string('link-to')
- .string('searchpath')
- .argv;
-
- if (args.v || args.version) {
- return console.log(require('../package').version);
+ if (args.version) {
+ console.log( require('../package').version );
+ return
}
- var opts = {
- platforms: [],
- options: [],
- verbose: (args.d || args.verbose),
- silent: args.silent,
- };
+ var cordova_lib = require('cordova-lib'),
+ CordovaError = cordova_lib.CordovaError,
+ cordova = cordova_lib.cordova,
+ plugman = cordova_lib.plugman;
+
// For CrodovaError print only the message without stack trace.
process.on('uncaughtException', function(err){
@@ -82,85 +95,113 @@ module.exports = function CLI(inputArgs) {
process.exit(1);
});
+
+ // Set up event handlers for logging and results emitted as events.
cordova.on('results', console.log);
- if (!opts.silent) {
+ if ( !args.silent ) {
cordova.on('log', console.log);
cordova.on('warn', console.warn);
plugman.on('log', console.log);
plugman.on('results', console.log);
plugman.on('warn', console.warn);
- } else {
- // Remove the token.
- tokens.splice(tokens.indexOf('--silent'), 1);
}
-
- if (opts.verbose) {
- // Add handlers for verbose logging.
+ // Add handlers for verbose logging.
+ if (args.verbose) {
cordova.on('verbose', console.log);
plugman.on('verbose', console.log);
-
- //Remove the corresponding token
- if(args.d && args.verbose) {
- tokens.splice(Math.min(tokens.indexOf("-d"), tokens.indexOf("--verbose")), 1);
- } else if (args.d) {
- tokens.splice(tokens.indexOf("-d"), 1);
- } else if (args.verbose) {
- tokens.splice(tokens.indexOf("--verbose"), 1);
- }
}
- if (args.experimental) {
- tokens.splice(tokens.indexOf("--experimental"), 1);
+ // TODO: Example wanted, is this functionality ever used?
+ // If there were arguments protected from nopt with a double dash, keep
+ // them in unparsedArgs. For example:
+ // cordova build ios -- --verbose --whatever
+ // In this case "--verbose" is not parsed by nopt and args.vergbose will be
+ // false, the unparsed args after -- are kept in unparsedArgs and can be
+ // passed downstream to some scripts invoked by Cordova.
+ var unparsedArgs = []
+ var parseStopperIdx = args.argv.original.indexOf('--')
+ if (parseStopperIdx != -1) {
+ unparsedArgs = args.argv.original.slice(parseStopperIdx + 1)
}
- if (args.noregistry) {
- tokens.splice(tokens.indexOf("--noregistry"), 1);
+ // args.argv.remain contains both the undashed args (like platform names)
+ // and whatever unparsed args that were protected by " -- ".
+ // "undashed" stores only the undashed args without those after " -- " .
+ var remain = args.argv.remain
+ var undashed = remain.slice(0, remain.length - unparsedArgs.length)
+ var cmd = undashed[0]
+ var subcommand
+ var msg
+ var known_platforms = Object.keys(cordova_lib.cordova_platforms)
+
+ if ( !cmd || cmd == 'help' || args.help ) {
+ return help()
}
- if (args.usenpm) {
- tokens.splice(tokens.indexOf("--usenpm"), 1);
+ if ( !cordova.hasOwnProperty(cmd) ) {
+ msg =
+ 'Cordova does not know ' + cmd + '; try `' + cordova_lib.binname +
+ ' help` for a list of all the available commands.'
+ throw new CordovaError(msg);
}
- var cmd = tokens && tokens.length ? tokens.splice(0,1) : undefined;
- if (cmd === undefined) {
- return help();
- }
+ var opts = {
+ platforms: [],
+ options: [],
+ verbose: args.verbose || false,
+ silent: args.silent || false,
+ };
- if (!cordova.hasOwnProperty(cmd)) {
- throw new CordovaError('Cordova does not know ' + cmd + '; try `'+cordova_lib.binname+' help` for a list of all the available commands.');
- }
if (cmd == 'emulate' || cmd == 'build' || cmd == 'prepare' || cmd == 'compile' || cmd == 'run') {
- // Filter all non-platforms into options
- var platforms = cordova_lib.cordova_platforms;
- tokens.forEach(function(option, index) {
- if (platforms.hasOwnProperty(option)) {
- opts.platforms.push(option);
- } else {
- opts.options.push(option);
+ // All options without dashes are assumed to be platform names
+ opts.platforms = undashed.slice(1)
+ var badPlatforms = _.difference(opts.platforms, known_platforms)
+ if( !_.isEmpty(badPlatforms) ) {
+ msg = 'Unknown platforms: ' + badPlatforms.join(', ')
+ throw new CordovaError(msg)
+ }
+
+ // Reconstruct the args to be passed along to platform scripts.
+ // This is an ugly temporary fix. The code spawning or otherwise
+ // calling into platform code should be dealing with this based
+ // on the parsed args object.
+ var downstreamArgs = []
+ var argNames = [ 'debug', 'release', 'device', 'emulator' ]
+ argNames.forEach(function(flag) {
+ if (args[flag]) {
+ downstreamArgs.push('--' + flag)
}
- });
- cordova.raw[cmd].call(this, opts).done();
+ })
+ if (args.target) {
+ downstreamArgs.push('--target=' + args.target)
+ }
+ opts.options = downstreamArgs.concat(unparsedArgs)
+
+ cordova.raw[cmd].call(null, opts).done();
} else if (cmd == 'serve') {
- cordova.raw[cmd].apply(this, tokens).done();
+ var port = undashed[1]
+ cordova.raw.serve(port).done();
} else if (cmd == 'create') {
var cfg = {};
- // If we got a forth parameter, consider it to be JSON to init the config.
- if (args._[4]) {
- cfg = JSON.parse(args._[4]);
+ // If we got a fourth parameter, consider it to be JSON to init the config.
+ if ( undashed[4] ) {
+ cfg = JSON.parse(undashed[4]);
}
var customWww = args['copy-from'] || args['link-to'];
if (customWww) {
if (customWww.indexOf(':') != -1) {
- throw new CordovaError('Only local paths for custom www assets are supported.');
+ throw new CordovaError(
+ 'Only local paths for custom www assets are supported.'
+ );
}
- if (customWww.substr(0,1) === '~') { // resolve tilde in a naive way.
+ if ( customWww.substr(0,1) === '~' ) { // resolve tilde in a naive way.
customWww = path.join(process.env.HOME, customWww.substr(1));
}
customWww = path.resolve(customWww);
- var wwwCfg = {uri: customWww};
+ var wwwCfg = { uri: customWww };
if (args['link-to']) {
wwwCfg.link = true;
}
@@ -168,28 +209,46 @@ module.exports = function CLI(inputArgs) {
cfg.lib.www = wwwCfg;
}
// create(dir, id, name, cfg)
- cordova.raw[cmd].call(this, args._[1], args._[2], args._[3], cfg).done();
- } else if( cmd == 'save' || cmd == 'restore'){
- if(!opts.experimental && !args.experimental ){
- throw new CordovaError('save and restore commands are experimental, please add "--experimental" to indicate that you understand that it may change in the future');
+ cordova.raw.create( undashed[1] // dir to create the project in
+ , undashed[2] // App id
+ , undashed[3] // App name
+ , cfg
+ ).done();
+ } else if ( cmd == 'save' || cmd == 'restore') {
+ if ( !args.experimental ) {
+ msg =
+ 'save and restore commands are experimental, please ' +
+ 'add "--experimental" to indicate that you understand that ' +
+ 'it may change in the future'
+ throw new CordovaError(msg);
}
- var subcommand = tokens[0]
- if(subcommand == 'plugins'){
- cordova.raw[cmd].call(this,'plugins',{ shrinkwrap:args.shrinkwrap });
- }else{
- throw new CordovaError('Let cordova know what you want to '+ cmd + ', try "cordova '+ cmd +' plugins"');
+ subcommand = undashed[1]
+ if (subcommand == 'plugins') {
+ cordova.raw[cmd].call(null, 'plugins', { shrinkwrap:args.shrinkwrap })
+ } else {
+ msg =
+ 'Let cordova know what you want to '+ cmd +
+ ', try "cordova '+ cmd +' plugins"'
+ throw new CordovaError(msg)
}
- } else if (cmd == 'help') {
- return help();
} else {
// platform/plugins add/rm [target(s)]
- var subcommand = tokens[0]; // this has the sub-command, like "add", "ls", "rm" etc.
- var targets = tokens.slice(1); // this should be an array of targets, be it platforms or plugins
- var download_opts = {
- searchpath: args.searchpath,
- noregistry: args.noregistry,
- usenpm: args.usenpm
+ subcommand = undashed[1] // sub-command like "add", "ls", "rm" etc.
+ var targets = undashed.slice(2) // array of targets, either platforms or plugins
+ var cli_vars = {}
+ if (args.variable) {
+ args.variable.forEach( function(s) {
+ var keyval = s.split('=')
+ var key = keyval[0].toUpperCase()
+ cli_vars[key] = keyval[1]
+ })
}
- cordova.raw[cmd].call(this, subcommand, targets, download_opts).done();
+ var download_opts =
+ { searchpath : args.searchpath
+ , noregistry : args.noregistry
+ , usenpm : args.usenpm
+ , cli_variables : cli_vars
+ }
+ cordova.raw[cmd](subcommand, targets, download_opts).done()
}
-};
+}