jj
jj copied to clipboard
Add support for symlinks on Windows
We currently don't support symlinks on Windows (in fact, the project doesn't even build on Windows because of that). The advice I got from [email protected] and former hg contributor "bmp" was (please correct me if I'm wrong):
- Prior to Windows 10: No symlink support
- Windows 10 without dev mode: No symlink support
- Windows 10 dev mode: use FFI to call CreateSymbolicLink
- Don't use the
symlink
creates, because it creates "junctions", which is not what we want.
Rust's standard library has std::os::windows::fs::symlink_file
and std::os::windows::fs::symlink_dir
, which both seem to call CreateSymbolicLinkW
, only with different flags. Perhaps we can always use the symlink_file
version? It's still unclear to me what the effect would be if a "file symbolic link" points to a target that's actually a directory.
Correct enough for government purposes.
To clarify, not to be annoying, but just in case it changes anything: Windows supports symlinks when Developer Mode isn't enabled, and has done so going all the way back to at least Vista. What actually changed was that, prior to Windows 10, you needed to be an admin to create them. The only (albeit major) thing Windows 10 with Developer Mode changes is that normal users can now create symlinks, rather than either needing to run a process as an admin or mucking about with group policy options (GPOs).
For reasons I'm not clear on, the underlying API for this (CreateSymbolicLinkW
) still requires you to say whether you're linking a file or a directory. I have absolutely no idea why, but I don't //think// (from two minutes of mucking about) you can cheat, just pass 0x0
, and be happy.
I think 0x0
is what std::os::windows::fs::symlink_file
passes, so I guess we'll try to do that whether the target is a file or a directory. I don't have access to a Windows machine, but it sounded like Augie might be able to attempt it later. Thanks!
Based on tests using mklink /D
vs mklink
, I think symlink_dir
is the one to be used. It seems to handle both the directory and file cases, while directory symlink crated by symlink_file
won't allow cd
into it.
Thanks for checking!