Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code to escape non-escaped spaces in arg paths #47

Merged
merged 2 commits into from Aug 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/tmp
/node_modules
/node_modules
/tmp with spaces
9 changes: 7 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@ module.exports = function(grunt) {
shell: {
tmpdir : {
command: "mkdir tmp"
},
tmpdir_with_spaces: {
command: "mkdir 'tmp with spaces'"
}
},
clean: {
tmp: ["tmp"]
tmp: ["tmp"],
tmp_with_spaces: ["tmp with spaces"]
},
vows: {
all: {
src: [
"tests/package.js",
"tests/errors.js",
"tests/single-copy.js",
"tests/single-copy-with-escaped-spaces.js",
"tests/multi-copy.js",
"tests/src-as-array.js",
"tests/remote-host.js",
Expand All @@ -53,5 +58,5 @@ module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-contrib-clean");
grunt.loadNpmTasks("grunt-vows");

grunt.registerTask("test",["jshint","clean:tmp","shell:tmpdir","vows","clean:tmp"]);
grunt.registerTask("test",["jshint","clean:tmp","shell:tmpdir","shell:tmpdir_with_spaces","vows","clean:tmp","clean:tmp_with_spaces"]);
};
23 changes: 23 additions & 0 deletions lib/rsyncwrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,33 @@ var spawn = require("child_process").spawn;
var util = require("util");
var _ = require("lodash");

var escapeSpaces = function(path) {
if (typeof path === "string") {
return path.replace(/\b\s/g, "\\ ");
} else {
return path;
}
};

var escapeSpacesInOptions = function(options) {
// Escape paths in the src, dest, include, exclude, and excludeFirst arguments
["src", "dest", "include", "exclude", "excludeFirst"].forEach(function(optionKey) {
var option = options[optionKey];
if (typeof option === "string") {
options[optionKey] = escapeSpaces(option);
} else if (Array.isArray(option) === true) {
options[optionKey] = option.map(escapeSpaces);
}
});

return options;
};

module.exports = function (options,callback) {

options = options || {};
options = util._extend({},options);
options = escapeSpacesInOptions(options);

var platform = options.platform || process.platform; // Enable process.platform to be mocked in options for testing
var isWin = platform === "win32";
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/single filename with spaces.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
txt
95 changes: 95 additions & 0 deletions tests/single-copy-with-escaped-spaces.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"use strict";

var fs = require("fs");
var path = require("path");
var vows = require("vows");
var assert = require("assert");
var rsync = require("../lib/rsyncwrapper");

var srcFile = "single filename with spaces.txt";
var srcFileWithAlreadyEscapedSpaces = "single\ filename\ with\ spaces.txt";
var srcFilePath = path.join("./tests/fixtures/", srcFile);
var srcFileWithAlreadyEscapedSpacesPath = path.join("./tests/fixtures/", srcFileWithAlreadyEscapedSpaces);
var destDir = "./tmp/";
var destDirWithSpaces = "./tmp with spaces/";
var destDirWithAlreadyEscapedSpaces = "./tmp\ with\ spaces/";
var copiedFile = path.join(destDir, srcFile);
var copiedFileWithSpaces = path.join(destDirWithSpaces, srcFile);
var copiedFileWithAlreadyEscapedSpaces = path.join(destDirWithAlreadyEscapedSpaces, srcFileWithAlreadyEscapedSpaces);

var commandWithNonEscapedSpaces = null;

exports.suite = vows.describe("Single file with spaces in filename copy tests").addBatch({
"Copying a single file (with spaces in filename) into a dir": {
topic: function() {
rsync({
src: srcFilePath,
dest: destDir
},this.callback);
},
"does not error": function (error,stdout,stderr) {
assert.isNull(error);
},
"results in a file that": {
topic: function () {
fs.stat(copiedFile,this.callback);
},
"can be accessed": function (error,stats) {
assert.isNull(error);
},
"has non-zero size": function (stats) {
assert.isNotZero(stats.size);
}
}
}
}).addBatch({
"Copying a single file (with spaces in filename) into a dir (with spaces in the destination name)": {
topic: function() {
rsync({
src: srcFilePath,
dest: destDirWithSpaces
},this.callback);
},
"does not error": function (error,stdout,stderr, cmd) {
assert.isNull(error);
commandWithNonEscapedSpaces = cmd;
},
"results in a file that": {
topic: function () {
fs.stat(copiedFileWithSpaces,this.callback);
},
"can be accessed": function (error,stats) {
assert.isNull(error);
},
"has non-zero size": function (stats) {
assert.isNotZero(stats.size);
}
}
}
}).addBatch({
"Copying a single file (with *already escaped* spaces in filename) into a dir (with *already escaped* spaces in the destination name)": {
topic: function() {
rsync({
src: srcFileWithAlreadyEscapedSpacesPath,
dest: destDirWithAlreadyEscapedSpaces
},this.callback);
},
"does not error": function (error,stdout,stderr) {
assert.isNull(error);
},
"does not escape already-escaped spaces": function (error,stdout,stderr, cmd) {
assert.equal(cmd, commandWithNonEscapedSpaces);
},
"results in a file that": {
topic: function () {
fs.stat(copiedFileWithAlreadyEscapedSpaces,this.callback);
},
"can be accessed": function (error,stats) {
assert.isNull(error);
},
"has non-zero size": function (stats) {
assert.isNotZero(stats.size);
}
}
}
});