gulp-rsync
Version:
Rsync tasks for deploying gulp file structures
144 lines (120 loc) • 3.82 kB
JavaScript
;
var assert = require('better-assert');
var every = require('lodash.every');
var isString = require('lodash.isstring');
var spawn = require('child_process').spawn;
function rsync(config) {
if (!(this instanceof rsync)) {
return new rsync(config);
}
assert(typeof config === 'object');
assert(!config.options || typeof config.options === 'object');
this._options = config.options || {};
var sources = config.source;
if (!Array.isArray(sources)) {
sources = [sources];
}
assert(sources.length > 0 && every(sources, isString));
assert(sources.length === 1 || config.destination);
this._sources = sources;
assert(!config.destination || typeof config.destination === 'string');
this._destination = config.destination;
assert(!config.cwd || typeof config.cwd === 'string');
this._cwd = config.cwd;
assert(!config.stdoutHandler || typeof config.stdoutHandler === 'function');
this._stdout = config.stdoutHandler;
assert(!config.stderrHandler || typeof config.stderrHandler === 'function');
this._stderr = config.stderrHandler;
return this;
}
rsync.prototype = {
command: function() {
var args = [];
var shortOptions = [];
var longOptions = [];
for (var key in this._options) {
var value = this._options[key];
if (typeof value !== 'undefined' && value !== false) {
if (key.length === 1 && value === true) {
shortOptions.push(key);
} else {
var values = Array.isArray(value) ? value : [value];
for (var i = 0, l = values.length; i < l; i++) {
longOptions.push({key: key, value: values[i]});
}
}
}
}
if (shortOptions.length > 0) {
args.push('-' + shortOptions.join(''));
}
// "include" -argument must be applied before "exclude"
longOptions.sort(function (a, b) {
if (a.key === 'include') {
return -1;
}
if (b.key === 'include') {
return 1;
}
return 0;
})
if (longOptions.length > 0) {
args = args.concat(longOptions.map(function(option) {
var single = option.key.length === 1;
var output = (single ? '-' : '--') + option.key;
if (typeof option.value !== 'boolean') {
output += (single ? ' ' : '=') + escapeShellArg(option.value);
}
return output;
}));
}
args = args.concat(this._sources.map(escapeShellArg));
if (this._destination) {
args.push(escapeShellArg(this._destination));
}
return 'rsync ' + args.join(' ');
},
execute: function(callback) {
var command = this.command();
require('gulp-util').log('gulp-rsync:', 'Command: ' + command);
var childProcess;
if (process.platform === 'win32') {
childProcess = spawn('cmd.exe', ['/s', '/c', '"' + command + '"'], {
cwd: this._cwd,
stdio: [process.stdin, 'pipe', 'pipe'],
env: process.env,
windowsVerbatimArguments: true
});
} else {
childProcess = spawn('/bin/sh', ['-c', command], {
cwd: this._cwd,
stdio: 'pipe',
env: process.env
});
}
if (this._stdout) {
childProcess.stdout.on('data', this._stdout);
}
if (this._stderr) {
childProcess.stderr.on('data', this._stderr);
}
childProcess.on('close', function(code) {
var error = null;
if (code !== 0) {
error = new Error('rsync exited with code ' + code);
}
if (typeof callback === 'function') {
callback(error, command);
}
});
return childProcess;
}
};
function escapeShellArg(arg) {
if (!/(["'`\\\(\) ])/.test(arg)) {
return arg;
}
arg = arg.replace(/([\\])/g, '/');
return '"' + arg.replace(/(["'`\\])/g, '\\$1') + '"';
}
module.exports = rsync;