mecano
Version:
Common functions for system deployment.
248 lines (233 loc) • 6.91 kB
JavaScript
// Generated by CoffeeScript 1.11.1
var crypto, each, exec, file, fs, glob, rimraf, ssh2fs,
slice = [].slice;
ssh2fs = require('ssh2-fs');
crypto = require('crypto');
exec = require('ssh2-exec');
each = require('each');
fs = require('fs');
glob = require('./glob');
rimraf = require('rimraf');
module.exports = file = {
copyFile: function(ssh, source, target, callback) {
var s;
s = function(ssh, callback) {
if (!ssh) {
return callback(null, fs);
} else {
return ssh.sftp(callback);
}
};
return s(ssh, function(err, fs) {
var rs, ws;
if (err) {
return callback(err);
}
rs = fs.createReadStream(source);
ws = rs.pipe(fs.createWriteStream(target));
ws.on('close', function() {
var modified;
if (fs.end) {
fs.end();
}
modified = true;
return callback();
});
return ws.on('error', callback);
});
},
/*
Compare modes
-------------
*/
cmpmod: function() {
var modes, ref;
modes = 1 <= arguments.length ? slice.call(arguments, 0) : [];
console.log('Deprecated, use `misc.mode.compare`');
return (ref = misc.mode.compare).call.apply(ref, [this].concat(slice.call(modes)));
},
copy: function(ssh, source, target, callback) {
if (!ssh) {
source = fs.createReadStream(u.pathname);
source.pipe(target);
target.on('close', callback);
return target.on('error', callback);
} else {
return callback(new Error('Copy over SSH not yet implemented'));
}
},
/*
`files.compare(files, callback)`
--------------------------------
Compare the hash of multiple file. Return the file md5
if the file are the same or false otherwise.
*/
compare: function(ssh, files, callback) {
var result;
if (files.length < 2) {
return callback(new Error('Minimum of 2 files'));
}
result = null;
return each(files).call(function(f, next) {
return file.hash(ssh, f, function(err, md5) {
if (err) {
return next(err);
}
if (result === null) {
result = md5;
} else if (result !== md5) {
result = false;
}
return next();
});
}).then(function(err) {
if (err) {
return callback(err);
}
return callback(null, result);
});
},
compare_hash: function(ssh1, file1, ssh2, file2, algo, callback) {
return file.hash(ssh1, file1, algo, function(err, hash1) {
if (err) {
return callback(err);
}
return file.hash(ssh2, file2, algo, function(err, hash2) {
if ((err != null ? err.code : void 0) === 'ENOENT') {
err = null;
}
if (err) {
return callback(err);
}
return callback(null, hash1 === hash2, hash1, hash2);
});
});
},
/*
`files.hash(file, [algorithm], callback)`
-----------------------------------------
Retrieve the hash of a supplied file in hexadecimal
form. If the provided file is a directory, the returned hash
is the sum of all the hashs of the files it recursively
contains. The default algorithm to compute the hash is md5.
Throw an error if file does not exist unless it is a directory.
file.hash ssh, '/path/to/file', (err, md5) ->
md5.should.eql '287621a8df3c3f6c99c7b7645bd09ffd'
*/
hash: function(ssh, file, algorithm, callback) {
var hasher, hashs;
if (arguments.length === 3) {
callback = algorithm;
algorithm = 'md5';
}
hasher = function(ssh, path, callback) {
var shasum;
shasum = crypto.createHash(algorithm);
if (!ssh) {
return ssh2fs.createReadStream(ssh, path, function(err, stream) {
if (err) {
return callback(err);
}
return stream.on('data', function(data) {
return shasum.update(data);
}).on('error', function(err) {
if (err.code === 'EISDIR') {
return callback();
}
return callback(err);
}).on('end', function() {
return callback(err, shasum.digest('hex'));
});
});
} else {
return ssh2fs.stat(ssh, path, function(err, stat) {
if (err) {
return callback(err);
}
if (stat.isDirectory()) {
return callback();
}
return exec({
cmd: "openssl " + algorithm + " " + path + " | sed 's/^.* \\([a-z0-9]*\\)$/\\1/g'",
ssh: ssh,
trim: true
}, function(err, stdout) {
return callback(err, stdout != null ? stdout.trim() : void 0);
});
});
}
};
hashs = [];
return ssh2fs.stat(ssh, file, function(err, stat) {
var compute;
if ((err != null ? err.code : void 0) === 'ENOENT') {
err = Error("Does not exist: " + file);
err.code = 'ENOENT';
return callback(err);
}
if (err) {
return callback(err);
}
if (stat.isFile()) {
return hasher(ssh, file, callback);
} else if (stat.isDirectory()) {
compute = function(files) {
files.sort();
return each(files).call(function(item, next) {
return hasher(ssh, item, function(err, h) {
if (err) {
return next(err);
}
if (h != null) {
hashs.push(h);
}
return next();
});
}).then(function(err) {
if (err) {
return callback(err);
}
switch (hashs.length) {
case 0:
if (stat.isFile()) {
return callback(new Error("Does not exist: " + file));
} else {
return callback(null, crypto.createHash(algorithm).update('').digest('hex'));
}
break;
case 1:
return callback(null, hashs[0]);
default:
hashs = crypto.createHash(algorithm).update(hashs.join('')).digest('hex');
return callback(null, hashs);
}
});
};
return glob(ssh, file + "/**", function(err, files) {
if (err) {
return callback(err);
}
return compute(files);
});
} else {
return callback(Error("File type not supported"));
}
});
},
/*
remove(ssh, path, callback)
---------------------------
Remove a file or directory
*/
remove: function(ssh, path, callback) {
var child;
if (!ssh) {
return rimraf(path, callback);
} else {
child = exec(ssh, "rm -rf " + path);
return child.on('exit', function(code) {
return callback(null, code);
});
}
}
};