Skip to content
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

Reloading fails on Windows with Unix search path #17

Open
gabdube opened this issue Mar 29, 2019 · 10 comments
Open

Reloading fails on Windows with Unix search path #17

gabdube opened this issue Mar 29, 2019 · 10 comments

Comments

@gabdube
Copy link
Contributor

gabdube commented Mar 29, 2019

On windows, if a unix path is used in "search_paths" (ex: DynamicReload::new(Some(vec!["./routes/target/debug/"]), Some("target/debug"), Search::Default); ), the changes to the libraries are not reported. This is most likely because dynamic_reload cannot match the path sent by the watcher to the one saved in the Lib.

Here's an example of events that fails to be matched
ex: RawEvent { path: Some("C:\\Users\\Gab\\Documents\\projects\\test\\./routes/target/debug\\routes.dll"), op: Ok(WRITE), cookie: None }

I've managed to fix this by mapping the path in search_paths with .canonicalize. Therefore replacing search_paths: Vec<&'a str> by search_paths: Vec<PathBuf>

With this the event becomes

RawEvent { path: Some("\\\\?\\C:\\Users\\Gab\\Documents\\projects\\test\\routes\\target\\debug\\routes.dll"), op: Ok(WRITE), cookie: None }

And everything works fine. Not exactly sure how this would impact non Windows OS though...

@emoon
Copy link
Owner

emoon commented Mar 30, 2019

Hi. Thanks for the report. Could you try to make a PR with this change? As I have some CI running for non-Windows platforms it should report if something goes bad.

Cheers!

@gabdube
Copy link
Contributor Author

gabdube commented Mar 30, 2019

So the tests didn't pass because canonicalize returns an Err if it's called on a path that do not exist (ex: "../test"). To fix the issue, I've added a fallback that use the non-canon path in that case.

I assume it's OK to pass a path that do not exist just in case the application creates the folder after DynamicReload was is instanced.

@emoon
Copy link
Owner

emoon commented Mar 30, 2019

Yeah. It may be a directory that gets populated later and things like that.

@Boscop
Copy link
Contributor

Boscop commented Oct 27, 2020

@gabdube Does that mean if the folder is only created later (so the path only becomes valid after DynamicReload::new/get_search_paths is called), it doesn't get canonicalized, so the issue still happens in that case?

@gabdube
Copy link
Contributor Author

gabdube commented Oct 29, 2020

Just tested it and it panics. Do you think we could just create the path if it doesn't already exists?

@Boscop
Copy link
Contributor

Boscop commented Oct 30, 2020

@gabdube I think it would make more sense to canonicalize the path as soon as it exists and the dll is loaded.

@gabdube
Copy link
Contributor Author

gabdube commented Oct 30, 2020

@Boscop Not sure if that's possible because we are sending the path to the watcher and at that point its out of our control.

@Boscop
Copy link
Contributor

Boscop commented Oct 30, 2020

@gabdube Ah right. I think the best solution would be to compare paths in a way that treats / and \ the same.
This crate could be useful: https://crates.io/crates/relative-path
Or this one (probably even more useful): https://crates.io/crates/path-slash
(But it could also be done in-place to avoid allocations.)

@Boscop
Copy link
Contributor

Boscop commented Nov 9, 2020

There's a new crate that could be very useful for this issue:
https://www.reddit.com/r/rust/comments/jqx8hf/normpath_more_reliable_path_manipulation/

normpath - a crate meant to make correct path manipulation easier. It lets you to avoid doing canonicalization that is often unnecessary on Windows and unreliable: #45067, #48249, #52440, #55812, #58613, #59107, #74327. Canonicalization can cause errors for some valid paths (e.g., shared partitions) and always returns a verbatim path, which is usually unexpected. Normalization is probably what you want instead, which this crate provides with PathExt::normalize.

It also defines BasePath and BasePathBuf, which improve the API of Path and PathBuf and handle more edge cases when joining paths. For example, you can use them to join verbatim paths without custom workarounds.

@Boscop
Copy link
Contributor

Boscop commented Dec 2, 2022

On nightly, std now has a function to make paths absolute without requiring the file to exist!

https://doc.rust-lang.org/nightly/std/path/fn.absolute.html

This would solve this issue but it's only on nightly for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants