Skip to content

Commit

Permalink
fix: correctly split the argv string (#7533)
Browse files Browse the repository at this point in the history
  • Loading branch information
btea authored Feb 27, 2025
1 parent 7f7ff11 commit 4325ac6
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
28 changes: 27 additions & 1 deletion packages/vitest/src/node/cli/cac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function addCommand(cli: CAC | Command, name: string, option: CLIOption<any>) {
`Expected a single value for option "${command}", received [${received}]`,
)
}
value = removeQuotes(value)
if (option.transform) {
return option.transform(value)
}
Expand Down Expand Up @@ -196,11 +197,36 @@ export function createCLI(options: CliParseOptions = {}): CAC {
return cli
}

function removeQuotes<T>(str: T): T {
if (typeof str !== 'string') {
if (Array.isArray(str)) {
return str.map(removeQuotes) as unknown as T
}
return str
}
if (str.startsWith('"') && str.endsWith('"')) {
return str.slice(1, -1) as unknown as T
}
if (str.startsWith(`'`) && str.endsWith(`'`)) {
return str.slice(1, -1) as unknown as T
}
return str
}

function splitArgv(argv: string): string[] {
const reg = /(['"])(?:(?!\1).)+\1/g
argv = argv.replace(reg, match => match.replace(/\s/g, '\x00'))
return argv.split(' ').map((arg: string) => {
arg = arg.replace(/\0/g, ' ')
return removeQuotes(arg)
})
}

export function parseCLI(argv: string | string[], config: CliParseOptions = {}): {
filter: string[]
options: CliOptions
} {
const arrayArgs = typeof argv === 'string' ? argv.split(' ') : argv
const arrayArgs = typeof argv === 'string' ? splitArgv(argv) : argv
if (arrayArgs[0] !== 'vitest') {
throw new Error(`Expected "vitest" as the first argument, received "${arrayArgs[0]}"`)
}
Expand Down
45 changes: 45 additions & 0 deletions test/core/test/cli-test.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,51 @@ test('public parseCLI works correctly', () => {
},
})

expect(parseCLI('vitest --project="space 1"')).toEqual({
filter: [],
options: {
'project': ['space 1'],
'--': [],
'color': true,
},
})

expect(parseCLI('vitest "--project=space 1"')).toEqual({
filter: [],
options: {
'project': ['space 1'],
'--': [],
'color': true,
},
})

expect(parseCLI('vitest --project "space 1"')).toEqual({
filter: [],
options: {
'project': ['space 1'],
'--': [],
'color': true,
},
})

expect(parseCLI('vitest --project="space 1" --project="space 2"')).toEqual({
filter: [],
options: {
'project': ['space 1', 'space 2'],
'--': [],
'color': true,
},
})

expect(parseCLI('vitest ./test-1.js ./test-2.js --project="space 1" --project="space 2" --project="space 3"')).toEqual({
filter: ['./test-1.js', './test-2.js'],
options: {
'project': ['space 1', 'space 2', 'space 3'],
'--': [],
'color': true,
},
})

expect(parseCLI('vitest --exclude=docs --exclude=demo')).toEqual({
filter: [],
options: {
Expand Down

0 comments on commit 4325ac6

Please sign in to comment.