-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add tests for hard and soft links #12590
Conversation
af1f272
to
08adb19
Compare
|
21696c5
to
a8ec90d
Compare
43c98c9
to
084c2a3
Compare
@@ -1153,7 +1151,9 @@ mod tests { | |||
#[test] | |||
#[cfg(target_family = "unix")] | |||
fn symlink() -> anyhow::Result<()> { | |||
use crate::db::tests::TestDb; |
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.
This fixes a few unused warnings on windows
.expect("Expected watch changes but observed none.") | ||
} | ||
|
||
fn try_stop_watch(&mut self, timeout: Duration) -> Option<Vec<watch::ChangeEvent>> { |
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.
I hope this will help to improve the stability of the tests. We can now use a high timeout for functions that expect at least a single event and a smaller timeout for functions that don't.
fn next_io_tick() { | ||
let temp = tempfile::tempfile().unwrap(); | ||
/// Updates the content of a file and ensures that the last modified file time is updated. | ||
fn update_file(path: impl AsRef<SystemPath>, content: &str) -> anyhow::Result<()> { |
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.
Let's hope this fixes the other instability
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.
Some of this I've only skimmed, but it LGTM overall. I have a few questions and a few nits:
f4d9ec9
to
3570bb7
Compare
Summary
The goal I set out for was to add support for symlinks and hard links when watching files. I no longer think we should pursue this goal, at least not now. This PR has mainly become a documentation PR and it adds a few tests demonstrating the behavior on different systems/platforms.
Why not support watching symlinks and hardlinks? Primarily, because I don't think there's sufficient use to justify the complexity. I tested both VS Code and Pycharm and both show stale results after making changes to a hard-linked file or updating a symlinked file. This is as good as Red Knot is today. Specifically, the following changes are not supported:
The other reason is that the platform specific file watcher APIs don't generate the necessary events. I compared the events with
@parcel/watcher
(used by VS Code, and parcel), andfs.watch
(nodejs) and the generated events match. The only system that I found that supported hard links well is Pyright which is based onchokidar
. I'm not a 100% sure how chokidar makes it work but I belive it does a directory traversal to find changes rather than relying on the events only. We could do that as well, but it seems rather expensive to support a not so common workflow.There are ways how we could support symlinks and hardlinks without traversing the directory.
Handle
toVec<File>
to lookup all files pointing to the same hard link. There's some complexity how we would support this with ourSystem
abstractionreal_path
toVec<File>
for all symlinked files.I think any approach (or traversing the directory to find changes) is worth exploring if this is something that users run into often.
It is probably also worth exploring watchman as a possible
notify
backend to support very large projects.Side note: Ruff doesn't follow symlinks today. Pyright has support for it.
Test Plan
This PR is only tests 😆