From 23d257de9fbee9d6d293fb32946b90c1466c883b Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Mon, 17 Jun 2019 15:12:41 +0200 Subject: [PATCH] [INTERNAL] fsInterface: Handle non-POSIX paths correctly fs functions can be called with non-POSIX paths on non-POSIX systems --- lib/fsInterface.js | 22 +++++++++++-------- package-lock.json | 13 ++++++++--- package.json | 3 ++- test/fixtures/fsInterface/foo.txt | 2 +- test/lib/fsInterface.js | 36 +++++++++++++++++-------------- 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/lib/fsInterface.js b/lib/fsInterface.js index adb0c0a6..0687faeb 100644 --- a/lib/fsInterface.js +++ b/lib/fsInterface.js @@ -12,8 +12,9 @@ * [mkdir]{@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; @@ -21,7 +22,8 @@ module.exports = (reader) => { if (typeof options === "string") { options = {encoding: options}; } - reader.byPath(path, { + const posixPath = slash(fsPath); + reader.byPath(posixPath, { nodir: false }).then(function(resource) { if (!resource) { @@ -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) { @@ -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) => { @@ -71,7 +75,7 @@ module.exports = (reader) => { callback(null, files); }).catch(callback); }, - mkdir(path, callback) { + mkdir(fsPath, callback) { setTimeout(callback, 0); } }; diff --git a/package-lock.json b/package-lock.json index a591e058..78c67d97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3021,6 +3021,13 @@ "ignore": "^4.0.3", "pify": "^4.0.1", "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + } } }, "got": { @@ -5857,9 +5864,9 @@ } }, "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "slice-ansi": { "version": "1.0.0", diff --git a/package.json b/package.json index 59955a29..a8dbce42 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/test/fixtures/fsInterface/foo.txt b/test/fixtures/fsInterface/foo.txt index 538451fc..6b584e8e 100644 --- a/test/fixtures/fsInterface/foo.txt +++ b/test/fixtures/fsInterface/foo.txt @@ -1 +1 @@ -content of /foo.txt \ No newline at end of file +content \ No newline at end of file diff --git a/test/lib/fsInterface.js b/test/lib/fsInterface.js index d0d7f163..adf4ff1f 100644 --- a/test/lib/fsInterface.js +++ b/test/lib/fsInterface.js @@ -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); })); }; @@ -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) => { @@ -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); @@ -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) => { @@ -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) => {