Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"theme": "light"
},
"engines": {
"vscode": "^1.104.0"
"vscode": "^1.102.0"
},
"l10n": "./l10n",
"extensionKind": [
Expand Down
41 changes: 41 additions & 0 deletions src/platform/common/extensions.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,45 @@ suite('String Extensions', () => {
expect(trimQuotes(quotedString3)).to.be.equal(expectedString);
expect(trimQuotes(quotedString4)).to.be.equal(expectedString);
});

// Tests for Windows paths with special characters (issue #16932)
test('Should quote Windows paths with spaces in username', () => {
const pathToTest = 'C:\\Users\\John Smith\\AppData\\Local\\env\\python.exe';
expect(toCommandArgument(pathToTest)).to.be.equal(`"${pathToTest}"`);
});
test('Should quote Windows paths with parentheses in username', () => {
const pathToTest = 'C:\\Users\\John(Contractor)\\AppData\\Local\\env\\python.exe';
expect(toCommandArgument(pathToTest)).to.be.equal(`"${pathToTest}"`);
});
test('Should quote Windows paths with both spaces and parentheses', () => {
const pathToTest = 'C:\\Users\\John Smith (Contractor)\\AppData\\Local\\env\\python.exe';
expect(toCommandArgument(pathToTest)).to.be.equal(`"${pathToTest}"`);
});
test('Should quote file paths with special characters and normalize slashes', () => {
const pathToTest = 'C:\\Users\\John(Contractor)\\AppData\\Local\\env\\python.exe';
const expectedPath = 'C:/Users/John(Contractor)/AppData/Local/env/python.exe';
expect(fileToCommandArgument(pathToTest)).to.be.equal(`"${expectedPath}"`);
});
test('Should handle already quoted paths correctly', () => {
const pathToTest = '"C:\\Users\\John(Contractor)\\AppData\\Local\\env\\python.exe"';
// toCommandArgument should not double-quote if already quoted
expect(toCommandArgument(pathToTest)).to.be.equal(pathToTest);
});
test('Should quote paths with other shell metacharacters', () => {
const pathWithAmpersand = 'C:\\Users\\John&Jane\\python.exe';
const pathWithPipe = 'C:\\Users\\John|Jane\\python.exe';
const pathWithLessThan = 'C:\\Users\\John<Jane\\python.exe';
const pathWithGreaterThan = 'C:\\Users\\John>Jane\\python.exe';
const pathWithCaret = 'C:\\Users\\John^Jane\\python.exe';

expect(toCommandArgument(pathWithAmpersand)).to.be.equal(`"${pathWithAmpersand}"`);
expect(toCommandArgument(pathWithPipe)).to.be.equal(`"${pathWithPipe}"`);
expect(toCommandArgument(pathWithLessThan)).to.be.equal(`"${pathWithLessThan}"`);
expect(toCommandArgument(pathWithGreaterThan)).to.be.equal(`"${pathWithGreaterThan}"`);
expect(toCommandArgument(pathWithCaret)).to.be.equal(`"${pathWithCaret}"`);
});
test('Should not quote paths without special characters', () => {
const normalPath = 'C:\\Users\\JohnSmith\\AppData\\Local\\env\\python.exe';
expect(toCommandArgument(normalPath)).to.be.equal(normalPath);
});
});
9 changes: 6 additions & 3 deletions src/platform/common/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@ export function splitLines(

/**
* Appropriately formats a string so it can be used as an argument for a command in a shell.
* E.g. if an argument contains a space, then it will be enclosed within double quotes.
* E.g. if an argument contains a space or special characters, then it will be enclosed within double quotes.
* @param {String} value.
*/
export function toCommandArgument(value: string): string {
if (!value) {
return value;
}
return value.indexOf(' ') >= 0 && !value.startsWith('"') && !value.endsWith('"') ? `"${value}"` : value.toString();
// Check for special characters that require quoting in shell commands
// This includes spaces, parentheses, and other shell metacharacters
const needsQuoting = /[\s()&|<>^]/.test(value);
return needsQuoting && !value.startsWith('"') && !value.endsWith('"') ? `"${value}"` : value.toString();
}

/**
* Appropriately formats a a file path so it can be used as an argument for a command in a shell.
* E.g. if an argument contains a space, then it will be enclosed within double quotes.
* E.g. if an argument contains a space or special characters, then it will be enclosed within double quotes.
*/
export function fileToCommandArgument(value: string): string {
if (!value) {
Expand Down
Loading