123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
-
-
- (function(exports) {
-
- 'use strict';
-
-
- function Task() {
-
- this.current = {};
-
- this._tasks = {};
-
- this._queue = [];
-
- this._placeholder = {placeholder: true};
-
- this._marker = {marker: true};
-
- this._options = {};
-
- this._running = false;
-
- this._success = {};
- }
-
-
- exports.Task = Task;
-
-
- exports.create = function() {
- return new Task();
- };
-
-
-
- Task.prototype._throwIfRunning = function(obj) {
- if (this._running || !this._options.error) {
-
- throw obj;
- } else {
-
- this._options.error.call({name: null}, obj);
- }
- };
-
-
- Task.prototype.registerTask = function(name, info, fn) {
-
- if (fn == null) {
- fn = info;
- info = null;
- }
-
- var tasks;
- if (typeof fn !== 'function') {
-
- tasks = this.parseArgs([fn]);
-
- fn = this.run.bind(this, fn);
- fn.alias = true;
-
- if (!info) {
- info = 'Alias for "' + tasks.join('", "') + '" task' +
- (tasks.length === 1 ? '' : 's') + '.';
- }
- } else if (!info) {
- info = 'Custom task.';
- }
-
- this._tasks[name] = {name: name, info: info, fn: fn};
-
- return this;
- };
-
-
- Task.prototype.isTaskAlias = function(name) {
- return !!this._tasks[name].fn.alias;
- };
-
-
- Task.prototype.exists = function(name) {
- return name in this._tasks;
- };
-
-
-
-
- Task.prototype.renameTask = function(oldname, newname) {
- if (!this._tasks[oldname]) {
- throw new Error('Cannot rename missing "' + oldname + '" task.');
- }
-
- this._tasks[newname] = this._tasks[oldname];
-
- this._tasks[newname].name = newname;
-
- delete this._tasks[oldname];
-
- return this;
- };
-
-
-
-
-
- Task.prototype.parseArgs = function(args) {
-
-
- return Array.isArray(args[0]) ? args[0] : [].slice.call(args);
- };
-
-
-
- Task.prototype.splitArgs = function(str) {
- if (!str) { return []; }
-
- str = str.replace(/\\\\/g, '\uFFFF').replace(/\\:/g, '\uFFFE');
-
- return str.split(':').map(function(s) {
-
- return s.replace(/\uFFFE/g, ':').replace(/\uFFFF/g, '\\');
- });
- };
-
-
-
-
-
-
- Task.prototype._taskPlusArgs = function(name) {
-
- var parts = this.splitArgs(name);
-
- var i = parts.length;
- var task;
- do {
-
- task = this._tasks[parts.slice(0, i).join(':')];
-
-
- } while (!task && --i > 0);
-
- var args = parts.slice(i);
-
- var flags = {};
- args.forEach(function(arg) { flags[arg] = true; });
-
- return {task: task, nameArgs: name, args: args, flags: flags};
- };
-
-
- Task.prototype._push = function(things) {
-
- var index = this._queue.indexOf(this._placeholder);
- if (index === -1) {
-
- this._queue = this._queue.concat(things);
- } else {
-
- [].splice.apply(this._queue, [index, 0].concat(things));
- }
- };
-
-
- Task.prototype.run = function() {
-
- var things = this.parseArgs(arguments).map(this._taskPlusArgs, this);
-
- var fails = things.filter(function(thing) { return !thing.task; });
- if (fails.length > 0) {
- this._throwIfRunning(new Error('Task "' + fails[0].nameArgs + '" not found.'));
- return this;
- }
-
- this._push(things);
-
- return this;
- };
-
-
- Task.prototype.mark = function() {
- this._push(this._marker);
-
- return this;
- };
-
-
- Task.prototype.runTaskFn = function(context, fn, done, asyncDone) {
-
- var async = false;
-
-
- var complete = function(success) {
- var err = null;
- if (success === false) {
-
- err = new Error('Task "' + context.nameArgs + '" failed.');
- } else if (success instanceof Error || {}.toString.call(success) === '[object Error]') {
-
- err = success;
- success = false;
- } else {
-
- success = true;
- }
-
- this.current = {};
-
-
- this._success[context.nameArgs] = success;
-
- if (!success && this._options.error) {
- this._options.error.call({name: context.name, nameArgs: context.nameArgs}, err);
- }
-
-
- if (asyncDone) {
- process.nextTick(function () {
- done(err, success);
- });
- } else {
- done(err, success);
- }
- }.bind(this);
-
-
-
- context.async = function() {
- async = true;
-
-
- return function(success) {
- setTimeout(function() { complete(success); }, 1);
- };
- };
-
-
- this.current = context;
-
- try {
-
-
- var success = fn.call(context);
-
- if (!async) {
- complete(success);
- }
- } catch (err) {
- complete(err);
- }
- };
-
-
- Task.prototype.start = function(opts) {
- if (!opts) {
- opts = {};
- }
-
- if (this._running) { return false; }
-
- var nextTask = function() {
-
- var thing;
-
- do {
- thing = this._queue.shift();
- } while (thing === this._placeholder || thing === this._marker);
-
- if (!thing) {
- this._running = false;
- if (this._options.done) {
- this._options.done();
- }
- return;
- }
-
- this._queue.unshift(this._placeholder);
-
-
- var context = {
-
- nameArgs: thing.nameArgs,
-
- name: thing.task.name,
-
- args: thing.args,
-
- flags: thing.flags
- };
-
-
- this.runTaskFn(context, function() {
- return thing.task.fn.apply(this, this.args);
- }, nextTask, !!opts.asyncDone);
-
- }.bind(this);
-
-
- this._running = true;
-
- nextTask();
- };
-
-
- Task.prototype.clearQueue = function(options) {
- if (!options) { options = {}; }
- if (options.untilMarker) {
- this._queue.splice(0, this._queue.indexOf(this._marker) + 1);
- } else {
- this._queue = [];
- }
-
- return this;
- };
-
-
- Task.prototype.requires = function() {
- this.parseArgs(arguments).forEach(function(name) {
- var success = this._success[name];
- if (!success) {
- throw new Error('Required task "' + name +
- '" ' + (success === false ? 'failed' : 'must be run first') + '.');
- }
- }.bind(this));
- };
-
-
- Task.prototype.options = function(options) {
- Object.keys(options).forEach(function(name) {
- this._options[name] = options[name];
- }.bind(this));
- };
-
- }(typeof exports === 'object' && exports || this));
|