-
Notifications
You must be signed in to change notification settings - Fork 779
Fix symlink copy failing when source and dest symlinks point to same target #1060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix symlink copy failing when source and dest symlinks point to same target #1060
Conversation
|
Nevermind the macOS CI failures; unrelated to this PR. |
|
macOS CI fixed in #1061; feel free to rebase. |
RyanZim
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; just might be good to have a little more test completeness. This is a fix for #1019, right?
@PazerOP Not a bother at all, this PR is in better shape than a lot of human-created PRs I see. OOI, what was your prompt? |
It's a bit of a stretch to call this a prompt IMO, basically handed it the answer. This is the result of debugging the problem in Claude Code CLI, then saying "just describe in detail the issue and how to fix it, i'll delegate it to another coding agent". Then I stuck this in the web edition of Claude Code Opus 4.5. It took 8.5 minutes.
|
…target
When copying a directory containing symlinks, if the destination already
contains symlinks pointing to the same target as the source symlinks,
the operation would incorrectly fail with "Cannot copy X to a subdirectory
of itself" error.
This happened because the isSrcSubdir() check returns true when two paths
are identical. However, two different symlinks that happen to point to
the same target are distinct filesystem entries that should be copyable.
The fix adds a check to ensure the resolved paths are actually different
before applying the subdirectory constraints. When both symlinks resolve
to the same target (resolvedSrc === resolvedDest), we skip the subdirectory
checks and allow the copy to proceed, which correctly replaces the
destination symlink with the source symlink.
Fixes issue where:
- Source: ./src/link → symlink to /tmp/target
- Dest: ./dest/link → symlink to /tmp/target
- copySync('./src', './dest') would fail
Added comprehensive test cases for:
- Copy symlink when dest has no existing symlink
- Overwrite symlink when dest has symlink pointing to SAME target
- Overwrite symlink when dest has symlink pointing to DIFFERENT target
- File symlinks with same target
- Edge case: copying symlink to itself still fails
- Edge case: copying symlink into subdirectory of its target works
- Add DIFFERENT target tests for file symlinks (async + sync) - Add direct symlink-to-symlink copy test for issue jprichardson#1019 - Add issue jprichardson#1027 reference to existing tests
8614b40 to
fba3725
Compare
JPeer264
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Amazing that you added so many tests for it
|
Thanks. I think someone needs to approve the Github Actions workflow to run before this can be merged. |
manidlou
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
Will release tomorrow. BTW, unless things have changed since then, as per #1019 (comment), this is also a bug in Node core |
|
Published as v11.3.3 🎉 |
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [fs-extra](https://github.com/jprichardson/node-fs-extra) | [`^10.0.0` → `^11.0.0`](https://renovatebot.com/diffs/npm/fs-extra/10.1.0/11.3.3) |  |  | --- ### Release Notes <details> <summary>jprichardson/node-fs-extra (fs-extra)</summary> ### [`v11.3.3`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1133--2025-12-18) [Compare Source](jprichardson/node-fs-extra@11.3.2...11.3.3) - Fix copying symlink when destination is a symlink to the same target ([#​1019](jprichardson/node-fs-extra#1019), [#​1060](jprichardson/node-fs-extra#1060)) ### [`v11.3.2`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1132--2025-09-15) [Compare Source](jprichardson/node-fs-extra@11.3.1...11.3.2) - Fix spurrious `UnhandledPromiseRejectionWarning` that could occur when calling `.copy()` in some cases ([#​1056](jprichardson/node-fs-extra#1056), [#​1058](jprichardson/node-fs-extra#1058)) ### [`v11.3.1`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1131--2025-08-05) [Compare Source](jprichardson/node-fs-extra@11.3.0...11.3.1) - Fix case where `move`/`moveSync` could incorrectly think files are identical on Windows ([#​1050](jprichardson/node-fs-extra#1050)) ### [`v11.3.0`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1130--2025-01-15) [Compare Source](jprichardson/node-fs-extra@11.2.0...11.3.0) - Add promise support for newer `fs` methods ([#​1044](jprichardson/node-fs-extra#1044), [#​1045](jprichardson/node-fs-extra#1045)) - Use `fs.opendir` in `copy()`/`copySync()` for better perf/scalability ([#​972](jprichardson/node-fs-extra#972), [#​1028](jprichardson/node-fs-extra#1028)) ### [`v11.2.0`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1120--2023-11-27) [Compare Source](jprichardson/node-fs-extra@11.1.1...11.2.0) - Copy directory contents in parallel for better performance ([#​1026](jprichardson/node-fs-extra#1026)) - Refactor internal code to use `async`/`await` ([#​1020](jprichardson/node-fs-extra#1020)) ### [`v11.1.1`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1111--2023-03-20) [Compare Source](jprichardson/node-fs-extra@11.1.0...11.1.1) - Preserve timestamps when moving files across devices ([#​992](jprichardson/node-fs-extra#992), [#​994](jprichardson/node-fs-extra#994)) ### [`v11.1.0`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1110--2022-11-29) [Compare Source](jprichardson/node-fs-extra@11.0.0...11.1.0) - Re-add `main` field to `package.json` for better TypeScript compatibility ([#​979](jprichardson/node-fs-extra#979), [#​981](jprichardson/node-fs-extra#981)) ### [`v11.0.0`](https://github.com/jprichardson/node-fs-extra/blob/HEAD/CHANGELOG.md#1100--2022-11-28) [Compare Source](jprichardson/node-fs-extra@10.1.0...11.0.0) ##### Breaking Changes - Don't allow requiring `fs-extra/lib/SOMETHING` (switched to `exports`) ([#​974](jprichardson/node-fs-extra#974)) - Require Node v14.14+ ([#​968](jprichardson/node-fs-extra#968), [#​969](jprichardson/node-fs-extra#969)) ##### New Features - Add `fs-extra/esm` for ESM named export support; see [docs](https://github.com/jprichardson/node-fs-extra#esm) for details ([#​746](jprichardson/node-fs-extra#746), [#​974](jprichardson/node-fs-extra#974)) - Add promise support for `fs.readv()` ([#​970](jprichardson/node-fs-extra#970)) ##### Bugfixes - Don't `stat` filtered items in `copy*` ([#​965](jprichardson/node-fs-extra#965), [#​971](jprichardson/node-fs-extra#971)) - Remove buggy stats check in `copy` ([#​918](jprichardson/node-fs-extra#918), [#​976](jprichardson/node-fs-extra#976)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4wLjUiLCJ1cGRhdGVkSW5WZXIiOiI0My4wLjUiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIiLCJsYWJlbHMiOlsiYXV0b21hdGVkIiwiZGVwZW5kZW5jaWVzIl19--> Reviewed-on: https://code.popov.link/valentineus/strapi-plugin-checkbox-list/pulls/6 Co-authored-by: renovate[bot] <renovatebot@noreply.localhost> Co-committed-by: renovate[bot] <renovatebot@noreply.localhost>
I couldn't see anything immediately obvious banning AI PRs, hope this isn't a bother. I had Claude create this fix for part of the build process of https://neutralino.js.org/.