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