@@ -8,17 +8,21 @@ import { fileURLToPath } from "url";
88/**
99 * Converts a root URI to a normalized directory path with basic security validation.
1010 * @param rootUri - File URI (file://...) or plain directory path
11- * @returns Promise resolving to validated path or null if invalid
11+ * @returns Promise resolving to original and resolved paths, or null if invalid
1212 */
13- async function parseRootUri ( rootUri : string ) : Promise < string | null > {
13+ async function parseRootUri ( rootUri : string ) : Promise < string [ ] | null > {
1414 try {
1515 const rawPath = rootUri . startsWith ( 'file://' ) ? fileURLToPath ( rootUri ) : rootUri ;
1616 const expandedPath = rawPath . startsWith ( '~/' ) || rawPath === '~'
1717 ? path . join ( os . homedir ( ) , rawPath . slice ( 1 ) )
1818 : rawPath ;
1919 const absolutePath = path . resolve ( expandedPath ) ;
20+ const normalizedOriginal = normalizePath ( absolutePath ) ;
2021 const resolvedPath = await fs . realpath ( absolutePath ) ;
21- return normalizePath ( resolvedPath ) ;
22+ const normalizedResolved = normalizePath ( resolvedPath ) ;
23+ return normalizedOriginal === normalizedResolved
24+ ? [ normalizedResolved ]
25+ : [ normalizedOriginal , normalizedResolved ] ;
2226 } catch {
2327 return null ; // Path doesn't exist or other error
2428 }
@@ -53,25 +57,33 @@ export async function getValidRootDirectories(
5357 requestedRoots : readonly Root [ ]
5458) : Promise < string [ ] > {
5559 const validatedDirectories : string [ ] = [ ] ;
60+ const seenDirectories = new Set < string > ( ) ;
5661
5762 for ( const requestedRoot of requestedRoots ) {
58- const resolvedPath = await parseRootUri ( requestedRoot . uri ) ;
59- if ( ! resolvedPath ) {
63+ const rootPaths = await parseRootUri ( requestedRoot . uri ) ;
64+ if ( ! rootPaths ) {
6065 console . error ( formatDirectoryError ( requestedRoot . uri , undefined , 'invalid path or inaccessible' ) ) ;
6166 continue ;
6267 }
6368
64- try {
65- const stats : Stats = await fs . stat ( resolvedPath ) ;
66- if ( stats . isDirectory ( ) ) {
67- validatedDirectories . push ( resolvedPath ) ;
68- } else {
69- console . error ( formatDirectoryError ( resolvedPath , undefined , 'non-directory root' ) ) ;
69+ for ( const rootPath of rootPaths ) {
70+ if ( seenDirectories . has ( rootPath ) ) {
71+ continue ;
72+ }
73+
74+ try {
75+ const stats : Stats = await fs . stat ( rootPath ) ;
76+ if ( stats . isDirectory ( ) ) {
77+ validatedDirectories . push ( rootPath ) ;
78+ seenDirectories . add ( rootPath ) ;
79+ } else {
80+ console . error ( formatDirectoryError ( rootPath , undefined , 'non-directory root' ) ) ;
81+ }
82+ } catch ( error ) {
83+ console . error ( formatDirectoryError ( rootPath , error ) ) ;
7084 }
71- } catch ( error ) {
72- console . error ( formatDirectoryError ( resolvedPath , error ) ) ;
7385 }
7486 }
7587
7688 return validatedDirectories ;
77- }
89+ }
0 commit comments