Follow symlinked dirs in recursive file mode#1639
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates FilenameOptions file enumeration to follow symlinked directories during recursive traversal (to support ko apply --recursive -f ... use cases), while ensuring non-recursive traversal does not descend into nested symlinked directories.
Changes:
- Replaced
filepath.Walk-based enumeration with a custom recursive enumerator that can treat symlinked directories as directories. - Added cycle prevention for directory traversal via a
visitedset of resolved absolute paths. - Added unit tests covering recursive symlinked directory traversal and non-recursive behavior with nested symlinked directories.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| pkg/commands/options/filestuff.go | Implements custom traversal to follow symlinked directories (recursive) while skipping nested directories (non-recursive) and avoiding cycles. |
| pkg/commands/options/filestuff_test.go | Adds unit coverage for symlinked directory roots / nested symlinked directories behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if err != nil { | ||
| // Preserve the old behavior for file-like symlinks: if the entry was | ||
| // passed explicitly, stream it and let later file handling report errors. | ||
| if filename == root { | ||
| files <- filename | ||
| } | ||
| return nil | ||
| } | ||
| isDir = targetInfo.IsDir() |
There was a problem hiding this comment.
When encountering a symlink, an os.Stat failure causes the entry to be silently ignored unless it was explicitly passed as root. This changes previous behavior for symlinked files discovered during directory traversal (e.g., a broken *.yaml symlink would previously be enumerated and then fail later during os.ReadFile), and can result in missing manifests with no error. Consider treating os.Stat errors as “not a directory” (continue through the normal extension filter / emission path) or returning the error so the user gets a clear failure instead of silently skipping the entry.
| if err != nil { | |
| // Preserve the old behavior for file-like symlinks: if the entry was | |
| // passed explicitly, stream it and let later file handling report errors. | |
| if filename == root { | |
| files <- filename | |
| } | |
| return nil | |
| } | |
| isDir = targetInfo.IsDir() | |
| if err == nil { | |
| isDir = targetInfo.IsDir() | |
| } |
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
5c5fefd to
37946b9
Compare
Summary
Fixes #460
Validation
go test ./pkg/commands/options -run 'TestEnumerateFiles.*Symlinked' -count=1go test ./pkg/commands/options -count=1go test ./pkg/commands/... -count=1go vet ./pkg/commands/...git diff --check