mecano
Version:
Common functions for system deployment.
371 lines (362 loc) • 10.2 kB
JavaScript
// Generated by CoffeeScript 1.9.1
var handler, name, register, registered, registry, wrap,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
slice = [].slice;
module.exports = function() {
var call_async, call_callback, call_sync, handler, i, jump_to_error, len, name, obj, option, properties, proto, ref, run, stack, todos;
if (arguments.length === 2) {
obj = arguments[0];
obj.options = arguments[1];
} else if (arguments.length === 1) {
obj = {};
obj.options = arguments[0];
} else {
obj = {};
obj.options = {};
}
if (obj.registry == null) {
obj.registry = {};
}
if (obj.propagated_options == null) {
obj.propagated_options = [];
}
ref = module.exports.propagated_options;
for (i = 0, len = ref.length; i < len; i++) {
option = ref[i];
obj.propagated_options.push(option);
}
properties = {};
stack = [];
todos = [];
todos.err = null;
todos.changed = false;
todos.throw_if_error = true;
call_callback = function(fn, args) {
var err, mtodos;
stack.unshift(todos);
todos = [];
todos.err = null;
todos.changed = false;
todos.throw_if_error = true;
try {
fn.apply(obj, args);
} catch (_error) {
err = _error;
todos = stack.shift();
jump_to_error(err);
return run();
}
mtodos = todos;
todos = stack.shift();
if (mtodos.length) {
return todos.unshift.apply(todos, mtodos);
}
};
call_sync = function(fn, args) {
var err, mtodos, status;
stack.unshift(todos);
todos = [];
todos.err = null;
todos.changed = false;
todos.throw_if_error = true;
try {
status = fn.apply(obj, args);
} catch (_error) {
err = _error;
todos = stack.shift();
jump_to_error(err);
return run();
}
mtodos = todos;
todos = stack.shift();
if (mtodos.length) {
todos.unshift.apply(todos, mtodos);
}
return status;
};
call_async = function(action) {
var callback, err, finish, global_options, j, k, l, len1, len2, len3, local_options, local_options_array, local_opts, m, options, opts, parent_options, status_action, status_callback, v;
global_options = obj.options;
parent_options = todos.options;
local_options = action.args[0];
callback = action.args[1];
if (local_options == null) {
local_options = {};
}
local_options_array = Array.isArray(local_options);
if (!local_options_array) {
local_options = [local_options];
}
options = [];
for (j = 0, len1 = local_options.length; j < len1; j++) {
local_opts = local_options[j];
if ((local_opts != null) && typeof local_opts !== 'object') {
local_opts = {
argument: local_opts
};
}
opts = {};
for (k in local_opts) {
v = local_opts[k];
opts[k] = local_opts[k];
}
options.push(opts);
}
for (k in parent_options) {
v = parent_options[k];
for (l = 0, len2 = options.length; l < len2; l++) {
opts = options[l];
if (opts[k] === void 0 && indexOf.call(obj.propagated_options, k) >= 0) {
opts[k] = v;
}
}
}
for (k in global_options) {
v = global_options[k];
for (m = 0, len3 = options.length; m < len3; m++) {
opts = options[m];
if (opts[k] === void 0) {
opts[k] = v;
}
}
}
try {
stack.unshift(todos);
todos = [];
todos.err = null;
todos.changed = false;
todos.throw_if_error = true;
status_callback = [];
status_action = [];
finish = function(err) {
var callback_args;
if (arguments.length === 0) {
arguments.length = 2;
}
if (todos.length === 0) {
todos = stack.shift();
}
if (err && callback) {
todos.throw_if_error = false;
}
if (err) {
jump_to_error(err);
}
status_callback = status_callback.some(function(status) {
return !!status;
});
status_action = status_action.some(function(status) {
return !!status;
});
callback_args = [err, status_callback].concat(slice.call([].slice.call(arguments).slice(1)));
if (callback) {
call_callback(callback, callback_args);
}
if (status_action && !options.shy) {
todos.changed = true;
}
return run();
};
if (!local_options_array) {
options = options[0];
}
return wrap(obj, [options, finish], function(options, callback) {
todos.options = options;
return action.handler.call(obj, options, function() {
var args, err, status;
err = arguments[0], status = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
status_callback.push(status);
if (!options.shy) {
status_action.push(status);
}
return setImmediate(function() {
return callback.apply(null, [err, status].concat(slice.call(args)));
});
});
});
} catch (_error) {
err = _error;
todos = stack.shift();
jump_to_error(err);
return run();
}
};
jump_to_error = function(err) {
while (todos[0] && todos[0].type !== 'then') {
todos.shift();
}
return todos.err = err;
};
run = function() {
var changed, err, fn, ref1, todo;
todo = todos.shift();
if (!todo) {
if (todos.err && todos.throw_if_error) {
throw todos.err;
}
return;
}
if (todo.type === 'then') {
err = todos.err, changed = todos.changed;
todos.err = null;
todos.changed = false;
todos.throw_if_error = true;
todo.args[0].call(obj, err, changed);
run();
return;
}
if (todo.type === 'call') {
if (todo.args[0].length === 2) {
return call_async({
type: todo.type,
args: todo.args,
handler: todo.args[0]
});
} else {
changed = call_sync(todo.args[0], []);
if (changed) {
todos.changed = true;
}
return run();
}
}
todo.args[0].user_args = ((ref1 = todo.args[1]) != null ? ref1.length : void 0) > 2;
fn = obj.registry[todo.type] || registry[todo.type];
return call_async({
type: todo.type,
args: todo.args,
handler: obj.registry[todo.type] || registry[todo.type]
});
};
properties.child = {
get: function() {
return function() {
return module.exports(obj.options);
};
}
};
properties.then = {
get: function() {
return function() {
todos.push({
type: 'then',
args: arguments
});
if (todos.length === 1) {
process.nextTick(run);
}
return obj;
};
}
};
properties.call = {
get: function() {
return function() {
todos.push({
type: 'call',
args: arguments
});
process.nextTick(function() {});
if (todos.length === 1) {
process.nextTick(run);
}
return obj;
};
}
};
proto = Object.defineProperties(obj, properties);
Object.defineProperty(obj, 'register', {
get: function() {
return function(name, handler) {
var is_registered_locally;
is_registered_locally = obj.registered(name, true);
if (handler === null || handler === false) {
if (is_registered_locally) {
delete obj.registry[name];
delete obj[name];
} else if (module.exports.registered(name)) {
throw Error('Unregister a global function from local context');
}
return obj;
}
if (is_registered_locally) {
throw Error("Function already defined '" + name + "'");
}
obj.registry[name] = handler;
return Object.defineProperty(obj, name, {
configurable: true,
get: function() {
return function() {
var dest, ref1;
dest = (ref1 = arguments[0]) != null ? ref1.destination : void 0;
todos.push({
type: name,
args: arguments
});
if (todos.length === 1) {
process.nextTick(run);
}
return obj;
};
}
});
};
}
});
Object.defineProperty(obj, 'registered', {
get: function() {
return function(name, local_only) {
var global, local;
if (local_only == null) {
local_only = false;
}
global = Object.prototype.hasOwnProperty.call(module.exports, name);
local = Object.prototype.hasOwnProperty.call(obj, name);
if (local_only) {
return local;
} else {
return global || local;
}
};
}
});
for (name in registry) {
handler = registry[name];
obj.register(name, handler);
}
return obj;
};
module.exports.propagated_options = ['ssh', 'log', 'stdout', 'stderr'];
register = module.exports.register = function(name, handler) {
if (handler === null || handler === false) {
if (registered(name)) {
delete registry[name];
}
if (registered(name)) {
delete module.exports[name];
}
return module.exports;
}
if (registered(name)) {
throw Error("Function already defined '" + name + "'");
}
if (name !== 'call') {
registry[name] = handler;
}
return Object.defineProperty(module.exports, name, {
configurable: true,
get: function() {
return module.exports()[name];
}
});
};
registered = module.exports.registered = function(name) {
return Object.prototype.hasOwnProperty.call(module.exports, name);
};
registry = require('./misc/registry');
for (name in registry) {
handler = registry[name];
register(name, handler);
}
register('call', module.exports().call);
wrap = require('./misc/wrap');