Skip to content

Commit

Permalink
[FIX] fsInterface: Handle non-POSIX paths correctly (#147)
Browse files Browse the repository at this point in the history
fs functions can be called with non-POSIX paths on non-POSIX systems.
fsInterface should handle this correctly by converting any non-POSIX
paths to POSIX for further UI5 FS internal processing.
  • Loading branch information
RandomByte authored Jun 18, 2019
1 parent dc1eef1 commit 1ad0cc8
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 30 deletions.
22 changes: 13 additions & 9 deletions lib/fsInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@
* [<code>mkdir</code>]{@link https://nodejs.org/api/fs.html#fs_fs_mkdir_path_options_callback}
*/
module.exports = (reader) => {
const slash = require("slash");
return {
readFile(path, options, callback) {
readFile(fsPath, options, callback) {
if (typeof options === "function") {
callback = options;
options = undefined;
}
if (typeof options === "string") {
options = {encoding: options};
}
reader.byPath(path, {
const posixPath = slash(fsPath);
reader.byPath(posixPath, {
nodir: false
}).then(function(resource) {
if (!resource) {
Expand All @@ -44,8 +46,9 @@ module.exports = (reader) => {
});
}).catch(callback);
},
stat(path, callback) {
reader.byPath(path, {
stat(fsPath, callback) {
const posixPath = slash(fsPath);
reader.byPath(posixPath, {
nodir: false
}).then(function(resource) {
if (!resource) {
Expand All @@ -57,12 +60,13 @@ module.exports = (reader) => {
}
}).catch(callback);
},
readdir(path, callback) {
if (!path.match(/\/$/)) {
readdir(fsPath, callback) {
let posixPath = slash(fsPath);
if (!posixPath.match(/\/$/)) {
// Add trailing slash if not present
path += "/";
posixPath += "/";
}
reader.byGlob(path + "*", {
reader.byGlob(posixPath + "*", {
nodir: false
}).then((resources) => {
const files = resources.map((resource) => {
Expand All @@ -71,7 +75,7 @@ module.exports = (reader) => {
callback(null, files);
}).catch(callback);
},
mkdir(path, callback) {
mkdir(fsPath, callback) {
setTimeout(callback, 0);
}
};
Expand Down
13 changes: 10 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@
"minimatch": "^3.0.3",
"mock-require": "^3.0.3",
"pretty-hrtime": "^1.0.3",
"random-int": "^2.0.0"
"random-int": "^2.0.0",
"slash": "^3.0.0"
},
"devDependencies": {
"ava": "^2.1.0",
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/fsInterface/foo.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
content of /foo.txt
content
36 changes: 20 additions & 16 deletions test/lib/fsInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@ const MemAdapter = ui5Fs.adapters.Memory;
const FsAdapter = ui5Fs.adapters.FileSystem;
const Resource = ui5Fs.Resource;

const assertReadFile = (t, readFile, basepath, filepath) => {
const fullpath = basepath + filepath;
const assertReadFile = (t, readFile, basepath, filepath, content) => {
content = content || "content of " + filepath;
const fullpath = path.join(basepath, filepath);
return readFile(fullpath).then((buffer) => {
t.true(Buffer.isBuffer(buffer));
t.deepEqual(buffer.toString(), "content of " + filepath);
t.deepEqual(buffer.toString(), content);
}).then(() => readFile(fullpath, {})).then((buffer) => {
t.true(Buffer.isBuffer(buffer));
t.deepEqual(buffer.toString(), "content of " + filepath);
t.deepEqual(buffer.toString(), content);
}).then(() => readFile(fullpath, {encoding: null})).then((buffer) => {
t.true(Buffer.isBuffer(buffer));
t.deepEqual(buffer.toString(), "content of " + filepath);
t.deepEqual(buffer.toString(), content);
}).then(() => readFile(fullpath, "utf8").then((content) => {
t.is(typeof content, "string");
t.deepEqual(content, "content of " + filepath);
t.deepEqual(content, content);
}).then(() => readFile(fullpath, {encoding: "utf8"})).then((content) => {
t.is(typeof content, "string");
t.deepEqual(content, "content of " + filepath);
t.deepEqual(content, content);
}));
};

Expand All @@ -36,10 +37,11 @@ test("MemAdapter: readFile", (t) => {
const fs = fsInterface(memAdapter);
const readFile = promisify(fs.readFile);

const fsPath = path.join("/", "foo.txt");
return memAdapter.write(new Resource({
path: "/foo.txt",
string: "content of /foo.txt"
})).then(() => assertReadFile(t, readFile, "", "/foo.txt"));
string: `content of ${fsPath}`
})).then(() => assertReadFile(t, readFile, "", fsPath));
});

test("FsAdapter: readFile", (t) => {
Expand All @@ -50,17 +52,18 @@ test("FsAdapter: readFile", (t) => {
const fs = fsInterface(fsAdapter);
const readFile = promisify(fs.readFile);

return assertReadFile(t, readFile, "", "/foo.txt");
return assertReadFile(t, readFile, "", path.join("/", "foo.txt"), "content");
});

test("fs: readFile", (t) => {
const readFile = promisify(fs.readFile);
return assertReadFile(t, readFile, path.join(__dirname, "..", "fixtures", "fsInterface"), "/foo.txt");
return assertReadFile(t, readFile,
path.join(__dirname, "..", "fixtures", "fsInterface"), path.join("/", "foo.txt"), "content");
});


const assertStat = (t, stat, basepath, filepath) => {
const fullpath = basepath + filepath;
const fullpath = path.join(basepath, filepath);
return stat(fullpath).then((stats) => {
t.is(stats.isFile(), true);
t.is(stats.isDirectory(), false);
Expand All @@ -79,10 +82,11 @@ test("MemAdapter: stat", (t) => {
const fs = fsInterface(memAdapter);
const stat = promisify(fs.stat);

const fsPath = path.join("/", "foo.txt");
return memAdapter.write(new Resource({
path: "/foo.txt",
string: "content of /foo.txt"
})).then(() => assertStat(t, stat, "", "/foo.txt"));
string: `content of ${fsPath}`
})).then(() => assertStat(t, stat, "", fsPath));
});

test("FsAdapter: stat", (t) => {
Expand All @@ -93,12 +97,12 @@ test("FsAdapter: stat", (t) => {
const fs = fsInterface(fsAdapter);
const stat = promisify(fs.stat);

return assertStat(t, stat, "", "/foo.txt");
return assertStat(t, stat, "", path.join("/", "foo.txt"));
});

test("fs: stat", (t) => {
const stat = promisify(fs.stat);
return assertStat(t, stat, path.join(__dirname, "..", "fixtures", "fsInterface"), "/foo.txt");
return assertStat(t, stat, path.join(__dirname, "..", "fixtures", "fsInterface"), path.join("/", "foo.txt"));
});

test("MemAdapter: mkdir", async (t) => {
Expand Down

0 comments on commit 1ad0cc8

Please sign in to comment.