fix: keep dotdot-prefixed paths in quick open

This commit is contained in:
Neil
2026-05-30 04:51:43 -07:00
parent fa76bd02d0
commit c84bbe9df3
2 changed files with 24 additions and 2 deletions
+17
View File
@@ -75,6 +75,12 @@ describe('buildExcludePathPrefixes', () => {
it('strips trailing slashes', () => {
expect(buildExcludePathPrefixes('/r', ['/r/a/', '/r/b///'])).toEqual(['a', 'b'])
})
it('keeps valid child prefixes whose segment starts with dotdot characters', () => {
expect(buildExcludePathPrefixes('/home/u/repo', ['/home/u/repo/..fixtures'])).toEqual([
'..fixtures'
])
})
})
describe('shouldExcludeQuickOpenRelPath', () => {
@@ -179,6 +185,12 @@ describe('normalizeQuickOpenRgLine', () => {
expect(normalizeQuickOpenRgLine('./src/a.ts', { kind: 'cwd-relative' })).toBe('src/a.ts')
})
it('keeps cwd-relative files under dotdot-prefixed child directories', () => {
expect(normalizeQuickOpenRgLine('./..fixtures/a.ts', { kind: 'cwd-relative' })).toBe(
'..fixtures/a.ts'
)
})
it('strips CRLF', () => {
expect(normalizeQuickOpenRgLine('/root/a.ts\r', { kind: 'absolute', rootPath: '/root' })).toBe(
'a.ts'
@@ -195,6 +207,11 @@ describe('normalizeQuickOpenRgLine', () => {
expect(normalizeQuickOpenRgLine('', { kind: 'cwd-relative' })).toBeNull()
expect(normalizeQuickOpenRgLine('.', { kind: 'cwd-relative' })).toBeNull()
})
it('returns null for cwd-relative parent-directory escapes', () => {
expect(normalizeQuickOpenRgLine('../outside/a.ts', { kind: 'cwd-relative' })).toBeNull()
expect(normalizeQuickOpenRgLine('./../outside/a.ts', { kind: 'cwd-relative' })).toBeNull()
})
})
describe('buildGitLsFilesArgsForQuickOpen', () => {
+7 -2
View File
@@ -132,7 +132,7 @@ export function buildExcludePathPrefixes(rootPath: string, excludePaths?: unknow
: // Fall back to path-flavor relative so we do not accidentally use the
// local OS's semantics on remote paths.
flavor.relative(trimmedRoot, raw).replace(/\\/g, '/')
if (!rel || rel.startsWith('..') || rel.startsWith('/')) {
if (!rel || isParentRelativePath(rel) || rel.startsWith('/')) {
continue
}
// Strip any trailing slash so boundary checks are unambiguous.
@@ -189,6 +189,11 @@ function escapeGlobPath(relPath: string): string {
return relPath.split('/').map(escapeGlob).join('/')
}
function isParentRelativePath(relPath: string): boolean {
// Why: `..name` is a valid child path; only `..` and `../...` escape.
return relPath === '..' || relPath.startsWith('../')
}
// ─── rg traversal-pruning globs ──────────────────────────────────────
/**
@@ -305,7 +310,7 @@ export function normalizeQuickOpenRgLine(rawLine: string, outputMode: RgOutputMo
} else if (rel === '.') {
return null
}
if (!rel || rel.startsWith('/') || rel.startsWith('..')) {
if (!rel || rel.startsWith('/') || isParentRelativePath(rel)) {
return null
}
return rel