@@ -148,10 +148,28 @@ function walkFilesRecursive(
148148 excludeDirs : ReadonlySet < string > = new Set ( ) ,
149149) : string [ ] {
150150 const results : string [ ] = [ ] ;
151+
152+ // Exclude directories by *physical identity*, not by path string: the same
153+ // directory might be reachable under multiple names when a symlink aliases
154+ // one of its ancestors. This case can occur, e.g., when mounting a multi-repo
155+ // workspace, whose `/.tuor` folder is a symlink to some
156+ // `/tuor-config-repo/.tuor` that's also part of the workspace.
157+ //
158+ // Resolving to the canonical path lets us skip the excluded dir no matter
159+ // which alias the walk arrives through. Excluded dirs that don't resolve
160+ // simply can't be hit, so drop them.
161+ const excludeReal = new Set < string > ( ) ;
162+ for ( const d of excludeDirs ) {
163+ try {
164+ excludeReal . add ( realpathSync ( d ) ) ;
165+ } catch {
166+ // not present on disk → unreachable by the walk
167+ }
168+ }
169+
151170 const walk = ( dir : string ) => {
152171 for ( const entry of readdirSync ( dir , { withFileTypes : true } ) ) {
153172 const full = join ( dir , entry . name ) ;
154- if ( excludeDirs . has ( full ) ) continue ;
155173 if ( entry . isSymbolicLink ( ) ) {
156174 // statSync follows the link to its target. A dangling symlink (target
157175 // missing) throws ENOENT, so guard against it and skip rather than
@@ -164,6 +182,7 @@ function walkFilesRecursive(
164182 }
165183 if ( ! isDir ) continue ;
166184 const real = realpathSync ( full ) ;
185+ if ( excludeReal . has ( real ) ) continue ;
167186 if ( dir . startsWith ( real + "/" ) || dir === real ) {
168187 throw new Error (
169188 `Symlink cycle detected while scanning for ${ filename } : ` +
@@ -173,6 +192,13 @@ function walkFilesRecursive(
173192 }
174193 walk ( full ) ;
175194 } else if ( entry . isDirectory ( ) ) {
195+ let real : string ;
196+ try {
197+ real = realpathSync ( full ) ;
198+ } catch {
199+ continue ;
200+ }
201+ if ( excludeReal . has ( real ) ) continue ;
176202 walk ( full ) ;
177203 } else if ( entry . name === filename ) {
178204 results . push ( full ) ;
0 commit comments