path: appending local paths to external paths#14278
path: appending local paths to external paths#14278Alizter wants to merge 2 commits intoocaml:mainfrom
Conversation
c34687c to
9718e45
Compare
More test cases documenting quirky path behaviour when working on #14278.
9718e45 to
86f5da9
Compare
|
@nojb You may also be interested in having a look since this relates to path constructions on Windows. |
There was a problem hiding this comment.
Pull request overview
This PR makes path concatenation for external paths consistent across platforms by always using / when appending relative/local path fragments, and by normalizing away ./ and trailing separators in common cases.
Changes:
- Update
Path_external.relativeto join with/and strip leading./plus a trailing separator on the base path. - Update stdune expect-tests and blackbox tests to reflect the new normalized output.
- Add a changelog entry documenting the behavior change.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
otherlibs/stdune/src/path_external.ml |
Changes external path appending logic to normalize ./ and use / separators. |
otherlibs/stdune/test/path_tests.ml |
Updates expect-tests for external-relative normalization (./ removal and trailing slash handling). |
otherlibs/stdune/test/path_external_build_tests.ml |
Updates expectations to be platform-homogeneous for absolute filename/reach outputs. |
test/blackbox-tests/test-cases/optional-executable.t |
Adjusts expected printed binary paths to remove ./ segment. |
doc/changes/fixed/14278.md |
Documents the fix in the changelog. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
The PR says this is a fix, but what's the bug? That we use a different separate on windows? |
That and |
|
Is that a problem? |
|
Both choices of separator are arbitrary so strictly speaking we are not fixing anything. What we are doing however is choosing the more convenient option for dune. When rather than having two cases for Windows and otherwise. |
86f5da9 to
f879433
Compare
|
I've updated the PR title and commit message to say refactor now. |
nojb
left a comment
There was a problem hiding this comment.
Not tested, but LGTM from a distance.
Of course, the logic remains a heuristic: if y starts with ././foo, we are still left with unnecessary components in the path, but if this behaviour matches between Windows and Unix, then that's already an improvement.
| let len = String.length x in | ||
| if len > 0 && is_dir_sep x.[len - 1] then String.take x (len - 1) else x | ||
| in | ||
| x ^ "/" ^ y) |
There was a problem hiding this comment.
I'm unsure about this suggestion, but I always wonder if it isn't better (potentially less allocation) to use String.concat here:
| x ^ "/" ^ y) | |
| String.concat ~sep:"/" [x; y]) |
There was a problem hiding this comment.
That seems better thanks.
|
This remains a draft until I can work out what is going wrong with promotion on Windows. It seems the entries haven't been added to the promotion database correctly. |
Rather than using `Filename.concat` we use `/` as a directory separator on all platforms for paths that we construct. We already do this for local paths, so appending to external paths shouldn't be any different. This makes path behaviour homogeneous across platforms. Importantly on Windows something like: C:\foo\bar + ./baz/zaz used to be C:\foo\bar\./baz/zaz and is now C:\foo\bar/baz/zaz Notice that the prefix is untouched, since we don't control it. When scrubbing prefixes with `BUILD_PATH_PREFIX_MAP` this will mean that `$PREFIX/baz/zaz` will be the same on all platforms. That will be addressed in a later PR. We do however touch the prefix if it ends in a trailing directory separator. Before appending we make sure that this separator is stripped if it exists. The motivation is that both choices of separator are arbitrary, so strictly speaking we are not fixing a bug. What we are doing however is choosing the more convenient option for dune. When `BUILD_PATH_PREFIX_MAP` works we would like scrubbed paths like `$TESTCASE_ROOT/foo` to be the same on all platforms, rather than having two cases for Windows and otherwise. Addresses parts of ocaml#10176 Signed-off-by: Ali Caglayan <alizter@gmail.com>
|
Fun! So Windows' CreateProcessW accepts forward slashes in paths, but when constructing a valid path such as I will add special sanitation for paths involving |
Signed-off-by: Ali Caglayan <alizter@gmail.com>
f879433 to
68f660f
Compare
|
I'm still uncertain if we should be passing mixed paths to @nojb any recommendation? |
I think this makes sense. Backslashes are the native thing on Windows, so from a distance it indeed looks like a more principled approach. |
|
TODO:
|
Rather than using
Filename.concatwe use/as a directory separator on all platforms for paths that we construct. We already do this for local paths, so appending to external paths shouldn't be any different. This makes path behaviour homogeneous across platforms.Importantly on Windows something like:
used to be
and is now
Notice that the prefix is untouched, since we don't control it. When scrubbing prefixes with
BUILD_PATH_PREFIX_MAPthis will mean that$PREFIX/baz/zazwill be the same on all platforms. That will be addressed in a later PR.We do however touch the prefix if it ends in a trailing directory separator. Before appending we make sure that this separator is stripped if it exists.
Addresses parts of