Updated the Survey.
This commit is contained in:
parent
f59686eae0
commit
6d3ba1a714
1203 changed files with 140782 additions and 5 deletions
30
node_modules/jake/lib/task/directory_task.js
generated
vendored
Normal file
30
node_modules/jake/lib/task/directory_task.js
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
let fs = require('fs');
|
||||
let FileTask = require('./file_task').FileTask;
|
||||
|
||||
/**
|
||||
@name jake
|
||||
@namespace jake
|
||||
*/
|
||||
/**
|
||||
@name jake.DirectoryTask
|
||||
@constructor
|
||||
@augments EventEmitter
|
||||
@augments jake.Task
|
||||
@augments jake.FileTask
|
||||
@description A Jake DirectoryTask
|
||||
|
||||
@param {String} name The name of the directory to create.
|
||||
*/
|
||||
class DirectoryTask extends FileTask {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
if (fs.existsSync(this.name)) {
|
||||
this.updateModTime();
|
||||
}
|
||||
else {
|
||||
this.modTime = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.DirectoryTask = DirectoryTask;
|
124
node_modules/jake/lib/task/file_task.js
generated
vendored
Normal file
124
node_modules/jake/lib/task/file_task.js
generated
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
let fs = require('fs');
|
||||
let Task = require('./task').Task;
|
||||
|
||||
function isFileOrDirectory(t) {
|
||||
return (t instanceof FileTask ||
|
||||
t instanceof DirectoryTask);
|
||||
}
|
||||
|
||||
function isFile(t) {
|
||||
return (t instanceof FileTask && !(t instanceof DirectoryTask));
|
||||
}
|
||||
|
||||
/**
|
||||
@name jake
|
||||
@namespace jake
|
||||
*/
|
||||
/**
|
||||
@name jake.FileTask
|
||||
@class`
|
||||
@extentds Task
|
||||
@description A Jake FileTask
|
||||
|
||||
@param {String} name The name of the Task
|
||||
@param {Array} [prereqs] Prerequisites to be run before this task
|
||||
@param {Function} [action] The action to perform to create this file
|
||||
@param {Object} [opts]
|
||||
@param {Array} [opts.asyc=false] Perform this task asynchronously.
|
||||
If you flag a task with this option, you must call the global
|
||||
`complete` method inside the task's action, for execution to proceed
|
||||
to the next task.
|
||||
*/
|
||||
class FileTask extends Task {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.dummy = false;
|
||||
if (fs.existsSync(this.name)) {
|
||||
this.updateModTime();
|
||||
}
|
||||
else {
|
||||
this.modTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
isNeeded() {
|
||||
let prereqs = this.prereqs;
|
||||
let prereqName;
|
||||
let prereqTask;
|
||||
|
||||
// No repeatsies
|
||||
if (this.taskStatus == Task.runStatuses.DONE) {
|
||||
return false;
|
||||
}
|
||||
// The always-make override
|
||||
else if (jake.program.opts['always-make']) {
|
||||
return true;
|
||||
}
|
||||
// Default case
|
||||
else {
|
||||
|
||||
// We need either an existing file, or an action to create one.
|
||||
// First try grabbing the actual mod-time of the file
|
||||
try {
|
||||
this.updateModTime();
|
||||
}
|
||||
// Then fall back to looking for an action
|
||||
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 && prereqs.length) {
|
||||
for (let i = 0, ii = prereqs.length; i < ii; i++) {
|
||||
prereqName = prereqs[i];
|
||||
prereqTask = this.namespace.resolveTask(prereqName) ||
|
||||
jake.createPlaceholderFileTask(prereqName, this.namespace);
|
||||
// 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 {
|
||||
// Effectively done
|
||||
this.taskStatus = Task.runStatuses.DONE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateModTime() {
|
||||
let stats = fs.statSync(this.name);
|
||||
this.modTime = stats.mtime;
|
||||
}
|
||||
|
||||
complete() {
|
||||
if (!this.dummy) {
|
||||
this.updateModTime();
|
||||
}
|
||||
// Hackity hack
|
||||
Task.prototype.complete.apply(this, arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.FileTask = FileTask;
|
||||
|
||||
// DirectoryTask is a subclass of FileTask, depends on it
|
||||
// being defined
|
||||
let DirectoryTask = require('./directory_task').DirectoryTask;
|
||||
|
9
node_modules/jake/lib/task/index.js
generated
vendored
Normal file
9
node_modules/jake/lib/task/index.js
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
let Task = require('./task').Task;
|
||||
let FileTask = require('./file_task').FileTask;
|
||||
let DirectoryTask = require('./directory_task').DirectoryTask;
|
||||
|
||||
exports.Task = Task;
|
||||
exports.FileTask = FileTask;
|
||||
exports.DirectoryTask = DirectoryTask;
|
||||
|
439
node_modules/jake/lib/task/task.js
generated
vendored
Normal file
439
node_modules/jake/lib/task/task.js
generated
vendored
Normal file
|
@ -0,0 +1,439 @@
|
|||
let EventEmitter = require('events').EventEmitter;
|
||||
let async = require('async');
|
||||
let chalk = require('chalk');
|
||||
// 'rule' module is required at the bottom because circular deps
|
||||
|
||||
// Used for task value, so better not to use
|
||||
// null, since value should be unset/uninitialized
|
||||
let UNDEFINED_VALUE;
|
||||
|
||||
const ROOT_TASK_NAME = '__rootTask__';
|
||||
const POLLING_INTERVAL = 100;
|
||||
|
||||
// Parse any positional args attached to the task-name
|
||||
function parsePrereqName(name) {
|
||||
let taskArr = name.split('[');
|
||||
let taskName = taskArr[0];
|
||||
let taskArgs = [];
|
||||
if (taskArr[1]) {
|
||||
taskArgs = taskArr[1].replace(/\]$/, '');
|
||||
taskArgs = taskArgs.split(',');
|
||||
}
|
||||
return {
|
||||
name: taskName,
|
||||
args: taskArgs
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@name jake.Task
|
||||
@class
|
||||
@extends EventEmitter
|
||||
@description A Jake Task
|
||||
|
||||
@param {String} name The name of the Task
|
||||
@param {Array} [prereqs] Prerequisites to be run before this task
|
||||
@param {Function} [action] The action to perform for this task
|
||||
@param {Object} [opts]
|
||||
@param {Array} [opts.asyc=false] Perform this task asynchronously.
|
||||
If you flag a task with this option, you must call the global
|
||||
`complete` method inside the task's action, for execution to proceed
|
||||
to the next task.
|
||||
*/
|
||||
class Task extends EventEmitter {
|
||||
|
||||
constructor(name, prereqs, action, options) {
|
||||
// EventEmitter ctor takes no args
|
||||
super();
|
||||
|
||||
if (name.indexOf(':') > -1) {
|
||||
throw new Error('Task name cannot include a colon. It is used internally as namespace delimiter.');
|
||||
}
|
||||
let opts = options || {};
|
||||
|
||||
this._currentPrereqIndex = 0;
|
||||
this._internal = false;
|
||||
this._skipped = false;
|
||||
|
||||
this.name = name;
|
||||
this.prereqs = prereqs;
|
||||
this.action = action;
|
||||
this.async = false;
|
||||
this.taskStatus = Task.runStatuses.UNSTARTED;
|
||||
this.description = null;
|
||||
this.args = [];
|
||||
this.value = UNDEFINED_VALUE;
|
||||
this.concurrency = 1;
|
||||
this.startTime = null;
|
||||
this.endTime = null;
|
||||
this.directory = null;
|
||||
this.namespace = null;
|
||||
|
||||
// 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;
|
||||
}
|
||||
if (opts.concurrency) {
|
||||
this.concurrency = opts.concurrency;
|
||||
}
|
||||
}
|
||||
|
||||
//Do a test on self dependencies for this task
|
||||
if(Array.isArray(this.prereqs) && this.prereqs.indexOf(this.name) !== -1) {
|
||||
throw new Error("Cannot use prereq " + this.name + " as a dependency of itself");
|
||||
}
|
||||
}
|
||||
|
||||
get fullName() {
|
||||
return this._getFullName();
|
||||
}
|
||||
|
||||
_initInvocationChain() {
|
||||
// Legacy global invocation chain
|
||||
jake._invocationChain.push(this);
|
||||
|
||||
// New root chain
|
||||
if (!this._invocationChain) {
|
||||
this._invocationChainRoot = true;
|
||||
this._invocationChain = [];
|
||||
if (jake.currentRunningTask) {
|
||||
jake.currentRunningTask._waitForChains = jake.currentRunningTask._waitForChains || [];
|
||||
jake.currentRunningTask._waitForChains.push(this._invocationChain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@name jake.Task#invoke
|
||||
@function
|
||||
@description Runs prerequisites, then this task. If the task has already
|
||||
been run, will not run the task again.
|
||||
*/
|
||||
invoke() {
|
||||
this._initInvocationChain();
|
||||
|
||||
this.args = Array.prototype.slice.call(arguments);
|
||||
this.reenabled = false
|
||||
this.runPrereqs();
|
||||
}
|
||||
|
||||
/**
|
||||
@name jake.Task#execute
|
||||
@function
|
||||
@description Run only this task, without prereqs. If the task has already
|
||||
been run, *will* run the task again.
|
||||
*/
|
||||
execute() {
|
||||
this._initInvocationChain();
|
||||
|
||||
this.args = Array.prototype.slice.call(arguments);
|
||||
this.reenable();
|
||||
this.reenabled = true
|
||||
this.run();
|
||||
}
|
||||
|
||||
runPrereqs() {
|
||||
if (this.prereqs && this.prereqs.length) {
|
||||
|
||||
if (this.concurrency > 1) {
|
||||
async.eachLimit(this.prereqs, this.concurrency,
|
||||
|
||||
(name, cb) => {
|
||||
let parsed = parsePrereqName(name);
|
||||
|
||||
let prereq = this.namespace.resolveTask(parsed.name) ||
|
||||
jake.attemptRule(name, this.namespace, 0) ||
|
||||
jake.createPlaceholderFileTask(name, this.namespace);
|
||||
|
||||
if (!prereq) {
|
||||
throw new Error('Unknown task "' + name + '"');
|
||||
}
|
||||
|
||||
//Test for circular invocation
|
||||
if(prereq === this) {
|
||||
setImmediate(function () {
|
||||
cb(new Error("Cannot use prereq " + prereq.name + " as a dependency of itself"));
|
||||
});
|
||||
}
|
||||
|
||||
if (prereq.taskStatus == Task.runStatuses.DONE) {
|
||||
//prereq already done, return
|
||||
setImmediate(cb);
|
||||
}
|
||||
else {
|
||||
//wait for complete before calling cb
|
||||
prereq.once('_done', () => {
|
||||
prereq.removeAllListeners('_done');
|
||||
setImmediate(cb);
|
||||
});
|
||||
// Start the prereq if we are the first to encounter it
|
||||
if (prereq.taskStatus === Task.runStatuses.UNSTARTED) {
|
||||
prereq.taskStatus = Task.runStatuses.STARTED;
|
||||
prereq.invoke.apply(prereq, parsed.args);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
(err) => {
|
||||
//async callback is called after all prereqs have run.
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
else {
|
||||
setImmediate(this.run.bind(this));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
setImmediate(this.nextPrereq.bind(this));
|
||||
}
|
||||
}
|
||||
else {
|
||||
setImmediate(this.run.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
nextPrereq() {
|
||||
let self = this;
|
||||
let index = this._currentPrereqIndex;
|
||||
let name = this.prereqs[index];
|
||||
let prereq;
|
||||
let parsed;
|
||||
|
||||
if (name) {
|
||||
|
||||
parsed = parsePrereqName(name);
|
||||
|
||||
prereq = this.namespace.resolveTask(parsed.name) ||
|
||||
jake.attemptRule(name, this.namespace, 0) ||
|
||||
jake.createPlaceholderFileTask(name, this.namespace);
|
||||
|
||||
if (!prereq) {
|
||||
throw new Error('Unknown task "' + name + '"');
|
||||
}
|
||||
|
||||
// Do when done
|
||||
if (prereq.taskStatus == Task.runStatuses.DONE) {
|
||||
self.handlePrereqDone(prereq);
|
||||
}
|
||||
else {
|
||||
prereq.once('_done', () => {
|
||||
this.handlePrereqDone(prereq);
|
||||
prereq.removeAllListeners('_done');
|
||||
});
|
||||
if (prereq.taskStatus == Task.runStatuses.UNSTARTED) {
|
||||
prereq.taskStatus = Task.runStatuses.STARTED;
|
||||
prereq._invocationChain = this._invocationChain;
|
||||
prereq.invoke.apply(prereq, parsed.args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@name jake.Task#reenable
|
||||
@function
|
||||
@description Reenables a task so that it can be run again.
|
||||
*/
|
||||
reenable(deep) {
|
||||
let prereqs;
|
||||
let prereq;
|
||||
this._skipped = false;
|
||||
this.taskStatus = Task.runStatuses.UNSTARTED;
|
||||
this.value = UNDEFINED_VALUE;
|
||||
if (deep && this.prereqs) {
|
||||
prereqs = this.prereqs;
|
||||
for (let i = 0, ii = prereqs.length; i < ii; i++) {
|
||||
prereq = jake.Task[prereqs[i]];
|
||||
if (prereq) {
|
||||
prereq.reenable(deep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handlePrereqDone(prereq) {
|
||||
this._currentPrereqIndex++;
|
||||
if (this._currentPrereqIndex < this.prereqs.length) {
|
||||
setImmediate(this.nextPrereq.bind(this));
|
||||
}
|
||||
else {
|
||||
setImmediate(this.run.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
isNeeded() {
|
||||
let needed = true;
|
||||
if (this.taskStatus == Task.runStatuses.DONE) {
|
||||
needed = false;
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
|
||||
run() {
|
||||
let val, previous;
|
||||
let hasAction = typeof this.action == 'function';
|
||||
|
||||
if (!this.isNeeded()) {
|
||||
this.emit('skip');
|
||||
this.emit('_done');
|
||||
}
|
||||
else {
|
||||
if (this._invocationChain.length) {
|
||||
previous = this._invocationChain[this._invocationChain.length - 1];
|
||||
// If this task is repeating and its previous is equal to this, don't check its status because it was set to UNSTARTED by the reenable() method
|
||||
if (!(this.reenabled && previous == this)) {
|
||||
if (previous.taskStatus != Task.runStatuses.DONE) {
|
||||
let now = (new Date()).getTime();
|
||||
if (now - this.startTime > jake._taskTimeout) {
|
||||
return jake.fail(`Timed out waiting for task: ${previous.name} with status of ${previous.taskStatus}`);
|
||||
}
|
||||
setTimeout(this.run.bind(this), POLLING_INTERVAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(this.reenabled && previous == this)) {
|
||||
this._invocationChain.push(this);
|
||||
}
|
||||
|
||||
if (!(this._internal || jake.program.opts.quiet)) {
|
||||
console.log("Starting '" + chalk.green(this.fullName) + "'...");
|
||||
}
|
||||
|
||||
this.startTime = (new Date()).getTime();
|
||||
this.emit('start');
|
||||
|
||||
jake.currentRunningTask = this;
|
||||
|
||||
if (hasAction) {
|
||||
try {
|
||||
if (this.directory) {
|
||||
process.chdir(this.directory);
|
||||
}
|
||||
|
||||
val = this.action.apply(this, this.args);
|
||||
|
||||
if (typeof val == 'object' && typeof val.then == 'function') {
|
||||
this.async = true;
|
||||
|
||||
val.then(
|
||||
(result) => {
|
||||
setImmediate(() => {
|
||||
this.complete(result);
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
setImmediate(() => {
|
||||
this.errorOut(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
this.errorOut(err);
|
||||
return; // Bail out, not complete
|
||||
}
|
||||
}
|
||||
|
||||
if (!(hasAction && this.async)) {
|
||||
setImmediate(() => {
|
||||
this.complete(val);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errorOut(err) {
|
||||
this.taskStatus = Task.runStatuses.ERROR;
|
||||
this._invocationChain.chainStatus = Task.runStatuses.ERROR;
|
||||
this.emit('error', err);
|
||||
}
|
||||
|
||||
complete(val) {
|
||||
|
||||
if (Array.isArray(this._waitForChains)) {
|
||||
let stillWaiting = this._waitForChains.some((chain) => {
|
||||
return !(chain.chainStatus == Task.runStatuses.DONE ||
|
||||
chain.chainStatus == Task.runStatuses.ERROR);
|
||||
});
|
||||
if (stillWaiting) {
|
||||
let now = (new Date()).getTime();
|
||||
let elapsed = now - this.startTime;
|
||||
if (elapsed > jake._taskTimeout) {
|
||||
return jake.fail(`Timed out waiting for task: ${this.name} with status of ${this.taskStatus}. Elapsed: ${elapsed}`);
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.complete(val);
|
||||
}, POLLING_INTERVAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
jake._invocationChain.splice(jake._invocationChain.indexOf(this), 1);
|
||||
|
||||
if (this._invocationChainRoot) {
|
||||
this._invocationChain.chainStatus = Task.runStatuses.DONE;
|
||||
}
|
||||
|
||||
this._currentPrereqIndex = 0;
|
||||
|
||||
// If 'complete' getting called because task has been
|
||||
// run already, value will not be passed -- leave in place
|
||||
if (!this._skipped) {
|
||||
this.taskStatus = Task.runStatuses.DONE;
|
||||
this.value = val;
|
||||
|
||||
this.emit('complete', this.value);
|
||||
this.emit('_done');
|
||||
|
||||
this.endTime = (new Date()).getTime();
|
||||
let taskTime = this.endTime - this.startTime;
|
||||
|
||||
if (!(this._internal || jake.program.opts.quiet)) {
|
||||
console.log("Finished '" + chalk.green(this.fullName) + "' after " + chalk.magenta(taskTime + ' ms'));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_getFullName() {
|
||||
let ns = this.namespace;
|
||||
let path = (ns && ns.path) || '';
|
||||
path = (path && path.split(':')) || [];
|
||||
if (this.namespace !== jake.defaultNamespace) {
|
||||
path.push(this.namespace.name);
|
||||
}
|
||||
path.push(this.name);
|
||||
return path.join(':');
|
||||
}
|
||||
|
||||
static getBaseNamespacePath(fullName) {
|
||||
return fullName.split(':').slice(0, -1).join(':');
|
||||
}
|
||||
|
||||
static getBaseTaskName(fullName) {
|
||||
return fullName.split(':').pop();
|
||||
}
|
||||
}
|
||||
|
||||
Task.runStatuses = {
|
||||
UNSTARTED: 'unstarted',
|
||||
DONE: 'done',
|
||||
STARTED: 'started',
|
||||
ERROR: 'error'
|
||||
};
|
||||
|
||||
Task.ROOT_TASK_NAME = ROOT_TASK_NAME;
|
||||
|
||||
exports.Task = Task;
|
||||
|
||||
// Required here because circular deps
|
||||
require('../rule');
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue