Skip to content

Commit 6bd27ae

Browse files
authored
Fix problem with caching (#822)
1 parent 96180b0 commit 6bd27ae

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

‎lib/handle-ts-files.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export async function handleTsconfig({cwd, files}: {cwd: string; files: string[]
3737

3838
if (unincludedFiles.length > 0) {
3939
try {
40-
await fs.mkdir(path.dirname(fallbackTsConfigPath), {recursive: true});
4140
await fs.writeFile(fallbackTsConfigPath, JSON.stringify(tsConfig, null, 2));
4241
} catch (error) {
4342
console.error(error);

‎lib/xo.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from 'node:path';
22
import os from 'node:os';
3+
import fs from 'node:fs/promises';
34
import process from 'node:process';
45
import {ESLint, type Linter} from 'eslint';
56
import findCacheDirectory from 'find-cache-directory';
@@ -127,7 +128,7 @@ export class Xo {
127128
flatConfigPath?: string | undefined;
128129

129130
/**
130-
If any user configs contains Prettier, we will need to fetch the Prettier config.
131+
If any user configs contain Prettier, we will need to fetch the Prettier config.
131132
*/
132133
prettier?: boolean;
133134

@@ -231,6 +232,25 @@ export class Xo {
231232
this.xoConfig.push({ignores});
232233
}
233234

235+
/**
236+
Ensures the cache directory exists. This needs to run once before both tsconfig handling and running ESLint occur.
237+
238+
@private
239+
*/
240+
async ensureCacheDirectory() {
241+
try {
242+
const cacheStats = await fs.stat(this.cacheLocation);
243+
// If file, re-create as directory
244+
if (cacheStats.isFile()) {
245+
await fs.rm(this.cacheLocation, {recursive: true, force: true});
246+
await fs.mkdir(this.cacheLocation, {recursive: true});
247+
}
248+
} catch {
249+
// If not exists, create the directory
250+
await fs.mkdir(this.cacheLocation, {recursive: true});
251+
}
252+
}
253+
234254
/**
235255
Checks every TS file to ensure its included in the tsconfig and any that are not included are added to a generated tsconfig for type aware linting.
236256
@@ -274,6 +294,8 @@ export class Xo {
274294

275295
this.setIgnores();
276296

297+
await this.ensureCacheDirectory();
298+
277299
await this.handleUnincludedTsFiles(files);
278300

279301
this.setEslintConfig();

‎test/cli.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,3 +1158,40 @@ test('supports a custom config file with relative dot slash path for TypeScript'
11581158
t.true((error.stdout as string)?.includes('test.js'), 'Error should be reported for the test.js file');
11591159
t.true((error.stdout as string)?.includes('no-console'), 'The specific TypeScript rule should be mentioned in the output');
11601160
});
1161+
1162+
test('replaces cache file with directory when file exists at cache path', async t => {
1163+
const {cwd} = t.context;
1164+
1165+
// Create a simple TS file that will trigger cache creation
1166+
const filePath = path.join(cwd, 'test.ts');
1167+
await fs.writeFile(filePath, dedent`console.log('hello');\n`, 'utf8');
1168+
1169+
// Remove the default tsconfig to force cache creation
1170+
const tsConfigPath = path.join(cwd, 'tsconfig.json');
1171+
await fs.rm(tsConfigPath, {force: true});
1172+
1173+
// Create the cache directory structure up to the parent
1174+
const cacheParentDir = path.join(cwd, 'node_modules', '.cache');
1175+
await fs.mkdir(cacheParentDir, {recursive: true});
1176+
1177+
// Create a FILE at the path where XO needs to create a directory
1178+
const cacheDir = path.join(cacheParentDir, 'xo-linter');
1179+
await fs.writeFile(cacheDir, 'this is a file that should be replaced with a directory', 'utf8');
1180+
1181+
// Verify the file exists before running XO
1182+
const statsBeforeRun = await fs.stat(cacheDir);
1183+
t.true(statsBeforeRun.isFile(), 'Cache path should initially be a file');
1184+
1185+
// Run XO - this should handle the file-to-directory conversion
1186+
await t.notThrowsAsync($`node ./dist/cli --cwd ${cwd}`);
1187+
1188+
// Verify the cache path is now a directory
1189+
const statsAfterRun = await fs.stat(cacheDir);
1190+
t.true(statsAfterRun.isDirectory(), 'Cache path should now be a directory');
1191+
1192+
// Verify the cached tsconfig and the eslint cache file were created
1193+
const cachedFiles = await fs.readdir(cacheDir);
1194+
t.true(cachedFiles.includes('tsconfig.xo.json'), 'Cached tsconfig should exist');
1195+
t.true(cachedFiles.some(file => file.startsWith('.cache')), 'ESLint cache should exist');
1196+
});
1197+

0 commit comments

Comments
 (0)