UNPKG

4.78 kBJavaScriptView Raw
1'use strict';
2
3// Nodejs libs.
4var path = require('path');
5
6// This allows grunt to require() .coffee files.
7require('coffee-script/register');
8
9// The module to be exported.
10var grunt = module.exports = {};
11
12// Expose internal grunt libs.
13function gRequire(name) {
14 return grunt[name] = require('./grunt/' + name);
15}
16
17var util = require('grunt-legacy-util');
18grunt.util = util;
19grunt.util.task = require('./util/task');
20
21var Log = require('grunt-legacy-log').Log;
22var log = new Log({grunt: grunt});
23grunt.log = log;
24
25gRequire('template');
26gRequire('event');
27var fail = gRequire('fail');
28gRequire('file');
29var option = gRequire('option');
30var config = gRequire('config');
31var task = gRequire('task');
32var help = gRequire('help');
33gRequire('cli');
34var verbose = grunt.verbose = log.verbose;
35
36// Expose some grunt metadata.
37grunt.package = require('../package.json');
38grunt.version = grunt.package.version;
39
40// Expose specific grunt lib methods on grunt.
41function gExpose(obj, methodName, newMethodName) {
42 grunt[newMethodName || methodName] = obj[methodName].bind(obj);
43}
44gExpose(task, 'registerTask');
45gExpose(task, 'registerMultiTask');
46gExpose(task, 'registerInitTask');
47gExpose(task, 'renameTask');
48gExpose(task, 'loadTasks');
49gExpose(task, 'loadNpmTasks');
50gExpose(config, 'init', 'initConfig');
51gExpose(fail, 'warn');
52gExpose(fail, 'fatal');
53
54// Expose the task interface. I've never called this manually, and have no idea
55// how it will work. But it might.
56grunt.tasks = function(tasks, options, done) {
57 // Update options with passed-in options.
58 option.init(options);
59
60 // Display the grunt version and quit if the user did --version.
61 var _tasks, _options;
62 if (option('version')) {
63 // Not --verbose.
64 log.writeln('grunt v' + grunt.version);
65
66 if (option('verbose')) {
67 // --verbose
68 verbose.writeln('Install path: ' + path.resolve(__dirname, '..'));
69 // Yes, this is a total hack, but we don't want to log all that verbose
70 // task initialization stuff here.
71 grunt.log.muted = true;
72 // Initialize task system so that available tasks can be listed.
73 grunt.task.init([], {help: true});
74 // Re-enable logging.
75 grunt.log.muted = false;
76
77 // Display available tasks (for shell completion, etc).
78 _tasks = Object.keys(grunt.task._tasks).sort();
79 verbose.writeln('Available tasks: ' + _tasks.join(' '));
80
81 // Display available options (for shell completion, etc).
82 _options = [];
83 Object.keys(grunt.cli.optlist).forEach(function(long) {
84 var o = grunt.cli.optlist[long];
85 _options.push('--' + (o.negate ? 'no-' : '') + long);
86 if (o.short) { _options.push('-' + o.short); }
87 });
88 verbose.writeln('Available options: ' + _options.join(' '));
89 }
90
91 return;
92 }
93
94 // Init colors.
95 log.initColors();
96
97 // Display help and quit if the user did --help.
98 if (option('help')) {
99 help.display();
100 return;
101 }
102
103 // A little header stuff.
104 verbose.header('Initializing').writeflags(option.flags(), 'Command-line options');
105
106 // Determine and output which tasks will be run.
107 var tasksSpecified = tasks && tasks.length > 0;
108 tasks = task.parseArgs([tasksSpecified ? tasks : 'default']);
109
110 // Initialize tasks.
111 task.init(tasks, options);
112
113 verbose.writeln();
114 if (!tasksSpecified) {
115 verbose.writeln('No tasks specified, running default tasks.');
116 }
117 verbose.writeflags(tasks, 'Running tasks');
118
119 // Handle otherwise unhandleable (probably asynchronous) exceptions.
120 var uncaughtHandler = function(e) {
121 fail.fatal(e, fail.code.TASK_FAILURE);
122 };
123 process.on('uncaughtException', uncaughtHandler);
124
125 // Report, etc when all tasks have completed.
126 task.options({
127 error: function(e) {
128 fail.warn(e, fail.code.TASK_FAILURE);
129 },
130 done: function() {
131 // Stop handling uncaught exceptions so that we don't leave any
132 // unwanted process-level side effects behind. There is no need to do
133 // this in the error callback, because fail.warn() will either kill
134 // the process, or with --force keep on going all the way here.
135 process.removeListener('uncaughtException', uncaughtHandler);
136
137 // Output a final fail / success report.
138 fail.report();
139
140 if (done) {
141 // Execute "done" function when done (only if passed, of course).
142 done();
143 } else {
144 // Otherwise, explicitly exit.
145 util.exit(0);
146 }
147 }
148 });
149
150 // Execute all tasks, in order. Passing each task individually in a forEach
151 // allows the error callback to execute multiple times.
152 tasks.forEach(function(name) { task.run(name); });
153 // Run tasks async internally to reduce call-stack, per:
154 // https://github.com/gruntjs/grunt/pull/1026
155 task.start({asyncDone: true});
156};