Skip to content

Commit

Permalink
fix: TypeError: fs.exists is not a function on read-only file system (
Browse files Browse the repository at this point in the history
  • Loading branch information
fasttime committed Dec 13, 2023
1 parent 9271d10 commit 7d5e5f6
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/eslint/flat-eslint.js
Expand Up @@ -11,6 +11,7 @@

// Note: Node.js 12 does not support fs/promises.
const fs = require("fs").promises;
const { existsSync } = require("fs");
const path = require("path");
const findUp = require("find-up");
const { version } = require("../../package.json");
Expand Down Expand Up @@ -766,7 +767,7 @@ class FlatESLint {
const errorCode = error && error.code;

// Ignore errors when no such file exists or file system is read only (and cache file does not exist)
if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !(await fs.exists(cacheFilePath)))) {
if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !existsSync(cacheFilePath))) {
throw error;
}
}
Expand Down
35 changes: 35 additions & 0 deletions tests/lib/eslint/eslint.js
Expand Up @@ -2711,6 +2711,41 @@ describe("ESLint", () => {
assert(!shell.test("-f", cacheFilePath), "the cache for eslint should have been deleted since last run did not use the cache");
});

it("should not throw an error if the cache file to be deleted does not exist on a read-only file system", async () => {
cacheFilePath = getFixturePath(".eslintcache");
doDelete(cacheFilePath);
assert(!shell.test("-f", cacheFilePath), "the cache file already exists and wasn't successfully deleted");

// Simulate a read-only file system.
sinon.stub(fs, "unlinkSync").throws(
Object.assign(new Error("read-only file system"), { code: "EROFS" })
);

const eslintOptions = {
useEslintrc: false,

// specifying cache true the cache will be created
cache: false,
cacheLocation: cacheFilePath,
overrideConfig: {
rules: {
"no-console": 0,
"no-unused-vars": 2
}
},
extensions: ["js"],
cwd: path.join(fixtureDir, "..")
};

eslint = new ESLint(eslintOptions);

const file = getFixturePath("cache/src", "test-file.js");

await eslint.lintFiles([file]);

assert(fs.unlinkSync.calledWithExactly(cacheFilePath), "Expected attempt to delete the cache was not made.");
});

it("should store in the cache a file that has lint messages and a file that doesn't have lint messages", async () => {
cacheFilePath = getFixturePath(".eslintcache");
doDelete(cacheFilePath);
Expand Down
34 changes: 34 additions & 0 deletions tests/lib/eslint/flat-eslint.js
Expand Up @@ -2601,6 +2601,40 @@ describe("FlatESLint", () => {
assert(!shell.test("-f", cacheFilePath), "the cache for eslint should have been deleted since last run did not use the cache");
});

it("should not throw an error if the cache file to be deleted does not exist on a read-only file system", async () => {
cacheFilePath = getFixturePath(".eslintcache");
doDelete(cacheFilePath);
assert(!shell.test("-f", cacheFilePath), "the cache file already exists and wasn't successfully deleted");

// Simulate a read-only file system.
sinon.stub(fsp, "unlink").rejects(
Object.assign(new Error("read-only file system"), { code: "EROFS" })
);

const eslintOptions = {
overrideConfigFile: true,

// specifying cache false the cache will be deleted
cache: false,
cacheLocation: cacheFilePath,
overrideConfig: {
rules: {
"no-console": 0,
"no-unused-vars": 2
}
},
cwd: path.join(fixtureDir, "..")
};

eslint = new FlatESLint(eslintOptions);

const file = getFixturePath("cache/src", "test-file.js");

await eslint.lintFiles([file]);

assert(fsp.unlink.calledWithExactly(cacheFilePath), "Expected attempt to delete the cache was not made.");
});

it("should store in the cache a file that has lint messages and a file that doesn't have lint messages", async () => {
cacheFilePath = getFixturePath(".eslintcache");
doDelete(cacheFilePath);
Expand Down

0 comments on commit 7d5e5f6

Please sign in to comment.