UNPKG

mecano

Version:

Common functions for system deployment.

420 lines (406 loc) 13.6 kB
// Generated by CoffeeScript 1.7.1 var child, chmod, chown, conditions, diff, each, eco, fs, misc, mkdir, pad, path; fs = require('ssh2-fs'); path = require('path'); each = require('each'); eco = require('eco'); pad = require('pad'); diff = require('diff'); misc = require('./misc'); conditions = require('./misc/conditions'); child = require('./misc/child'); mkdir = require('./mkdir'); chown = require('./chown'); chmod = require('./chmod'); module.exports = function(goptions, options, callback) { var finish, result, _ref; _ref = misc.args(arguments, { parallel: 1 }), goptions = _ref[0], options = _ref[1], callback = _ref[2]; result = child(); finish = function(err, written) { if (callback) { callback(err, written); } return result.end(err, written); }; misc.options(options, function(err, options) { var written; if (err) { return finish(err); } written = 0; return each(options).parallel(goptions.parallel).on('item', function(options, next) { var append, between, content, destination, destinationHash, do_backup, do_diff, do_end, do_eof, do_ownership, do_permissions, do_read_destination, do_read_source, do_render, do_replace_partial, do_write, from, modified, to, write, _ref1; modified = false; if (!((options.source || (options.content != null)) || options.replace || ((_ref1 = options.write) != null ? _ref1.length : void 0))) { return next(new Error('Missing source or content')); } if (options.source && options.content) { return next(new Error('Define either source or content')); } if (!options.destination) { return next(new Error('Missing destination')); } if (options.content && Buffer.isBuffer(options.content)) { options.content = options.content.toString(); } if (options.diff == null) { options.diff = options.diff || !!options.stdout; } switch (options.eof) { case 'unix': options.eof = "\n"; break; case 'mac': options.eof = "\r"; break; case 'windows': options.eof = "\r\n"; break; case 'unicode': options.eof = "\u2028"; } destination = null; destinationHash = null; content = null; from = to = between = null; append = options.append; write = options.write; if (write == null) { write = []; } if ((options.from != null) || (options.to != null) || (options.match != null)) { write.push({ from: options.from, to: options.to, match: options.match, replace: options.replace, append: options.append }); } do_read_source = function() { var source, ssh; if (options.content != null) { content = options.content; if (typeof content === 'number') { content = "" + content; } return do_read_destination(); } source = options.source || options.destination; if (typeof options.log === "function") { options.log("Read source: " + source + (options.local_source ? ' (local)' : '')); } ssh = options.local_source ? null : options.ssh; return fs.exists(ssh, source, function(err, exists) { if (err) { return next(err); } if (!exists) { if (options.source) { return next(new Error("Source does not exist: \"" + options.source + "\"")); } content = ''; return do_read_destination(); } return fs.readFile(ssh, source, 'utf8', function(err, src) { if (err) { return next(err); } content = src; return do_read_destination(); }); }); }; do_read_destination = function() { var do_mkdir, do_read, exists; if (typeof options.destination === 'function') { return do_render(); } if (typeof options.log === "function") { options.log("Read destination: " + options.destination); } exists = function() { return fs.stat(options.ssh, options.destination, function(err, stat) { if ((err != null ? err.code : void 0) === 'ENOENT') { return do_mkdir(); } if (err) { return next(err); } if (stat.isDirectory()) { options.destination = "" + options.destination + "/" + (path.basename(options.source)); return fs.stat(options.ssh, options.destination, function(err, stat) { if ((err != null ? err.code : void 0) === 'ENOENT') { return do_render(); } if (err) { return next(err); } if (!stat.isFile()) { return next(new Error("Destination is not a file: " + options.destination)); } return do_read(); }); } else { return do_read(); } }); }; do_mkdir = function() { return mkdir({ ssh: options.ssh, destination: path.dirname(options.destination), uid: options.uid, gid: options.gid, mode: options.mode, not_if_exists: path.dirname(options.destination) }, function(err, created) { if (err) { return next(err); } return do_render(); }); }; do_read = function() { return fs.readFile(options.ssh, options.destination, 'utf8', function(err, dest) { if (err) { return next(err); } if (options.diff) { destination = dest; } destinationHash = misc.string.hash(dest); return do_render(); }); }; return exists(); }; do_render = function() { if (options.context == null) { return do_replace_partial(); } try { content = eco.render(content.toString(), options.context); } catch (_error) { err = _error; if (typeof err === 'string') { err = new Error(err); } return next(err); } return do_replace_partial(); }; do_replace_partial = function() { var linebreak, opts, orgContent, pos, posoffset, res, _i, _len; if (!write.length) { return do_eof(); } for (_i = 0, _len = write.length; _i < _len; _i++) { opts = write[_i]; if (opts.match) { if (opts.match instanceof RegExp) { if (opts.match.test(content)) { content = content.replace(opts.match, opts.replace); append = false; } else if (opts.append && typeof opts.replace === 'string') { if (typeof opts.append === "string") { opts.append = new RegExp("^.*" + opts.append + ".*$", 'mg'); } if (opts.append instanceof RegExp) { posoffset = 0; orgContent = content; while ((res = opts.append.exec(orgContent)) !== null) { pos = posoffset + res.index + res[0].length; content = content.slice(0, pos) + '\n' + opts.replace + content.slice(pos); posoffset += opts.replace.length + 1; if (!opts.append.global) { break; } } append = false; } else { linebreak = content.length === 0 || content.substr(content.length - 1) === '\n' ? '' : '\n'; content = content + linebreak + opts.replace; append = false; } } else { continue; } } else { from = content.indexOf(opts.match); to = from + opts.match.length; content = content.substr(0, from) + opts.replace + content.substr(to); } } else { from = opts.from ? content.indexOf(opts.from) + opts.from.length : 0; to = opts.to ? content.indexOf(opts.to) : content.length; content = content.substr(0, from) + opts.replace + content.substr(to); } } return do_eof(); }; do_eof = function() { var char, i, _i, _len; if (options.eof == null) { return do_diff(); } if (options.eof === true) { for (i = _i = 0, _len = content.length; _i < _len; i = ++_i) { char = content[i]; if (char === '\r') { options.eof = content[i + 1] === '\n' ? '\r\n' : char; break; } if (char === '\n' || char === '\u2028') { options.eof = char; break; } } if (options.eof === true) { options.eof = '\n'; } } if (!misc.string.endsWith(content, options.eof)) { content += options.eof; } return do_diff(); }; do_diff = function() { var count_added, count_removed, line, lines, ls, padsize, _i, _j, _k, _len, _len1, _len2; if (destinationHash === misc.string.hash(content)) { return do_ownership(); } if (typeof options.log === "function") { options.log("File content has changed"); } if (options.diff) { lines = diff.diffLines(destination, content); if (typeof options.diff === 'function') { options.diff(lines); } if (options.stdout) { count_added = count_removed = 0; padsize = Math.ceil(lines.length / 10); for (_i = 0, _len = lines.length; _i < _len; _i++) { line = lines[_i]; if (line.value === null) { continue; } if (!line.added && !line.removed) { count_added++; count_removed++; continue; } ls = line.value.split(/\r\n|[\n\r\u0085\u2028\u2029]/g); if (line.added) { for (_j = 0, _len1 = ls.length; _j < _len1; _j++) { line = ls[_j]; count_added++; options.stdout.write("" + (pad(padsize, '' + count_added)) + " + " + line + "\n"); } } else { for (_k = 0, _len2 = ls.length; _k < _len2; _k++) { line = ls[_k]; count_removed++; options.stdout.write("" + (pad(padsize, '' + count_removed)) + " - " + line + "\n"); } } } } } return do_write(); }; do_write = function() { if (typeof options.destination === 'function') { options.destination(content); return do_end(); } else { if (append) { if (options.flags == null) { options.flags = 'a'; } } return fs.writeFile(options.ssh, options.destination, content, options, function(err) { if (err) { return next(err); } modified = true; return do_backup(); }); } }; do_backup = function() { var backup; if (!options.backup) { return do_end(); } backup = options.backup; if (backup === true) { backup = "." + (Date.now()); } backup = "" + options.destination + backup; return fs.writeFile(options.ssh, backup, content, function(err) { if (err) { return next(err); } return do_end(); }); }; do_ownership = function() { if (!((options.uid != null) && (options.gid != null))) { return do_permissions(); } return chown({ ssh: options.ssh, destination: options.destination, uid: options.uid, gid: options.gid, log: options.log, stdout: options.stdout, stderr: options.stderr }, function(err, chowned) { if (err) { return next(err); } if (chowned) { modified = true; } return do_permissions(); }); }; do_permissions = function() { if (options.mode == null) { return do_end(); } return chmod({ ssh: options.ssh, destination: options.destination, mode: options.mode, log: options.log, stdout: options.stdout, stderr: options.stderr }, function(err, chmoded) { if (err) { return next(err); } if (chmoded) { modified = true; } return do_end(); }); }; do_end = function() { if (modified) { written++; } return next(); }; return conditions.all(options, next, do_read_source); }).on('both', function(err) { return finish(err, written); }); }); return result; };