Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / commander / index.js
1
2 /**
3  * Module dependencies.
4  */
5
6 var EventEmitter = require('events').EventEmitter;
7 var spawn = require('child_process').spawn;
8 var fs = require('fs');
9 var exists = fs.existsSync;
10 var path = require('path');
11 var dirname = path.dirname;
12 var basename = path.basename;
13
14 /**
15  * Expose the root command.
16  */
17
18 exports = module.exports = new Command;
19
20 /**
21  * Expose `Command`.
22  */
23
24 exports.Command = Command;
25
26 /**
27  * Expose `Option`.
28  */
29
30 exports.Option = Option;
31
32 /**
33  * Initialize a new `Option` with the given `flags` and `description`.
34  *
35  * @param {String} flags
36  * @param {String} description
37  * @api public
38  */
39
40 function Option(flags, description) {
41   this.flags = flags;
42   this.required = ~flags.indexOf('<');
43   this.optional = ~flags.indexOf('[');
44   this.bool = !~flags.indexOf('-no-');
45   flags = flags.split(/[ ,|]+/);
46   if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();
47   this.long = flags.shift();
48   this.description = description || '';
49 }
50
51 /**
52  * Return option name.
53  *
54  * @return {String}
55  * @api private
56  */
57
58 Option.prototype.name = function(){
59   return this.long
60     .replace('--', '')
61     .replace('no-', '');
62 };
63
64 /**
65  * Check if `arg` matches the short or long flag.
66  *
67  * @param {String} arg
68  * @return {Boolean}
69  * @api private
70  */
71
72 Option.prototype.is = function(arg){
73   return arg == this.short
74     || arg == this.long;
75 };
76
77 /**
78  * Initialize a new `Command`.
79  *
80  * @param {String} name
81  * @api public
82  */
83
84 function Command(name) {
85   this.commands = [];
86   this.options = [];
87   this._execs = [];
88   this._args = [];
89   this._name = name;
90 }
91
92 /**
93  * Inherit from `EventEmitter.prototype`.
94  */
95
96 Command.prototype.__proto__ = EventEmitter.prototype;
97
98 /**
99  * Add command `name`.
100  *
101  * The `.action()` callback is invoked when the
102  * command `name` is specified via __ARGV__,
103  * and the remaining arguments are applied to the
104  * function for access.
105  *
106  * When the `name` is "*" an un-matched command
107  * will be passed as the first arg, followed by
108  * the rest of __ARGV__ remaining.
109  *
110  * Examples:
111  *
112  *      program
113  *        .version('0.0.1')
114  *        .option('-C, --chdir <path>', 'change the working directory')
115  *        .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
116  *        .option('-T, --no-tests', 'ignore test hook')
117  *     
118  *      program
119  *        .command('setup')
120  *        .description('run remote setup commands')
121  *        .action(function(){
122  *          console.log('setup');
123  *        });
124  *     
125  *      program
126  *        .command('exec <cmd>')
127  *        .description('run the given remote command')
128  *        .action(function(cmd){
129  *          console.log('exec "%s"', cmd);
130  *        });
131  *     
132  *      program
133  *        .command('*')
134  *        .description('deploy the given env')
135  *        .action(function(env){
136  *          console.log('deploying "%s"', env);
137  *        });
138  *     
139  *      program.parse(process.argv);
140   *
141  * @param {String} name
142  * @param {String} [desc]
143  * @return {Command} the new command
144  * @api public
145  */
146
147 Command.prototype.command = function(name, desc){
148   var args = name.split(/ +/);
149   var cmd = new Command(args.shift());
150   if (desc) cmd.description(desc);
151   if (desc) this.executables = true;
152   if (desc) this._execs[cmd._name] = true;
153   this.commands.push(cmd);
154   cmd.parseExpectedArgs(args);
155   cmd.parent = this;
156   if (desc) return this;
157   return cmd;
158 };
159
160 /**
161  * Add an implicit `help [cmd]` subcommand
162  * which invokes `--help` for the given command.
163  *
164  * @api private
165  */
166
167 Command.prototype.addImplicitHelpCommand = function() {
168   this.command('help [cmd]', 'display help for [cmd]');
169 };
170
171 /**
172  * Parse expected `args`.
173  *
174  * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
175  *
176  * @param {Array} args
177  * @return {Command} for chaining
178  * @api public
179  */
180
181 Command.prototype.parseExpectedArgs = function(args){
182   if (!args.length) return;
183   var self = this;
184   args.forEach(function(arg){
185     switch (arg[0]) {
186       case '<':
187         self._args.push({ required: true, name: arg.slice(1, -1) });
188         break;
189       case '[':
190         self._args.push({ required: false, name: arg.slice(1, -1) });
191         break;
192     }
193   });
194   return this;
195 };
196
197 /**
198  * Register callback `fn` for the command.
199  *
200  * Examples:
201  *
202  *      program
203  *        .command('help')
204  *        .description('display verbose help')
205  *        .action(function(){
206  *           // output help here
207  *        });
208  *
209  * @param {Function} fn
210  * @return {Command} for chaining
211  * @api public
212  */
213
214 Command.prototype.action = function(fn){
215   var self = this;
216   this.parent.on(this._name, function(args, unknown){    
217     // Parse any so-far unknown options
218     unknown = unknown || [];
219     var parsed = self.parseOptions(unknown);
220     
221     // Output help if necessary
222     outputHelpIfNecessary(self, parsed.unknown);
223     
224     // If there are still any unknown options, then we simply 
225     // die, unless someone asked for help, in which case we give it
226     // to them, and then we die.
227     if (parsed.unknown.length > 0) {      
228       self.unknownOption(parsed.unknown[0]);
229     }
230     
231     // Leftover arguments need to be pushed back. Fixes issue #56
232     if (parsed.args.length) args = parsed.args.concat(args);
233     
234     self._args.forEach(function(arg, i){
235       if (arg.required && null == args[i]) {
236         self.missingArgument(arg.name);
237       }
238     });
239     
240     // Always append ourselves to the end of the arguments,
241     // to make sure we match the number of arguments the user
242     // expects
243     if (self._args.length) {
244       args[self._args.length] = self;
245     } else {
246       args.push(self);
247     }
248     
249     fn.apply(this, args);
250   });
251   return this;
252 };
253
254 /**
255  * Define option with `flags`, `description` and optional
256  * coercion `fn`. 
257  *
258  * The `flags` string should contain both the short and long flags,
259  * separated by comma, a pipe or space. The following are all valid
260  * all will output this way when `--help` is used.
261  *
262  *    "-p, --pepper"
263  *    "-p|--pepper"
264  *    "-p --pepper"
265  *
266  * Examples:
267  *
268  *     // simple boolean defaulting to false
269  *     program.option('-p, --pepper', 'add pepper');
270  *
271  *     --pepper
272  *     program.pepper
273  *     // => Boolean
274  *
275  *     // simple boolean defaulting to false
276  *     program.option('-C, --no-cheese', 'remove cheese');
277  *
278  *     program.cheese
279  *     // => true
280  *
281  *     --no-cheese
282  *     program.cheese
283  *     // => true
284  *
285  *     // required argument
286  *     program.option('-C, --chdir <path>', 'change the working directory');
287  *
288  *     --chdir /tmp
289  *     program.chdir
290  *     // => "/tmp"
291  *
292  *     // optional argument
293  *     program.option('-c, --cheese [type]', 'add cheese [marble]');
294  *
295  * @param {String} flags
296  * @param {String} description
297  * @param {Function|Mixed} fn or default
298  * @param {Mixed} defaultValue
299  * @return {Command} for chaining
300  * @api public
301  */
302
303 Command.prototype.option = function(flags, description, fn, defaultValue){
304   var self = this
305     , option = new Option(flags, description)
306     , oname = option.name()
307     , name = camelcase(oname);
308
309   // default as 3rd arg
310   if ('function' != typeof fn) defaultValue = fn, fn = null;
311
312   // preassign default value only for --no-*, [optional], or <required>
313   if (false == option.bool || option.optional || option.required) {
314     // when --no-* we make sure default is true
315     if (false == option.bool) defaultValue = true;
316     // preassign only if we have a default
317     if (undefined !== defaultValue) self[name] = defaultValue;
318   }
319
320   // register the option
321   this.options.push(option);
322
323   // when it's passed assign the value
324   // and conditionally invoke the callback
325   this.on(oname, function(val){
326     // coercion
327     if (null != val && fn) val = fn(val);
328
329     // unassigned or bool
330     if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
331       // if no value, bool true, and we have a default, then use it!
332       if (null == val) {
333         self[name] = option.bool
334           ? defaultValue || true
335           : false;
336       } else {
337         self[name] = val;
338       }
339     } else if (null !== val) {
340       // reassign
341       self[name] = val;
342     }
343   });
344
345   return this;
346 };
347
348 /**
349  * Parse `argv`, settings options and invoking commands when defined.
350  *
351  * @param {Array} argv
352  * @return {Command} for chaining
353  * @api public
354  */
355
356 Command.prototype.parse = function(argv){
357   // implicit help
358   if (this.executables) this.addImplicitHelpCommand();
359
360   // store raw args
361   this.rawArgs = argv;
362
363   // guess name
364   this._name = this._name || basename(argv[1]);
365
366   // process argv
367   var parsed = this.parseOptions(this.normalize(argv.slice(2)));
368   var args = this.args = parsed.args;
369  
370   var result = this.parseArgs(this.args, parsed.unknown);
371
372   // executable sub-commands
373   var name = result.args[0];
374   if (this._execs[name]) return this.executeSubCommand(argv, args, parsed.unknown);
375
376   return result;
377 };
378
379 /**
380  * Execute a sub-command executable.
381  *
382  * @param {Array} argv
383  * @param {Array} args
384  * @param {Array} unknown
385  * @api private
386  */
387
388 Command.prototype.executeSubCommand = function(argv, args, unknown) {
389   args = args.concat(unknown);
390
391   if (!args.length) this.help();
392   if ('help' == args[0] && 1 == args.length) this.help();
393
394   // <cmd> --help
395   if ('help' == args[0]) {
396     args[0] = args[1];
397     args[1] = '--help';
398   }
399
400   // executable
401   var dir = dirname(argv[1]);
402   var bin = basename(argv[1]) + '-' + args[0];
403
404   // check for ./<bin> first
405   var local = path.join(dir, bin);
406
407   // run it
408   args = args.slice(1);
409   var proc = spawn(local, args, { stdio: 'inherit', customFds: [0, 1, 2] });
410   proc.on('error', function(err){
411     if (err.code == "ENOENT") {
412       console.error('\n  %s(1) does not exist, try --help\n', bin);
413     } else if (err.code == "EACCES") {
414       console.error('\n  %s(1) not executable. try chmod or run with root\n', bin);
415     }
416   });
417
418   this.runningCommand = proc;
419 };
420
421 /**
422  * Normalize `args`, splitting joined short flags. For example
423  * the arg "-abc" is equivalent to "-a -b -c".
424  * This also normalizes equal sign and splits "--abc=def" into "--abc def".
425  *
426  * @param {Array} args
427  * @return {Array}
428  * @api private
429  */
430
431 Command.prototype.normalize = function(args){
432   var ret = []
433     , arg
434     , lastOpt
435     , index;
436
437   for (var i = 0, len = args.length; i < len; ++i) {
438     arg = args[i];
439     i > 0 && (lastOpt = this.optionFor(args[i-1]));
440     
441     if (lastOpt && lastOpt.required) {
442         ret.push(arg);
443     } else if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
444       arg.slice(1).split('').forEach(function(c){
445         ret.push('-' + c);
446       });
447     } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) {
448       ret.push(arg.slice(0, index), arg.slice(index + 1));
449     } else {
450       ret.push(arg);
451     }
452   }
453
454   return ret;
455 };
456
457 /**
458  * Parse command `args`.
459  *
460  * When listener(s) are available those
461  * callbacks are invoked, otherwise the "*"
462  * event is emitted and those actions are invoked.
463  *
464  * @param {Array} args
465  * @return {Command} for chaining
466  * @api private
467  */
468
469 Command.prototype.parseArgs = function(args, unknown){
470   var cmds = this.commands
471     , len = cmds.length
472     , name;
473
474   if (args.length) {
475     name = args[0];
476     if (this.listeners(name).length) {
477       this.emit(args.shift(), args, unknown);
478     } else {
479       this.emit('*', args);
480     }
481   } else {
482     outputHelpIfNecessary(this, unknown);
483     
484     // If there were no args and we have unknown options,
485     // then they are extraneous and we need to error.
486     if (unknown.length > 0) {      
487       this.unknownOption(unknown[0]);
488     }
489   }
490
491   return this;
492 };
493
494 /**
495  * Return an option matching `arg` if any.
496  *
497  * @param {String} arg
498  * @return {Option}
499  * @api private
500  */
501
502 Command.prototype.optionFor = function(arg){
503   for (var i = 0, len = this.options.length; i < len; ++i) {
504     if (this.options[i].is(arg)) {
505       return this.options[i];
506     }
507   }
508 };
509
510 /**
511  * Parse options from `argv` returning `argv`
512  * void of these options.
513  *
514  * @param {Array} argv
515  * @return {Array}
516  * @api public
517  */
518
519 Command.prototype.parseOptions = function(argv){
520   var args = []
521     , len = argv.length
522     , literal
523     , option
524     , arg;
525
526   var unknownOptions = [];
527
528   // parse options
529   for (var i = 0; i < len; ++i) {
530     arg = argv[i];
531
532     // literal args after --
533     if ('--' == arg) {
534       literal = true;
535       continue;
536     }
537
538     if (literal) {
539       args.push(arg);
540       continue;
541     }
542
543     // find matching Option
544     option = this.optionFor(arg);
545
546     // option is defined
547     if (option) {
548       // requires arg
549       if (option.required) {
550         arg = argv[++i];
551         if (null == arg) return this.optionMissingArgument(option);
552         this.emit(option.name(), arg);
553       // optional arg
554       } else if (option.optional) {
555         arg = argv[i+1];
556         if (null == arg || ('-' == arg[0] && '-' != arg)) {
557           arg = null;
558         } else {
559           ++i;
560         }
561         this.emit(option.name(), arg);
562       // bool
563       } else {
564         this.emit(option.name());
565       }
566       continue;
567     }
568     
569     // looks like an option
570     if (arg.length > 1 && '-' == arg[0]) {
571       unknownOptions.push(arg);
572       
573       // If the next argument looks like it might be
574       // an argument for this option, we pass it on.
575       // If it isn't, then it'll simply be ignored
576       if (argv[i+1] && '-' != argv[i+1][0]) {
577         unknownOptions.push(argv[++i]);
578       }
579       continue;
580     }
581     
582     // arg
583     args.push(arg);
584   }
585   
586   return { args: args, unknown: unknownOptions };
587 };
588
589 /**
590  * Argument `name` is missing.
591  *
592  * @param {String} name
593  * @api private
594  */
595
596 Command.prototype.missingArgument = function(name){
597   console.error();
598   console.error("  error: missing required argument `%s'", name);
599   console.error();
600   process.exit(1);
601 };
602
603 /**
604  * `Option` is missing an argument, but received `flag` or nothing.
605  *
606  * @param {String} option
607  * @param {String} flag
608  * @api private
609  */
610
611 Command.prototype.optionMissingArgument = function(option, flag){
612   console.error();
613   if (flag) {
614     console.error("  error: option `%s' argument missing, got `%s'", option.flags, flag);
615   } else {
616     console.error("  error: option `%s' argument missing", option.flags);
617   }
618   console.error();
619   process.exit(1);
620 };
621
622 /**
623  * Unknown option `flag`.
624  *
625  * @param {String} flag
626  * @api private
627  */
628
629 Command.prototype.unknownOption = function(flag){
630   console.error();
631   console.error("  error: unknown option `%s'", flag);
632   console.error();
633   process.exit(1);
634 };
635
636
637 /**
638  * Set the program version to `str`.
639  *
640  * This method auto-registers the "-V, --version" flag
641  * which will print the version number when passed.
642  *
643  * @param {String} str
644  * @param {String} flags
645  * @return {Command} for chaining
646  * @api public
647  */
648
649 Command.prototype.version = function(str, flags){
650   if (0 == arguments.length) return this._version;
651   this._version = str;
652   flags = flags || '-V, --version';
653   this.option(flags, 'output the version number');
654   this.on('version', function(){
655     console.log(str);
656     process.exit(0);
657   });
658   return this;
659 };
660
661 /**
662  * Set the description `str`.
663  *
664  * @param {String} str
665  * @return {String|Command}
666  * @api public
667  */
668
669 Command.prototype.description = function(str){
670   if (0 == arguments.length) return this._description;
671   this._description = str;
672   return this;
673 };
674
675 /**
676  * Set / get the command usage `str`.
677  *
678  * @param {String} str
679  * @return {String|Command}
680  * @api public
681  */
682
683 Command.prototype.usage = function(str){
684   var args = this._args.map(function(arg){
685     return arg.required
686       ? '<' + arg.name + '>'
687       : '[' + arg.name + ']';
688   });
689
690   var usage = '[options'
691     + (this.commands.length ? '] [command' : '')
692     + ']'
693     + (this._args.length ? ' ' + args : '');
694
695   if (0 == arguments.length) return this._usage || usage;
696   this._usage = str;
697
698   return this;
699 };
700
701 /**
702  * Return the largest option length.
703  *
704  * @return {Number}
705  * @api private
706  */
707
708 Command.prototype.largestOptionLength = function(){
709   return this.options.reduce(function(max, option){
710     return Math.max(max, option.flags.length);
711   }, 0);
712 };
713
714 /**
715  * Return help for options.
716  *
717  * @return {String}
718  * @api private
719  */
720
721 Command.prototype.optionHelp = function(){
722   var width = this.largestOptionLength();
723   
724   // Prepend the help information
725   return [pad('-h, --help', width) + '  ' + 'output usage information']
726     .concat(this.options.map(function(option){
727       return pad(option.flags, width)
728         + '  ' + option.description;
729       }))
730     .join('\n');
731 };
732
733 /**
734  * Return command help documentation.
735  *
736  * @return {String}
737  * @api private
738  */
739
740 Command.prototype.commandHelp = function(){
741   if (!this.commands.length) return '';
742   return [
743       ''
744     , '  Commands:'
745     , ''
746     , this.commands.map(function(cmd){
747       var args = cmd._args.map(function(arg){
748         return arg.required
749           ? '<' + arg.name + '>'
750           : '[' + arg.name + ']';
751       }).join(' ');
752
753       return pad(cmd._name
754         + (cmd.options.length 
755           ? ' [options]'
756           : '') + ' ' + args, 22)
757         + (cmd.description()
758           ? ' ' + cmd.description()
759           : '');
760     }).join('\n').replace(/^/gm, '    ')
761     , ''
762   ].join('\n');
763 };
764
765 /**
766  * Return program help documentation.
767  *
768  * @return {String}
769  * @api private
770  */
771
772 Command.prototype.helpInformation = function(){
773   return [
774       ''
775     , '  Usage: ' + this._name + ' ' + this.usage()
776     , '' + this.commandHelp()
777     , '  Options:'
778     , ''
779     , '' + this.optionHelp().replace(/^/gm, '    ')
780     , ''
781     , ''
782   ].join('\n');
783 };
784
785 /**
786  * Output help information for this command
787  *
788  * @api public
789  */
790
791 Command.prototype.outputHelp = function(){
792   process.stdout.write(this.helpInformation());
793   this.emit('--help');
794 };
795
796 /**
797  * Output help information and exit.
798  *
799  * @api public
800  */
801
802 Command.prototype.help = function(){
803   this.outputHelp();
804   process.exit();
805 };
806
807 /**
808  * Camel-case the given `flag`
809  *
810  * @param {String} flag
811  * @return {String}
812  * @api private
813  */
814
815 function camelcase(flag) {
816   return flag.split('-').reduce(function(str, word){
817     return str + word[0].toUpperCase() + word.slice(1);
818   });
819 }
820
821 /**
822  * Pad `str` to `width`.
823  *
824  * @param {String} str
825  * @param {Number} width
826  * @return {String}
827  * @api private
828  */
829
830 function pad(str, width) {
831   var len = Math.max(0, width - str.length);
832   return str + Array(len + 1).join(' ');
833 }
834
835 /**
836  * Output help information if necessary
837  *
838  * @param {Command} command to output help for
839  * @param {Array} array of options to search for -h or --help
840  * @api private
841  */
842
843 function outputHelpIfNecessary(cmd, options) {
844   options = options || [];
845   for (var i = 0; i < options.length; i++) {
846     if (options[i] == '--help' || options[i] == '-h') {
847       cmd.outputHelp();
848       process.exit(0);
849     }
850   }
851 }