/
task.js
191 lines (165 loc) · 4.59 KB
/
task.js
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
var fs = require('fs')
, EventEmitter = require('events').EventEmitter
, TaskMixin
, TaskVisitor = require('./task_visitor').TaskVisitor;
/**
* @constructor
* A Jake task
*/
var Task = function () {
this.constructor.prototype.initialize.apply(this, arguments);
};
Task.prototype = new EventEmitter();
Task.prototype.constructor = Task;
TaskMixin = new (function () {
this.initialize = function (name, prereqs, action, options) {
var opts = options || {};
this._currentPrereqIndex = 0;
this.name = name;
this.prereqs = prereqs;
this.action = action;
this.async = false;
this.done = false;
this.fullName = null;
this.desription = null;
this.args = [];
// Support legacy async-flag -- if not explicitly passed or falsy, will
// be set to empty-object
if (typeof opts == 'boolean' && opts === true) {
this.async = true;
}
else {
if (opts.async) {
this.async = true;
}
}
};
// Run prereqs, run task
this.invoke = function () {
this.args = Array.prototype.slice.call(arguments);
jake._invocationChain.push(this);
TaskVisitor.visit(this);
};
// Reenable, run task (no prereqs)
this.execute = function () {
};
this.reenable = function (deep) {
};
this.handlePrereqComplete = function (prereq) {
this._currentPrereqIndex++;
if (this._currentPrereqIndex < this.prereqs.length) {
TaskVisitor.visitNextPrereq(this);
}
else {
this.run();
}
};
this.shouldRunAction = function () {
if (this.done || typeof this.action != 'function') {
return false
}
return true;
};
this.run = function () {
var runAction = this.shouldRunAction();
if (runAction) {
this.action.apply(this, this.args);
}
if (!(runAction && this.async)) {
complete();
}
};
this.complete = function () {
this.done = true;
this.emit('complete');
};
})();
for (var p in TaskMixin) {
Task.prototype[p] = TaskMixin[p];
}
FileDirectoryMixin = new (function () {
var isFileOrDirectory = function (t) {
return (t instanceof FileTask ||
t instanceof DirectoryTask);
}
, isFile = function (t) {
return t instanceof FileTask;
};
this.shouldRunAction = function () {
var runAction = false
, prereqs = this.prereqs
, prereqName
, prereqTask;
// No repeatsies
if (this.done) {
return false;
}
// We need either an existing file, or an action to create one.
// Try grabbing the actual mod-time of the file, then fall back
// to looking for an action
try {
this.updateModTime();
}
catch(e) {
if (typeof this.action == 'function') {
return true;
}
else {
throw new Error('File-task ' + this.fullName + ' has no ' +
'existing file, and no action to create one.');
}
}
// Compare mod-time of all the prereqs with its mod-time
// If any prereqs are newer, need to run the action to update
if (prereqs.length) {
for (var i = 0, ii = prereqs.length; i < ii; i++) {
prereqName = prereqs[i];
prereqTask = jake.getTask(prereqName);
// Run the action if:
// 1. The prereq is a normal task (not file/dir)
// 2. The prereq is a file-task with a mod-date more recent than
// the one for this file/dir
if (prereqTask) {
if (!isFileOrDirectory(prereqTask) ||
(isFile(prereqTask) && prereqTask.modTime > this.modTime)) {
return true;
}
}
}
}
// File/dir has no prereqs, and exists -- no need to run
else {
return false;
}
};
this.updateModTime = function () {
var stats = fs.statSync(this.name);
this.modTime = stats.mtime;
};
this.complete = function () {
this.updateModTime();
this.done = true;
this.emit('complete');
};
})();
var FileTask = function (name, prereqs, action, opts) {
this.modTime = null;
this.constructor.prototype.initialize.apply(this, arguments);
};
FileTask.prototype = new Task();
FileTask.prototype.constructor = FileTask;
for (var p in FileDirectoryMixin) {
FileTask.prototype[p] = FileDirectoryMixin[p];
}
var DirectoryTask = function (name, prereqs, action, opts) {
this.modTime = null;
this.constructor.prototype.initialize.apply(this, arguments);
};
DirectoryTask.prototype = new Task();
DirectoryTask.prototype.constructor = DirectoryTask;
for (var p in FileDirectoryMixin) {
DirectoryTask.prototype[p] = FileDirectoryMixin[p];
}
exports.Task = Task;
exports.FileTask = FileTask;
exports.DirectoryTask = DirectoryTask;