Skip to content

Commit 96e84de

Browse files
authored
fix: check cache file existence before deletion (#19648)
* fix: check cache file existence before deletion * fix test * tweak api * fix tests * refactor
1 parent c25e858 commit 96e84de

2 files changed

Lines changed: 75 additions & 15 deletions

File tree

lib/eslint/eslint.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -704,15 +704,11 @@ class ESLint {
704704
debug(`Deleting cache file at ${cacheFilePath}`);
705705

706706
try {
707-
await fs.unlink(cacheFilePath);
707+
if (existsSync(cacheFilePath)) {
708+
await fs.unlink(cacheFilePath);
709+
}
708710
} catch (error) {
709-
const errorCode = error && error.code;
710-
711-
// Ignore errors when no such file exists or file system is read only (and cache file does not exist)
712-
if (
713-
errorCode !== "ENOENT" &&
714-
!(errorCode === "EROFS" && !existsSync(cacheFilePath))
715-
) {
711+
if (existsSync(cacheFilePath)) {
716712
throw error;
717713
}
718714
}

tests/lib/eslint/eslint.js

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12504,25 +12504,90 @@ describe("ESLint", () => {
1250412504
);
1250512505
});
1250612506

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

12515+
const spy = sinon.spy(fsp, "unlink");
12516+
12517+
const eslintOptions = {
12518+
overrideConfigFile: true,
12519+
cache: false,
12520+
cacheLocation: cacheFilePath,
12521+
overrideConfig: {
12522+
rules: {
12523+
"no-console": 0,
12524+
"no-unused-vars": 2,
12525+
},
12526+
},
12527+
cwd: path.join(fixtureDir, ".."),
12528+
};
12529+
12530+
eslint = new ESLint(eslintOptions);
12531+
12532+
const file = getFixturePath("cache/src", "test-file.js");
12533+
12534+
await eslint.lintFiles([file]);
12535+
12536+
assert(
12537+
spy.notCalled,
12538+
"Expected attempt to delete the cache was not made.",
12539+
);
12540+
12541+
spy.restore();
12542+
});
12543+
12544+
it("should throw an error if the cache file to be deleted exist on a read-only file system", async () => {
12545+
cacheFilePath = getFixturePath(".eslintcache");
12546+
fs.writeFileSync(cacheFilePath, "");
12547+
1251512548
// Simulate a read-only file system.
12516-
sinon.stub(fsp, "unlink").rejects(
12549+
const unlinkStub = sinon.stub(fsp, "unlink").rejects(
1251712550
Object.assign(new Error("read-only file system"), {
1251812551
code: "EROFS",
1251912552
}),
1252012553
);
1252112554

1252212555
const eslintOptions = {
1252312556
overrideConfigFile: true,
12557+
cache: false,
12558+
cacheLocation: cacheFilePath,
12559+
overrideConfig: {
12560+
rules: {
12561+
"no-console": 0,
12562+
"no-unused-vars": 2,
12563+
},
12564+
},
12565+
cwd: path.join(fixtureDir, ".."),
12566+
};
12567+
12568+
eslint = new ESLint(eslintOptions);
12569+
12570+
const file = getFixturePath("cache/src", "test-file.js");
12571+
12572+
await assert.rejects(
12573+
async () => await eslint.lintFiles([file]),
12574+
/read-only file system/u,
12575+
);
1252412576

12525-
// specifying cache false the cache will be deleted
12577+
unlinkStub.restore();
12578+
});
12579+
12580+
it("should not throw an error if deleting fails but cache file no longer exists", async () => {
12581+
cacheFilePath = getFixturePath(".eslintcache");
12582+
fs.writeFileSync(cacheFilePath, "");
12583+
12584+
const unlinkStub = sinon.stub(fsp, "unlink").callsFake(() => {
12585+
doDelete(cacheFilePath);
12586+
throw new Error("Failed to delete cache file");
12587+
});
12588+
12589+
const eslintOptions = {
12590+
overrideConfigFile: true,
1252612591
cache: false,
1252712592
cacheLocation: cacheFilePath,
1252812593
overrideConfig: {
@@ -12540,10 +12605,9 @@ describe("ESLint", () => {
1254012605

1254112606
await eslint.lintFiles([file]);
1254212607

12543-
assert(
12544-
fsp.unlink.calledWithExactly(cacheFilePath),
12545-
"Expected attempt to delete the cache was not made.",
12546-
);
12608+
assert(unlinkStub.calledWithExactly(cacheFilePath));
12609+
12610+
unlinkStub.restore();
1254712611
});
1254812612

1254912613
it("should store in the cache a file that has lint messages and a file that doesn't have lint messages", async () => {

0 commit comments

Comments
 (0)