Skip to content

fix(path): show one separator in a displayed Windows path - #12024

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix/display-path-separators
Aug 15, 2026
Merged

jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix/display-path-separators

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

A single path mise prints on Windows can carry both separators at once. Measured on
2026.8.2 windows-x64:

> mise config ls
C:\Users\Jam\.config/mise/config.toml    go, uv

> mise ls --current
go   1.26.5   C:\Users\Jam\.config/mise/config.toml   1.26

> mise generate git-pre-commit --write
Wrote to C:/Users/Jam/...\probeHook\.git/hooks\pre-commit

The last one switches form three times inside one path.

Two causes, and why fixing the construction sites does not finish the job

  1. Multi-segment literals. Path::join appends what it is given verbatim, so
    root.join(".git/hooks"), .join(".github/workflows"), .join(".devcontainer/devcontainer.json")
    and the config-filename candidates (".config/mise/config.toml" and friends) resolve correctly
    through components() while Display shows the /.
  2. Roots that arrive /-separated. The C:/Users/... above comes from the git library, not
    from anything mise assembled — there is no construction site to fix.

The change

Settled in PathExt::display_user, which #12014 established as the one place mise turns a path
into text for a person. That covers both causes at once, including (2).

/ is a separator on Windows and never part of a name, so both spellings address the same file
and rewriting is safe for display. Nothing changes off Windows, where \ is an ordinary
filename character — a file really can be named weird\name there, and turning that into a
separator would rename it in the message. The existing unix test pins that boundary.

display_rel_path bypassed display_user entirely, hardcoding ./ and printing the remainder
raw, so it produced ./mise-tasks\build. Its prefix now takes MAIN_SEPARATOR and its remainder
goes through display_user. On unix that is byte-identical, since MAIN_SEPARATOR is / and
display_user rewrites nothing. Its only caller is the +path/-path status line in hook_env.

Deliberately unchanged

  • The construction sites. Display settles all of them together, and one of the two causes has
    no construction site in mise to begin with.
  • Paths that flow into data — mise ls --json values, shim contents. Those go out through
    to_string_lossy, not display_path. The case that mattered there was already fixed at the
    source: see the note on replace_path, where tilde expansion was producing
    C:\Users\me\.local/share/mise and that path reached MISE_DATA_DIR, shims and ls --json.
    This PR is the display half of the same symptom, and says so rather than widening.
  • Glob patterns. Checked before writing anything, since \ is an escape in a glob and
    rewriting one would mislead: across all 356 display_path/display_rel_path call sites, none
    takes a pattern. Patterns are carried as String and printed with {}; the one site in
    task_source_checker that looked like a candidate prints a resolved source file.

Verification

Measured before the change (the three commands above) and again afterwards against the exact
composition the code performs, with a small cargo probe rather than by reading:

\\?\C:\a\b                              -> C:\a\b
C:/Users/me\proj\.git/hooks\pre-commit  -> C:\Users\me\proj\.git\hooks\pre-commit
\\server\share/dir                      -> \\server\share\dir
a/b                                     -> a\b
\\?\C:\a/b                              -> \\?\C:\a\b      <- not C:\a\b

That last one corrected an assertion I had written from reasoning: / is not a separator inside
\\?\, so a/b reads as one component there and dunce declines to simplify a name Windows
could not hold. The separators still settle; the prefix stays. canonicalize never emits that
shape, but the test now records the real answer.

Tests:

  • src/path.rs: a path that switches form three times settles; already-uniform, relative and UNC
    inputs; composition with the extended-length prefix from fix(trust): stop printing extended-length path prefixes #12014; and on unix, that weird\name
    and /a/b\c are left exactly as they are.
  • src/file.rs: display_rel_path uses the host separator on both halves.
  • e2e-win/display_path_separators.Tests.ps1: mise generate git-pre-commit --write and
    mise config ls report no /, while still naming the path — so neither can pass by printing
    nothing. Matched as a literal, since -BeLike would read ? and [ as wildcards.

cargo fmt was run locally. The build, clippy and the test suite were not — those are left to
CI, so behaviour after the fix rests on the measurements above and on the tests rather than on a
running binary.

Found while auditing Windows behaviour, the same pass that produced #12007, #12008, #12012, #12013,
#12014, #12016 and #12023. No existing issue or discussion covers it.

Summary by CodeRabbit

  • Bug Fixes
    • Windows paths now consistently display with backslash separators instead of mixed / and \ formatting.
    • Improved display of relative, extended-length, and network (UNC) paths.
    • Non-Windows behavior remains unchanged, including support for backslashes in Unix filenames.
    • Generated-file output and configuration listings now show expected Windows path formatting.
    • Path-related output and cache explanations now use the correct separators for the host platform.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 442c5a23-e9ed-4daf-9916-f66f41f17499

📥 Commits

Reviewing files that changed from the base of the PR and between 758eb7f and 6b14ce2.

📒 Files selected for processing (1)
  • src/file.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/file.rs

📝 Walkthrough

Walkthrough

Displayed paths now use host-specific separators. Windows output uses backslashes, while Unix output preserves existing behavior. Relative-path formatting, display assertions, and Windows end-to-end output have dedicated coverage.

Changes

Path display normalization

Layer / File(s) Summary
Define separator normalization
src/path.rs
settle_display_separators normalizes Windows display separators. display_user preserves separators for identity matching. Tests cover Windows and Unix behavior.
Apply normalization to displayed paths
src/file.rs, src/cli/generate/*.rs, src/task/task_cache.rs, src/toolset/tool_source.rs
display_path and display_rel_path use host-specific separators. Generate commands import the local implementation. Display assertions use platform-specific expectations.
Validate Windows displayed output
e2e-win/display_path_separators.Tests.ps1
End-to-end tests isolate configuration state and verify generated-file and configuration-listing output without / separators.

Estimated code review effort: 2 (Simple) | ~15 minutes

Merge Risk: ⚪ Minimal · up to 6b14c

This localized change standardizes displayed Windows path separators without altering stored paths or non-Windows behavior. No actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

  • jdx/mise#11312: Both changes modify Windows path-separator handling in src/file.rs.
  • jdx/mise#11948: Both changes preserve and restore MISE_TRUSTED_CONFIG_PATHS in Windows end-to-end tests.
  • jdx/mise#12014: Both changes update Windows path display behavior in src/path.rs and related tests.

Poem

A rabbit checks each path with care,
Windows gets backslashes there.
Unix keeps its familiar view,
Mixed separators settle too.
Tests guard every route.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: consistent separators in displayed Windows paths.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR normalizes separators in human-facing Windows path output while preserving path identity where strings are matched.

  • Adds host-specific separator normalization to display_path.
  • Updates relative-path rendering and generator output to use the normalized display helper.
  • Adds unit and Windows end-to-end coverage for mixed separators, UNC paths, and extended-length paths.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/path.rs Adds a Windows-only display normalization helper while deliberately preserving display_user semantics for identity-sensitive strings.
src/file.rs Applies separator normalization to human-facing paths and renders relative paths consistently with the host separator.
e2e-win/display_path_separators.Tests.ps1 Verifies generated-hook and config-list output contains a meaningful path without forward slashes on Windows.
src/cli/generate/git_pre_commit.rs Routes the generated-hook status path through the repository display helper without changing generated hook contents.
src/task/task_cache.rs Makes the existing escaped-path assertion platform-aware after display separator normalization.
src/toolset/tool_source.rs Updates display expectations to use the host path separator.

Reviews (4): Last reviewed commit: "fix(path): show one separator in a displ..." | Re-trigger Greptile

@JamBalaya56562
JamBalaya56562 force-pushed the fix/display-path-separators branch 2 times, most recently from 953be03 to 758eb7f Compare August 15, 2026 09:02
`Path::join` appends a multi-segment literal verbatim, so
`root.join(".git/hooks")` resolves correctly through `components()` while
`Display` shows the `/` it was given -- and roots handed back by libraries
arrive `/`-separated already. One printed path could switch form three
times: `C:/Users/me\proj\.git/hooks\pre-commit`.

Settled in `file::display_path`, the helper that formats a path for a
message. Deliberately *not* in `PathExt::display_user`: that one also feeds
strings mise matches rather than shows. `ToolRequest::Path::version()`
builds `path:<display_user>` and lockfile entries are compared on that
string, and `system::edits` compares a user-supplied filter against one --
rewriting there would change identity, not presentation.

Four `mise generate` subcommands were reporting through `xx::file::display_path`
rather than mise's own, so their "Wrote to"/"Generated" lines skipped every
step the rest of mise applies -- no `~`, no extended-length prefix removal,
and now no separator settling. They import `crate::file::display_path` now.
That is what the e2e case in this PR was catching.

`display_rel_path` bypassed the helper too, hardcoding `./` and printing the
remainder raw, so it produced `./mise-tasks\build`. Its prefix now takes the
host separator and its remainder goes through `display_path`.
Byte-identical on unix.
@JamBalaya56562
JamBalaya56562 force-pushed the fix/display-path-separators branch from 758eb7f to 6b14ce2 Compare August 15, 2026 11:27
@JamBalaya56562
JamBalaya56562 marked this pull request as ready for review August 15, 2026 12:36
@jdx
jdx merged commit 194818d into jdx:main Aug 15, 2026
30 checks passed
@JamBalaya56562
JamBalaya56562 deleted the fix/display-path-separators branch August 15, 2026 21:26
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.

2 participants