-
Notifications
You must be signed in to change notification settings - Fork 322
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
Comments
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 ( |
I think |
Based on tests using |
Thanks for checking! |
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.
Adds a new "ui.conflict-marker-style" config option. The "diff" option is the default jj-style conflict markers with a snapshot and a series of diffs to apply to the snapshot. New conflict marker style options will be added in later commits. The majority of the changes in this commit are from passing the config option down to the code that materializes the conflicts. Example of "diff" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); %%%%%%% Changes from base to side martinvonz#2 -fn example(w: String) { +fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "snapshot" conflict marker style which returns a series of snapshots, similar to Git's "diff3" conflict style. The "snapshot" option uses a subset of the conflict hunk headers as the "diff" option (it just doesn't use "%%%%%%%"), meaning that the two options are trivially compatible with each other (i.e. a file materialized with "snapshot" can be parsed with "diff" and vice versa). Example of "snapshot" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); ------- Contents of base fn example(w: String) { println!("word is {w}"); +++++++ Contents of side martinvonz#2 fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "ui.conflict-marker-style" config option. The "diff" option is the default jj-style conflict markers with a snapshot and a series of diffs to apply to the snapshot. New conflict marker style options will be added in later commits. The majority of the changes in this commit are from passing the config option down to the code that materializes the conflicts. Example of "diff" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); %%%%%%% Changes from base to side martinvonz#2 -fn example(w: String) { +fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "snapshot" conflict marker style which returns a series of snapshots, similar to Git's "diff3" conflict style. The "snapshot" option uses a subset of the conflict hunk headers as the "diff" option (it just doesn't use "%%%%%%%"), meaning that the two options are trivially compatible with each other (i.e. a file materialized with "snapshot" can be parsed with "diff" and vice versa). Example of "snapshot" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); ------- Contents of base fn example(w: String) { println!("word is {w}"); +++++++ Contents of side martinvonz#2 fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "ui.conflict-marker-style" config option. The "diff" option is the default jj-style conflict markers with a snapshot and a series of diffs to apply to the snapshot. New conflict marker style options will be added in later commits. The majority of the changes in this commit are from passing the config option down to the code that materializes the conflicts. Example of "diff" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); %%%%%%% Changes from base to side martinvonz#2 -fn example(w: String) { +fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "snapshot" conflict marker style which returns a series of snapshots, similar to Git's "diff3" conflict style. The "snapshot" option uses a subset of the conflict hunk headers as the "diff" option (it just doesn't use "%%%%%%%"), meaning that the two options are trivially compatible with each other (i.e. a file materialized with "snapshot" can be parsed with "diff" and vice versa). Example of "snapshot" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); ------- Contents of base fn example(w: String) { println!("word is {w}"); +++++++ Contents of side martinvonz#2 fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "ui.conflict-marker-style" config option. The "diff" option is the default jj-style conflict markers with a snapshot and a series of diffs to apply to the snapshot. New conflict marker style options will be added in later commits. The majority of the changes in this commit are from passing the config option down to the code that materializes the conflicts. Example of "diff" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); %%%%%%% Changes from base to side martinvonz#2 -fn example(w: String) { +fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "snapshot" conflict marker style which returns a series of snapshots, similar to Git's "diff3" conflict style. The "snapshot" option uses a subset of the conflict hunk headers as the "diff" option (it just doesn't use "%%%%%%%"), meaning that the two options are trivially compatible with each other (i.e. a file materialized with "snapshot" can be parsed with "diff" and vice versa). Example of "snapshot" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side martinvonz#1 fn example(word: String) { println!("word is {word}"); ------- Contents of base fn example(w: String) { println!("word is {w}"); +++++++ Contents of side martinvonz#2 fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "git-diff3" conflict marker style option. This option matches Git's "diff3" conflict style, allowing these conflicts to be parsed by some external tools that don't support JJ-style conflicts. If a conflict has more than 2 sides, then it falls back to the similar "snapshot" conflict marker style. The conflict parsing code now supports parsing Git-style conflict markers in addition to the normal JJ-style conflict markers, regardless of the conflict marker style setting. This has the benefit of allowing the user to switch the conflict marker style while they already have conflicts checked out, and their old conflicts will still be parsed correctly. Example of "git-diff3" conflict markers: ``` <<<<<<< Side martinvonz#1 (Conflict 1 of 1) fn example(word: String) { println!("word is {word}"); ||||||| Base fn example(w: String) { println!("word is {w}"); ======= fn example(w: &str) { println!("word is {w}"); >>>>>>> Side martinvonz#2 (Conflict 1 of 1 ends) } ```
Adds a new "ui.conflict-marker-style" config option. The "diff" option is the default jj-style conflict markers with a snapshot and a series of diffs to apply to the snapshot. New conflict marker style options will be added in later commits. The majority of the changes in this commit are from passing the config option down to the code that materializes the conflicts. Example of "diff" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side #1 fn example(word: String) { println!("word is {word}"); %%%%%%% Changes from base to side #2 -fn example(w: String) { +fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "snapshot" conflict marker style which returns a series of snapshots, similar to Git's "diff3" conflict style. The "snapshot" option uses a subset of the conflict hunk headers as the "diff" option (it just doesn't use "%%%%%%%"), meaning that the two options are trivially compatible with each other (i.e. a file materialized with "snapshot" can be parsed with "diff" and vice versa). Example of "snapshot" conflict markers: ``` <<<<<<< Conflict 1 of 1 +++++++ Contents of side #1 fn example(word: String) { println!("word is {word}"); ------- Contents of base fn example(w: String) { println!("word is {w}"); +++++++ Contents of side #2 fn example(w: &str) { println!("word is {w}"); >>>>>>> Conflict 1 of 1 ends } ```
Adds a new "git" conflict marker style option. This option matches Git's "diff3" conflict style, allowing these conflicts to be parsed by some external tools that don't support JJ-style conflicts. If a conflict has more than 2 sides, then it falls back to the similar "snapshot" conflict marker style. The conflict parsing code now supports parsing Git-style conflict markers in addition to the normal JJ-style conflict markers, regardless of the conflict marker style setting. This has the benefit of allowing the user to switch the conflict marker style while they already have conflicts checked out, and their old conflicts will still be parsed correctly. Example of "git" conflict markers: ``` <<<<<<< Side #1 (Conflict 1 of 1) fn example(word: String) { println!("word is {word}"); ||||||| Base fn example(w: String) { println!("word is {w}"); ======= fn example(w: &str) { println!("word is {w}"); >>>>>>> Side #2 (Conflict 1 of 1 ends) } ```
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 augie@google.com and former hg contributor "bmp" was (please correct me if I'm wrong):
symlink
creates, because it creates "junctions", which is not what we want.Rust's standard library has
std::os::windows::fs::symlink_file
andstd::os::windows::fs::symlink_dir
, which both seem to callCreateSymbolicLinkW
, only with different flags. Perhaps we can always use thesymlink_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.The text was updated successfully, but these errors were encountered: