Skip to content

Commit 3c84012

Browse files
authored
Fix HOME folder substitution when is not in the beginning of path (#19326)
1 parent ed6f4eb commit 3c84012

2 files changed

Lines changed: 74 additions & 7 deletions

File tree

src/client/common/process/logger.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,31 @@ export class ProcessLogger implements IProcessLogger {
5353
function replaceMatchesWithCharacter(original: string, match: string, character: string): string {
5454
// Backslashes, plus signs, brackets and other characters have special meaning in regexes,
5555
// we need to escape using an extra backlash so it's not considered special.
56-
let pattern = escapeRegExp(match);
57-
if (getOSType() === OSType.Windows) {
58-
// Match both forward and backward slash versions of 'match' for Windows.
59-
pattern = pattern.replaceAll('\\\\', '(\\\\|/)');
56+
function getRegex(match: string) {
57+
let pattern = escapeRegExp(match);
58+
if (getOSType() === OSType.Windows) {
59+
// Match both forward and backward slash versions of 'match' for Windows.
60+
pattern = pattern.replaceAll('\\\\', '(\\\\|/)');
61+
}
62+
let regex = new RegExp(pattern, 'ig');
63+
return regex;
64+
}
65+
66+
function isPrevioustoMatchRegexALetter(chunk: string, index: number) {
67+
return chunk[index].match(/[a-z]/);
68+
}
69+
70+
let chunked = original.split(' ');
71+
72+
for (let i = 0; i < chunked.length; i++) {
73+
let regex = getRegex(match);
74+
const regexResult = regex.exec(chunked[i]);
75+
if (regexResult) {
76+
const regexIndex = regexResult.index;
77+
if (regexIndex > 0 && isPrevioustoMatchRegexALetter(chunked[i], regexIndex - 1))
78+
regex = getRegex(match.substring(1));
79+
chunked[i] = chunked[i].replace(regex, character);
80+
}
6081
}
61-
let regex = new RegExp(pattern, 'ig');
62-
return original.replace(regex, character);
82+
return chunked.join(' ');
6383
}

src/test/common/process/logger.unit.test.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,61 @@ suite('ProcessLogger suite', () => {
9999
);
100100
});
101101

102-
test('Logger replaces the path/to/home with ~ in the command path', async () => {
102+
test('Logger replaces the path/to/home with ~ in the command path where the home path IS at the beginning of the path', async () => {
103103
const options = { cwd: path.join('debug', 'path') };
104104
logger.logProcess(path.join(untildify('~'), 'test'), ['--foo', '--bar'], options);
105105

106106
sinon.assert.calledWithExactly(traceLogStub, `> ${path.join('~', 'test')} --foo --bar`);
107107
sinon.assert.calledWithExactly(traceLogStub, `${Logging.currentWorkingDirectory} ${options.cwd}`);
108108
});
109109

110+
test('Logger replaces the path/to/home with ~ in the command path where the home path IS at the beginning of the path but another arg contains other ref to home folder', async () => {
111+
const options = { cwd: path.join('debug', 'path') };
112+
logger.logProcess(path.join(untildify('~'), 'test'), ['--foo', path.join(untildify('~'), 'boo')], options);
113+
114+
sinon.assert.calledWithExactly(traceLogStub, `> ${path.join('~', 'test')} --foo ${path.join('~', 'boo')}`);
115+
sinon.assert.calledWithExactly(traceLogStub, `${Logging.currentWorkingDirectory} ${options.cwd}`);
116+
});
117+
118+
test('Logger replaces the path/to/home with ~ in the command path where the home path IS at the beginning of the path between doble quotes', async () => {
119+
const options = { cwd: path.join('debug', 'path') };
120+
logger.logProcess(`"${path.join(untildify('~'), 'test')}" "--foo" "--bar"`, undefined, options);
121+
122+
sinon.assert.calledWithExactly(traceLogStub, `> "${path.join('~', 'test')}" "--foo" "--bar"`);
123+
sinon.assert.calledWithExactly(traceLogStub, `${Logging.currentWorkingDirectory} ${options.cwd}`);
124+
});
125+
126+
test('Logger replaces the path/to/home with ~ in the command path where the home path IS NOT at the beginning of the path', async () => {
127+
const options = { cwd: path.join('debug', 'path') };
128+
logger.logProcess(path.join('net', untildify('~'), 'test'), ['--foo', '--bar'], options);
129+
130+
sinon.assert.calledWithExactly(traceLogStub, `> ${path.join('net', '~', 'test')} --foo --bar`);
131+
sinon.assert.calledWithExactly(traceLogStub, `${Logging.currentWorkingDirectory} ${options.cwd}`);
132+
});
133+
134+
test('Logger replaces the path/to/home with ~ in the command path where the home path IS NOT at the beginning of the path but another arg contains other ref to home folder', async () => {
135+
const options = { cwd: path.join('debug', 'path') };
136+
logger.logProcess(
137+
path.join('net', untildify('~'), 'test'),
138+
['--foo', path.join(untildify('~'), 'boo')],
139+
options,
140+
);
141+
142+
sinon.assert.calledWithExactly(
143+
traceLogStub,
144+
`> ${path.join('net', '~', 'test')} --foo ${path.join('~', 'boo')}`,
145+
);
146+
sinon.assert.calledWithExactly(traceLogStub, `${Logging.currentWorkingDirectory} ${options.cwd}`);
147+
});
148+
149+
test('Logger replaces the path/to/home with ~ in the command path where the home path IS NOT at the beginning of the path between doble quotes', async () => {
150+
const options = { cwd: path.join('debug', 'path') };
151+
logger.logProcess(`"${path.join('net', untildify('~'), 'test')}" "--foo" "--bar"`, undefined, options);
152+
153+
sinon.assert.calledWithExactly(traceLogStub, `> "${path.join('net', '~', 'test')}" "--foo" "--bar"`);
154+
sinon.assert.calledWithExactly(traceLogStub, `${Logging.currentWorkingDirectory} ${options.cwd}`);
155+
});
156+
110157
test('Logger replaces the path/to/home with ~ if shell command is provided', async () => {
111158
const options = { cwd: path.join('debug', 'path') };
112159
logger.logProcess(`"${path.join(untildify('~'), 'test')}" "--foo" "--bar"`, undefined, options);

0 commit comments

Comments
 (0)