Skip to content

Conversation

@06393993
Copy link
Contributor

@06393993 06393993 commented Nov 30, 2025

... due to using incorrect separators.

Fix #8185.

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, demos/)
  • I have updated the config schema (cli/src/config-schema.json)
  • I have added/updated tests to cover my changes

@06393993 06393993 requested a review from a team as a code owner November 30, 2025 23:57
Copy link
Contributor

@PhilipMetzger PhilipMetzger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG, since its a Windows only fix

@06393993 06393993 enabled auto-merge December 1, 2025 00:06
@yuja
Copy link
Contributor

yuja commented Dec 1, 2025

Directory separators in symlink content will have to be transformed back and forth by local working copy. See #6977 (comment) for the previous discussion.

@06393993
Copy link
Contributor Author

06393993 commented Dec 1, 2025

Directory separators in symlink content will have to be transformed back and forth by local working copy. See #6977 (comment) for the previous discussion.

Then I have a question. What's the plan for handling absolute paths?

@yuja
Copy link
Contributor

yuja commented Dec 1, 2025

Directory separators in symlink content will have to be transformed back and forth by local working copy. See #6977 (comment) for the previous discussion.

Then I have a question. What's the plan for handling absolute paths?

What's different between relative and absolute paths? Absolute paths (and symlinks pointing to out of the tree) wouldn't work on different machines, but I don't think it's wrong to translate /foo/bar to \foo\bar (or c:\foo to c:/foo.)

@06393993
Copy link
Contributor Author

06393993 commented Dec 1, 2025

What's different between relative and absolute paths?

On Windows, absolute paths don't always start with a drive ID(e.g. C:). There are many possible prefixes. For verbatim paths (i.e., prefixed with \\?\), / should not be treated as a separator.

However, given the Windows path name convention, / can't be part of a file name or a directory name, so I also don't think there can be an actual issue with just always applying the slash conversion on snapshot and update on Windows. But we should just do a stirng level character replacement so that the following Windows absolute paths won't get messed up on the same machine1:

  • c:\temp\test-file.txt <-> c:/temp/test-file.txt
  • \\127.0.0.1\c$\temp\test-file.txt <-> //127.0.0.1/c$/temp/test-file.txt
  • \\LOCALHOST\c$\temp\test-file.txt <-> //LOCALHOST/c$/temp/test-file.txt
  • \\.\c:\temp\test-file.txt <-> //./c:/temp/test-file.txt
  • \\?\c:\temp\test-file.txt <-> //?/c:/temp/test-file.txt
  • \\.\UNC\LOCALHOST\c$\temp\test-file.txt <-> //./UNC/LOCALHOST/c$/temp/test-file.txt

Partial conversion can be incorrect. For example, for \\?\c:\temp\test-file.txt, if we convert it to \\?\c:/temp/test-file.txt in Store, and use the following try_symlink implementation:

        let original = original
            .as_ref()
            .components()
            .fold(std::path::PathBuf::new(), |res, component| {
                res.join(component)
            });
        symlink_file(original, link)

an incorrect symink to \\?\c:/temp/test-file.txt will be created, because the components functions will yield \\?\c:, \, and temp/test-file.txt. For the same reason, the existing file_util::slash_path function can't be used.

Footnotes

  1. The example paths come from https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#example-ways-to-refer-to-the-same-file, so they are very likely to be valid paths.

@yuja
Copy link
Contributor

yuja commented Dec 2, 2025

But we should just do a stirng level character replacement so that the following Windows absolute paths won't get messed up on the same machine

Yes, I meant textual conversion. We might have to fix slash_path() to do that. I think we use path.components() there just because string manipulation over OsStr isn't easy.

@06393993 06393993 force-pushed the fix_symlink_win branch 10 times, most recently from 9c77c29 to dedf4bd Compare December 2, 2025 19:05
@06393993
Copy link
Contributor Author

06393993 commented Dec 2, 2025

Yes, I meant textual conversion.

Done. Also added test to guard the usage of absolute symlinks on Windows which fails if we use std::pah::Path::components(https://doc.rust-lang.org/std/path/struct.Path.html#method.components).

Copy link
Contributor

@yuja yuja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also update the changelog?
Thanks.

@06393993 06393993 force-pushed the fix_symlink_win branch 3 times, most recently from 6b2c869 to ff6d52f Compare December 3, 2025 16:18
@06393993 06393993 disabled auto-merge December 3, 2025 16:19
@06393993 06393993 requested a review from yuja December 3, 2025 16:20
@06393993 06393993 force-pushed the fix_symlink_win branch 2 times, most recently from 2b81558 to 83392f5 Compare December 3, 2025 18:42
... due to using incorrect separators.

Fix jj-vcs#8185.
@06393993 06393993 added this pull request to the merge queue Dec 5, 2025
Merged via the queue into jj-vcs:main with commit eb1f72a Dec 5, 2025
29 checks passed
@06393993 06393993 deleted the fix_symlink_win branch December 5, 2025 04:02
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 this pull request may close these issues.

Windows symlink is not correctly created

3 participants