diff --git a/common/changes/@rushstack/eslint-patch/eslint-bulk-issues_2024-03-28-17-06.json b/common/changes/@rushstack/eslint-patch/eslint-bulk-issues_2024-03-28-17-06.json new file mode 100644 index 00000000000..c3286b8f661 --- /dev/null +++ b/common/changes/@rushstack/eslint-patch/eslint-bulk-issues_2024-03-28-17-06.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-patch", + "comment": "Fix an issue with running `eslint-bulk prune` in a project with suppressions that refer to deleted files.", + "type": "patch" + } + ], + "packageName": "@rushstack/eslint-patch" +} \ No newline at end of file diff --git a/eslint/eslint-patch/src/eslint-bulk-suppressions/cli/prune.ts b/eslint/eslint-patch/src/eslint-bulk-suppressions/cli/prune.ts index 288cd1c36dd..9a3b727091a 100755 --- a/eslint/eslint-patch/src/eslint-bulk-suppressions/cli/prune.ts +++ b/eslint/eslint-patch/src/eslint-bulk-suppressions/cli/prune.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. +import fs from 'fs'; + import { printPruneHelp } from './utils/print-help'; import { runEslintAsync } from './runEslint'; import { ESLINT_BULK_PRUNE_ENV_VAR_NAME } from '../constants'; @@ -20,13 +22,11 @@ export async function pruneAsync(): Promise { process.env[ESLINT_BULK_PRUNE_ENV_VAR_NAME] = '1'; - const allFiles: string[] = getAllFilesWithExistingSuppressionsForCwd(); - console.log(`Pruning suppressions for ${allFiles.length} files...`); - + const allFiles: string[] = await getAllFilesWithExistingSuppressionsForCwdAsync(); await runEslintAsync(allFiles, 'prune'); } -function getAllFilesWithExistingSuppressionsForCwd(): string[] { +async function getAllFilesWithExistingSuppressionsForCwdAsync(): Promise { const { jsonObject: bulkSuppressionsConfigJson } = getSuppressionsConfigForEslintrcFolderPath( process.cwd().replace(/\\/g, '/') ); @@ -35,5 +35,28 @@ function getAllFilesWithExistingSuppressionsForCwd(): string[] { allFiles.add(filePath); } - return Array.from(allFiles); + const allFilesArray: string[] = Array.from(allFiles); + + const allExistingFiles: string[] = []; + // TODO: limit parallelism here with something similar to `Async.forEachAsync` from `node-core-library`. + await Promise.all( + allFilesArray.map(async (filePath: string) => { + try { + await fs.promises.access(filePath, fs.constants.F_OK); + allExistingFiles.push(filePath); + } catch { + // Doesn't exist - ignore + } + }) + ); + + console.log(`Found ${allExistingFiles.length} files with existing suppressions.`); + const deletedCount: number = allFilesArray.length - allExistingFiles.length; + if (deletedCount > 0) { + console.log(`${deletedCount} files with suppressions were deleted.`); + } + + console.log(`Pruning suppressions for ${allExistingFiles.length} files...`); + + return allExistingFiles; }