From a3c0314d3cc00c9fd84cae63085316ecd2ddca63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Chalk?= Date: Mon, 17 Jun 2024 17:05:10 +0200 Subject: [PATCH] fix: wrap paths in quotes in case of spaces --- packages/plugin-coverage/src/lib/runner/index.ts | 3 ++- .../src/lib/runner/runner.integration.test.ts | 2 +- .../eslint-plugin.integration.test.ts.snap | 2 +- packages/plugin-eslint/src/lib/runner/index.ts | 3 ++- packages/plugin-eslint/src/lib/runner/lint.ts | 9 +++++++-- .../src/lib/runner/lint.unit.test.ts | 2 +- .../plugin-js-packages/src/lib/runner/index.ts | 3 ++- .../src/lib/runner/runner.integration.test.ts | 2 +- packages/utils/src/index.ts | 15 ++++++++------- packages/utils/src/lib/file-system.ts | 5 +++++ packages/utils/src/lib/file-system.unit.test.ts | 9 +++++++++ 11 files changed, 39 insertions(+), 16 deletions(-) diff --git a/packages/plugin-coverage/src/lib/runner/index.ts b/packages/plugin-coverage/src/lib/runner/index.ts index a88874d56..26fa0824f 100644 --- a/packages/plugin-coverage/src/lib/runner/index.ts +++ b/packages/plugin-coverage/src/lib/runner/index.ts @@ -6,6 +6,7 @@ import { ProcessError, ensureDirectoryExists, executeProcess, + filePathToCliArg, readJsonFile, ui, } from '@code-pushup/utils'; @@ -60,7 +61,7 @@ export async function createRunnerConfig( return { command: 'node', - args: [scriptPath], + args: [filePathToCliArg(scriptPath)], outputFile: RUNNER_OUTPUT_PATH, ...(threshold != null && { outputTransform: outputs => diff --git a/packages/plugin-coverage/src/lib/runner/runner.integration.test.ts b/packages/plugin-coverage/src/lib/runner/runner.integration.test.ts index 22e02f5c1..80f4dc837 100644 --- a/packages/plugin-coverage/src/lib/runner/runner.integration.test.ts +++ b/packages/plugin-coverage/src/lib/runner/runner.integration.test.ts @@ -17,7 +17,7 @@ describe('createRunnerConfig', () => { }); expect(runnerConfig).toStrictEqual({ command: 'node', - args: ['executeRunner.ts'], + args: ['"executeRunner.ts"'], outputTransform: expect.any(Function), outputFile: expect.stringContaining('runner-output.json'), }); diff --git a/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.integration.test.ts.snap b/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.integration.test.ts.snap index 027b5dd21..bb19bcc6d 100644 --- a/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.integration.test.ts.snap +++ b/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.integration.test.ts.snap @@ -508,7 +508,7 @@ exports[`eslintPlugin > should initialize ESLint plugin for React application 1` "packageName": "@code-pushup/eslint-plugin", "runner": { "args": [ - "/bin.js", + ""/bin.js"", ], "command": "node", "outputFile": "node_modules/.code-pushup/eslint/runner-output.json", diff --git a/packages/plugin-eslint/src/lib/runner/index.ts b/packages/plugin-eslint/src/lib/runner/index.ts index 4de4275a1..b605333f2 100644 --- a/packages/plugin-eslint/src/lib/runner/index.ts +++ b/packages/plugin-eslint/src/lib/runner/index.ts @@ -3,6 +3,7 @@ import { dirname, join } from 'node:path'; import type { Audit, AuditOutput, RunnerConfig } from '@code-pushup/models'; import { ensureDirectoryExists, + filePathToCliArg, pluginWorkDir, readJsonFile, } from '@code-pushup/utils'; @@ -60,7 +61,7 @@ export async function createRunnerConfig( return { command: 'node', - args: [scriptPath], + args: [filePathToCliArg(scriptPath)], outputFile: RUNNER_OUTPUT_PATH, }; } diff --git a/packages/plugin-eslint/src/lib/runner/lint.ts b/packages/plugin-eslint/src/lib/runner/lint.ts index 95960a743..1b1045883 100644 --- a/packages/plugin-eslint/src/lib/runner/lint.ts +++ b/packages/plugin-eslint/src/lib/runner/lint.ts @@ -2,7 +2,12 @@ import type { ESLint, Linter } from 'eslint'; import { rm, writeFile } from 'node:fs/promises'; import { platform } from 'node:os'; import { join } from 'node:path'; -import { distinct, executeProcess, toArray } from '@code-pushup/utils'; +import { + distinct, + executeProcess, + filePathToCliArg, + toArray, +} from '@code-pushup/utils'; import type { ESLintTarget } from '../config'; import { setupESLint } from '../setup'; import type { LinterOutput, RuleOptionsPerFile } from './types'; @@ -26,7 +31,7 @@ function executeLint({ command: 'npx', args: [ 'eslint', - ...(configPath ? [`--config=${configPath}`] : []), + ...(configPath ? [`--config=${filePathToCliArg(configPath)}`] : []), ...(typeof eslintrc === 'object' ? ['--no-eslintrc'] : []), '--no-error-on-unmatched-pattern', '--format=json', diff --git a/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts b/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts index 6ef803c80..2e2a43d6d 100644 --- a/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts @@ -106,7 +106,7 @@ describe('lint', () => { command: 'npx', args: [ 'eslint', - '--config=.eslintrc.js', + '--config=".eslintrc.js"', '--no-error-on-unmatched-pattern', '--format=json', expect.stringContaining('**/*.js'), // wraps in quotes on Unix diff --git a/packages/plugin-js-packages/src/lib/runner/index.ts b/packages/plugin-js-packages/src/lib/runner/index.ts index ff5ae7bac..5383dc6d1 100644 --- a/packages/plugin-js-packages/src/lib/runner/index.ts +++ b/packages/plugin-js-packages/src/lib/runner/index.ts @@ -4,6 +4,7 @@ import type { RunnerConfig } from '@code-pushup/models'; import { ensureDirectoryExists, executeProcess, + filePathToCliArg, isPromiseFulfilledResult, isPromiseRejectedResult, objectFromEntries, @@ -34,7 +35,7 @@ export async function createRunnerConfig( return { command: 'node', - args: [scriptPath], + args: [filePathToCliArg(scriptPath)], outputFile: RUNNER_OUTPUT_PATH, }; } diff --git a/packages/plugin-js-packages/src/lib/runner/runner.integration.test.ts b/packages/plugin-js-packages/src/lib/runner/runner.integration.test.ts index b21f3b5c1..e4d69bcfe 100644 --- a/packages/plugin-js-packages/src/lib/runner/runner.integration.test.ts +++ b/packages/plugin-js-packages/src/lib/runner/runner.integration.test.ts @@ -17,7 +17,7 @@ describe('createRunnerConfig', () => { }); expect(runnerConfig).toStrictEqual({ command: 'node', - args: ['executeRunner.ts'], + args: ['"executeRunner.ts"'], outputFile: expect.stringContaining('runner-output.json'), }); }); diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 48646def8..d8e73f266 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,5 +1,3 @@ -export * from './lib/text-formats'; -export { ExcludeNullFromPropertyTypes } from './lib/types'; export { exists } from '@code-pushup/models'; export { Diff, comparePairs, matchArrayItemsByKey } from './lib/diff'; export { @@ -17,6 +15,7 @@ export { directoryExists, ensureDirectoryExists, fileExists, + filePathToCliArg, findLineNumberInText, importEsmModule, logMultipleFileResults, @@ -39,18 +38,18 @@ export { } from './lib/formatting'; export { formatGitPath, - guardAgainstLocalChanges, getGitRoot, + guardAgainstLocalChanges, safeCheckout, toGitPath, } from './lib/git/git'; export { - getSemverTags, LogResult, - getHashes, - getHashFromTag, getCurrentBranchOrTag, + getHashFromTag, + getHashes, getLatestCommit, + getSemverTags, } from './lib/git/git.commits-and-tags'; export { groupByStatus } from './lib/group-by-status'; export { @@ -85,6 +84,8 @@ export { compareIssueSeverity, loadReport, } from './lib/reports/utils'; +export { isSemver, normalizeSemver, sortSemvers } from './lib/semver'; +export * from './lib/text-formats'; export { CliArgsObject, apostrophize, @@ -104,5 +105,5 @@ export { toUnixNewlines, toUnixPath, } from './lib/transform'; +export { ExcludeNullFromPropertyTypes } from './lib/types'; export { verboseUtils } from './lib/verbose-utils'; -export { isSemver, normalizeSemver, sortSemvers } from './lib/semver'; diff --git a/packages/utils/src/lib/file-system.ts b/packages/utils/src/lib/file-system.ts index e7c05aba6..5f72a6e17 100644 --- a/packages/utils/src/lib/file-system.ts +++ b/packages/utils/src/lib/file-system.ts @@ -139,3 +139,8 @@ export function findLineNumberInText( const lineNumber = lines.findIndex(line => line.includes(pattern)) + 1; // +1 because line numbers are 1-based return lineNumber === 0 ? null : lineNumber; // If the package isn't found, return null } + +export function filePathToCliArg(path: string): string { + // needs to be escaped if spaces included + return `"${path}"`; +} diff --git a/packages/utils/src/lib/file-system.unit.test.ts b/packages/utils/src/lib/file-system.unit.test.ts index 763ed1fb0..40dce6f7a 100644 --- a/packages/utils/src/lib/file-system.unit.test.ts +++ b/packages/utils/src/lib/file-system.unit.test.ts @@ -7,6 +7,7 @@ import { FileResult, crawlFileSystem, ensureDirectoryExists, + filePathToCliArg, findLineNumberInText, logMultipleFileResults, } from './file-system'; @@ -139,3 +140,11 @@ describe('findLineNumberInText', () => { expect(findLineNumberInText(``, 'x')).toBeNull(); }); }); + +describe('filePathToCliArg', () => { + it('should wrap path in quotes', () => { + expect(filePathToCliArg('My Project/index.js')).toBe( + '"My Project/index.js"', + ); + }); +});