Fix import* and read* skipping symlinked files#1522
Fix import* and read* skipping symlinked files#1522nkakouros wants to merge 1 commit intoapple:mainfrom
Conversation
FileResolver.listElements() unconditionally skipped all symlinks to prevent cyclical globs from directory symlinks. As a side effect, import*() and read*() silently dropped symlinks to regular files from their results, returning partial output with no warning. Narrow the skip to symlinks whose target is a directory. Symlinks to regular files are now surfaced as ordinary entries; broken symlinks also surface and produce a clear load-time error rather than silent omission.
67f4939 to
fcb8ea3
Compare
bioball
left a comment
There was a problem hiding this comment.
This is more of a behavior change than a fix.
In the past, we've chatted about just allowing symlinks, and bubbling up cycles as errors. Either way, I think just allowing symlinking files but not directories is surprising behavior. Either, it should follow symlinks, or not.
Fair. To support directory symlinks, is there a preferred approach? I am thinking of using a Set of traversed paths through the recursion in |
|
Tested what happens when you have circular symlinks and try to resolve the real path (I added this as a junit test): @Test
fun `test circular link`(@TempDir tempDir: Path) {
val linkOne = tempDir.resolve("a.lnk")
val linkTwo = tempDir.resolve("b.lnk")
Files.createSymbolicLink(linkOne, linkTwo)
Files.createSymbolicLink(linkTwo, linkOne)
linkOne.toRealPath()
}I got this thrown error: I think we should be able to handle the circular symlink stuff by calling |
f5cf70d to
fcb8ea3
Compare
|
Superseded by #1562 . |
Problem
import*()andread*()glob expansion silently omits symlinked files from results. Regular files matching the same pattern in the same directory are returned, so the partial result is easy to miss. There's also no warning that the glob returned only some matches.Reproduction
Cause
FileResolver.listElements()skipped every directory entry that was a symbolic link, with the comment "skip symlinks to prevent cyclical globs". The intent, preventing cycles caused by directory symlinks, was good, but the check was too broad and also excluded symlinks to regular files that don't cause cyclical globs.Fix
Narrow the skip to symlinks whose target is a directory. Symlinks to regular files are now surfaced as ordinary
PathElemententries. Broken symlinks are also surfaced; their failure now shows up as a clear load-time error rather than a silent omission.read*()shares the sameFileResolver.listElements()code path asimport*(), so the same change fixes both.Tests
New unit test
FileResolverTestcovering: symlink to a regular file (the bug), symlink to a directory (stillskipped, invariant preserved), and broken symlink (now surfaced).
New language snippet test
importGlobSymlink.pklexercising the fix end-to-end throughimport*(). Fixture lives in a newinput-helper/globtest-symlink/directory so existing snippet tests are untouched.Future work
Following directory symlinks (with real-path cycle tracking) is intentionally out of scope for this PR. This is the minimal change to stop the silent-drop bug; full shell-glob-style symlink following can be a follow-up.