program.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Jake JavaScript build tool
  3. * Copyright 2112 Matthew Eernisse ([email protected])
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. var fs = require('fs')
  19. , parseargs = require('./parseargs')
  20. , utils = require('./utils')
  21. , Program
  22. , optsReg
  23. , preempts
  24. , usage
  25. , die;
  26. optsReg = [
  27. { full: 'jakefile'
  28. , abbr: 'f'
  29. , preempts: false
  30. , expectValue: true
  31. }
  32. , { full: 'quiet'
  33. , abbr: 'q'
  34. , preempts: false
  35. , expectValue: false
  36. }
  37. , { full: 'directory'
  38. , abbr: 'C'
  39. , preempts: false
  40. , expectValue: true
  41. }
  42. , { full: 'always-make'
  43. , abbr: 'B'
  44. , preempts: false
  45. , expectValue: false
  46. }
  47. , { full: 'tasks'
  48. , abbr: 'T'
  49. , preempts: true
  50. }
  51. // Alias ls
  52. , { full: 'tasks'
  53. , abbr: 'ls'
  54. , preempts: true
  55. }
  56. , { full: 'trace'
  57. , abbr: 't'
  58. , preempts: false
  59. , expectValue: false
  60. }
  61. , { full: 'help'
  62. , abbr: 'h'
  63. , preempts: true
  64. }
  65. , { full: 'version'
  66. , abbr: 'V'
  67. , preempts: true
  68. }
  69. // Alias lowercase v
  70. , { full: 'version'
  71. , abbr: 'v'
  72. , preempts: true
  73. }
  74. , { full: 'jakelibdir'
  75. , abbr: 'J'
  76. , preempts: false
  77. , expectValue: true
  78. }
  79. ];
  80. preempts = {
  81. version: function () {
  82. die(jake.version);
  83. }
  84. , help: function () {
  85. die(usage);
  86. }
  87. };
  88. usage = ''
  89. + 'Jake JavaScript build tool\n'
  90. + '********************************************************************************\n'
  91. + 'If no flags are given, Jake looks for a Jakefile or Jakefile.js in the current directory.\n'
  92. + '********************************************************************************\n'
  93. + '{Usage}: jake [options ...] [env variables ...] target\n'
  94. + '\n'
  95. + '{Options}:\n'
  96. + ' -f, --jakefile FILE Use FILE as the Jakefile.\n'
  97. + ' -C, --directory DIRECTORY Change to DIRECTORY before running tasks.\n'
  98. + ' -q, --quiet Do not log messages to standard output.\n'
  99. + ' -B, --always-make Unconditionally make all targets.\n'
  100. + ' -T/ls, --tasks Display the tasks (matching optional PATTERN) with descriptions, then exit.\n'
  101. + ' -J, --jakelibdir JAKELIBDIR Auto-import any .jake files in JAKELIBDIR. (default is \'jakelib\')\n'
  102. + ' -t, --trace Enable full backtrace.\n'
  103. + ' -h, --help Display this help message.\n'
  104. + ' -V/v, --version Display the Jake version.\n'
  105. + '';
  106. Program = function () {
  107. this.opts = {};
  108. this.taskNames = null;
  109. this.taskArgs = null;
  110. this.envVars = null;
  111. };
  112. Program.prototype = new (function () {
  113. this.handleErr = function (err) {
  114. if(jake.listeners('error').length !== 0) {
  115. jake.emit('error', err);
  116. return;
  117. }
  118. var msg;
  119. if (jake.listeners('error').length) {
  120. jake.emit('error', err);
  121. return;
  122. }
  123. utils.logger.error('jake aborted.');
  124. if (this.opts.trace && err.stack) {
  125. utils.logger.error(err.stack);
  126. }
  127. else {
  128. if (err.stack) {
  129. msg = err.stack.split('\n').slice(0, 3).join('\n');
  130. utils.logger.error(msg);
  131. utils.logger.error('(See full trace by running task with --trace)');
  132. }
  133. else {
  134. utils.logger.error(err.message);
  135. }
  136. }
  137. process.stdout.write('', function() {
  138. process.stderr.write('', function() {
  139. jake.errorCode = jake.errorCode || 1;
  140. process.exit(jake.errorCode);
  141. });
  142. });
  143. };
  144. this.parseArgs = function (args) {
  145. var result = (new parseargs.Parser(optsReg)).parse(args);
  146. this.setOpts(result.opts);
  147. this.setTaskNames(result.taskNames);
  148. this.setEnvVars(result.envVars);
  149. };
  150. this.setOpts = function (options) {
  151. var opts = options || {};
  152. utils.mixin(this.opts, opts);
  153. };
  154. this.setTaskNames = function (names) {
  155. if (names && !Array.isArray(names)) {
  156. throw new Error('Task names must be an array');
  157. }
  158. this.taskNames = (names && names.length) ? names : ['default'];
  159. };
  160. this.setEnvVars = function (vars) {
  161. this.envVars = vars || null;
  162. };
  163. this.firstPreemptiveOption = function () {
  164. var opts = this.opts;
  165. for (var p in opts) {
  166. if (preempts[p]) {
  167. return preempts[p];
  168. }
  169. }
  170. return false;
  171. };
  172. this.init = function (configuration) {
  173. var self = this
  174. , config = configuration || {};
  175. if (config.options) {
  176. this.setOpts(config.options);
  177. }
  178. if (config.taskNames) {
  179. this.setTaskNames(config.taskNames);
  180. }
  181. if (config.envVars) {
  182. this.setEnvVars(config.envVars);
  183. }
  184. process.addListener('uncaughtException', function (err) {
  185. self.handleErr(err);
  186. });
  187. if (this.envVars) {
  188. utils.mixin(process.env, this.envVars);
  189. }
  190. };
  191. this.run = function () {
  192. var rootTask
  193. , taskNames
  194. , dirname
  195. , opts = this.opts;
  196. // Run with `jake -T`, just show descriptions
  197. if (opts.tasks) {
  198. return jake.showAllTaskDescriptions(opts.tasks);
  199. }
  200. taskNames = this.taskNames;
  201. if (!(Array.isArray(taskNames) && taskNames.length)) {
  202. throw new Error('Please pass jake.runTasks an array of task-names');
  203. }
  204. // Set working dir
  205. dirname = opts.directory;
  206. if (dirname) {
  207. if (utils.file.existsSync(dirname) &&
  208. fs.statSync(dirname).isDirectory()) {
  209. process.chdir(dirname);
  210. }
  211. else {
  212. throw new Error(dirname + ' is not a valid directory path');
  213. }
  214. }
  215. task('__root__', taskNames, function () {});
  216. rootTask = jake.Task.__root__;
  217. rootTask.once('complete', function () {
  218. jake.emit('complete');
  219. });
  220. jake.emit('start');
  221. rootTask.invoke();
  222. };
  223. })();
  224. die = function (msg) {
  225. console.log(msg);
  226. process.stdout.write('', function() {
  227. process.stderr.write('', function() {
  228. process.exit();
  229. });
  230. });
  231. };
  232. module.exports.Program = Program;