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

Add support for symlinks on Windows #2

Closed
martinvonz opened this issue Jan 8, 2021 · 4 comments · Fixed by #2939
Closed

Add support for symlinks on Windows #2

martinvonz opened this issue Jan 8, 2021 · 4 comments · Fixed by #2939

Comments

@martinvonz
Copy link
Owner

martinvonz commented Jan 8, 2021

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.

@bpollack
Copy link

bpollack commented Jan 8, 2021

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.

@martinvonz
Copy link
Owner Author

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!

@quark-zju
Copy link
Contributor

quark-zju commented Feb 1, 2021

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.

@martinvonz
Copy link
Owner Author

Thanks for checking!

ilyagr added a commit that referenced this issue May 6, 2024
For example, 

```
<<<<<<< Conflict 1 of 3
+++++++ Contents of side #1
left 3.1
left 3.2
left 3.3
%%%%%%% Changes from base to side #2
-line 3
+right 3.1
>>>>>>>
```

or

```
<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side #1
-line 3
+right 3.1
+++++++ Contents of side #2
left 3.1
left 3.2
left 3.3
>>>>>>>
```

Currently, there is no way to disable these, this is TODO for a future
PR. Other TODOs for future PRs: make these labels configurable. After
that, we could support a `diff3/git`-like conflict format as well, in
principle.

Counting conflicts helps with knowing whether you fixed all the
conflicts while you are in the editor.

While labeling "side #1", etc, does not tell you the commit id or
description as requested in #1176, I still think it's an improvement.
Most importantly, I hope this will make `jj`'s conflict format less
scary-looking for new users.

I've used this for a bit, and I like it. Without the labels, I would see
that the two conflicts have a different order of conflict markers, but I
wouldn't be able to remember what that means. For longer diffs, it can
be tricky for me to quickly tell that it's a diff as opposed to one of
the sides. This also creates some hope of being able to navigate a
conflict with more than 2 sides.

Another not-so-secret goal for this is explained in
#3109 (comment). The
idea is a little weird, but I *think* it could be helpful, and I'd like
to experiment with it.
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

Successfully merging a pull request may close this issue.

3 participants