feat: override Cwd::abs_path to resolve mocked symlinks (#139)#211
Draft
Koan-Bot wants to merge 1 commit intocpanel:masterfrom
Draft
feat: override Cwd::abs_path to resolve mocked symlinks (#139)#211Koan-Bot wants to merge 1 commit intocpanel:masterfrom
Koan-Bot wants to merge 1 commit intocpanel:masterfrom
Conversation
Koan-Bot
added a commit
to atoomic/Test-MockFile
that referenced
this pull request
Feb 24, 2026
IO::File::open() uses CORE::open internally, which bypasses CORE::GLOBAL::open and makes IO::File->new() ignore mocked files. Fix: replace IO::File::open with a wrapper that checks if the target file is mocked. If mocked, tie the existing IO::File glob directly (avoiding the need to create a new handle). If not mocked, fall through to the original IO::File::open via goto. This follows the same pattern as the Cwd::abs_path override (PR cpanel#211) — intercept at the namespace level when C/XS code bypasses CORE::GLOBAL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
Author
Rebase: feat: override Cwd::abs_path to resolve mocked symlinks (#139)Branch Actions
Automated by Kōan |
c60db1b to
d9f0de2
Compare
Koan-Bot
added a commit
to atoomic/Test-MockFile
that referenced
this pull request
Feb 24, 2026
IO::File::open() uses CORE::open internally, which bypasses CORE::GLOBAL::open and makes IO::File->new() ignore mocked files. Fix: replace IO::File::open with a wrapper that checks if the target file is mocked. If mocked, tie the existing IO::File glob directly (avoiding the need to create a new handle). If not mocked, fall through to the original IO::File::open via goto. This follows the same pattern as the Cwd::abs_path override (PR cpanel#211) — intercept at the namespace level when C/XS code bypasses CORE::GLOBAL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cwd::abs_path uses XS (bsd_realpath) which bypasses CORE::GLOBAL::readlink, so mocked symlinks were invisible to it. Fix: replace Cwd::abs_path, realpath, fast_abs_path, and fast_realpath with a wrapper that walks path components, resolves mocked symlinks, and falls through to the original implementation when no mocked paths are involved. The override is installed in the same BEGIN block as the CORE::GLOBAL overrides. When Cwd is imported AFTER Test::MockFile, the imported functions also get the override. Features: - Resolves direct mocked symlinks - Follows chained symlinks (a -> b -> c) - Resolves intermediate symlinks in paths (/link/subdir/file) - Handles relative symlink targets (including ..) - Detects circular symlinks (ELOOP) - Falls through to original for non-mocked paths 21 new tests in t/cwd_abs_path.t. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
d9f0de2 to
344bcc7
Compare
Koan-Bot
added a commit
to atoomic/Test-MockFile
that referenced
this pull request
Feb 25, 2026
IO::File::open() uses CORE::open internally, which bypasses CORE::GLOBAL::open and makes IO::File->new() ignore mocked files. Fix: replace IO::File::open with a wrapper that checks if the target file is mocked. If mocked, tie the existing IO::File glob directly (avoiding the need to create a new handle). If not mocked, fall through to the original IO::File::open via goto. This follows the same pattern as the Cwd::abs_path override (PR cpanel#211) — intercept at the namespace level when C/XS code bypasses CORE::GLOBAL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #139.
Cwd::abs_path()uses XS (bsd_realpath) which calls the realreadlink()at the C level, completely bypassing ourCORE::GLOBAL::readlinkoverride. This means mocked symlinks are invisible toabs_path/realpath.Fix: Override
Cwd::abs_path,Cwd::realpath,Cwd::fast_abs_path, andCwd::fast_realpathwith a wrapper that walks path components one-by-one, resolving mocked symlinks from%files_being_mocked. When no mocked paths are involved, the original implementation is called.What works:
abs_path('/mocked_link')→ follows to targeta → b → cabs_path('/link/subdir/file')when/linkis mocked..)ELOOP)abs_pathfor non-mocked pathsCwd::abs_path(...)and importedabs_path(...)Limitation:
When
Cwdis imported BEFORETest::MockFile(e.g.use Cwd qw(abs_path); use Test::MockFile), the importedabs_pathcaptures the original XS function. LoadTest::MockFilefirst for the import to work. The fully qualifiedCwd::abs_path(...)always works regardless of load order.Test plan
t/cwd_abs_path.t🤖 Generated with Claude Code