Skip to content

Commit 483aa0d

Browse files
fix(task): honor MISE_CYGDRIVE_PREFIX for Git Bash, not only Cygwin (#10190)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 9ecd682 commit 483aa0d

2 files changed

Lines changed: 55 additions & 19 deletions

File tree

docs/troubleshooting.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,21 @@ the intended one is used:
204204
$env:MISE_BASH_PATH = "C:\cygwin64\bin\bash.exe"
205205
```
206206

207-
If you changed the `cygdrive` prefix in `/etc/fstab` (the default is `/cygdrive`),
208-
set `MISE_CYGDRIVE_PREFIX` to match — mise does not read `/etc/fstab`:
207+
#### Custom `cygdrive` mount root (Cygwin **and** Git Bash / MSYS2)
208+
209+
The `cygdrive` automount mechanism is shared by Cygwin and MSYS2 / Git Bash — both let
210+
you change the mount root in `/etc/fstab` (Cygwin's default is `/cygdrive`, Git Bash /
211+
MSYS2's is `/`, i.e. `/c/...`). mise does not read `/etc/fstab`, so if you changed it,
212+
set `MISE_CYGDRIVE_PREFIX` to match — this works for **either** shell:
209213

210214
```powershell
211215
# e.g. for an fstab that mounts drives under /mnt
212216
$env:MISE_CYGDRIVE_PREFIX = "/mnt"
213217
```
214218

215219
The prefix must be absolute (start with `/`); a relative value like `mnt` is rejected
216-
with a warning and the default `/cygdrive` is used instead.
220+
with a warning and the shell's default is used instead. `MISE_CYGDRIVE_PREFIX=/`
221+
collapses to the Git Bash `/c/...` form.
217222

218223
## mise isn't working when calling from tmux or another shell initialization script
219224

src/task/task_executor.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,27 +1529,33 @@ fn maybe_convert_env_for_msys_shell<'a>(
15291529
}
15301530

15311531
/// The cygdrive prefix inserted before drive letters when converting PATH for a
1532-
/// POSIX shell: empty for MSYS2 / Git Bash (`/c/...`), `/cygdrive` for Cygwin
1533-
/// (`/cygdrive/c/...`). A Cygwin user with a non-default `cygdrive` mount (configured
1534-
/// in `/etc/fstab`) can override it via `MISE_CYGDRIVE_PREFIX` — mise does not parse
1535-
/// fstab. A trailing `/` is trimmed since the converter emits its own separator after
1536-
/// the prefix, so `MISE_CYGDRIVE_PREFIX=/` collapses to the MSYS `/c/...` form. A
1537-
/// non-empty value that is not absolute (no leading `/`, e.g. `mnt`) would produce
1538-
/// relative PATH entries that bash silently ignores, so it is rejected with a warning
1539-
/// and the default `/cygdrive` is used instead.
1532+
/// POSIX shell. `is_cygwin_shell` only selects the *default* when no override is set:
1533+
/// empty for MSYS2 / Git Bash (`/c/...`), `/cygdrive` for Cygwin (`/cygdrive/c/...`).
1534+
///
1535+
/// The `cygdrive` automount mechanism is shared by Cygwin and MSYS2 / Git Bash — both
1536+
/// let the user change the mount root in `/etc/fstab` (Cygwin's default is `/cygdrive`,
1537+
/// MSYS2's is `/`). mise does not parse fstab, so `MISE_CYGDRIVE_PREFIX` is an explicit
1538+
/// override honored for *both* shells. A trailing `/` is trimmed since the converter
1539+
/// emits its own separator after the prefix, so `MISE_CYGDRIVE_PREFIX=/` collapses to
1540+
/// the MSYS `/c/...` form. A non-empty value that is not absolute (no leading `/`, e.g.
1541+
/// `mnt`) would produce relative PATH entries that bash silently ignores, so it is
1542+
/// rejected with a warning and the shell's default is used instead.
15401543
#[cfg(windows)]
15411544
fn msys_drive_prefix_for(program: &Path, env: &BTreeMap<String, String>) -> String {
1542-
const DEFAULT: &str = "/cygdrive";
1543-
if !crate::path::is_cygwin_shell(program) {
1544-
return String::new();
1545-
}
1545+
// Default automount root when no override is set: empty for Git Bash / MSYS2
1546+
// (`/c/...`), `/cygdrive` for Cygwin (`/cygdrive/c/...`).
1547+
let default = if crate::path::is_cygwin_shell(program) {
1548+
"/cygdrive"
1549+
} else {
1550+
""
1551+
};
15461552
let raw = env
15471553
.get("MISE_CYGDRIVE_PREFIX")
15481554
.cloned()
15491555
.or_else(|| std::env::var("MISE_CYGDRIVE_PREFIX").ok())
15501556
.filter(|s| !s.is_empty());
15511557
let Some(mut s) = raw else {
1552-
return DEFAULT.to_string();
1558+
return default.to_string();
15531559
};
15541560
// Trim trailing slashes in place — the converter appends its own separator.
15551561
s.truncate(s.trim_end_matches('/').len());
@@ -1559,11 +1565,18 @@ fn msys_drive_prefix_for(program: &Path, env: &BTreeMap<String, String>) -> Stri
15591565
} else if s.starts_with('/') {
15601566
s
15611567
} else {
1568+
// Describe the default clearly: an empty prefix is the Git Bash `/c/...` form,
1569+
// otherwise the Cygwin `/cygdrive` root.
1570+
let default_desc = if default.is_empty() {
1571+
"the Git Bash `/c/...` form".to_string()
1572+
} else {
1573+
format!("the default `{default}`")
1574+
};
15621575
warn!(
15631576
"MISE_CYGDRIVE_PREFIX={s:?} is not absolute (must start with `/`); \
1564-
using the default `{DEFAULT}`"
1577+
using {default_desc}"
15651578
);
1566-
DEFAULT.to_string()
1579+
default.to_string()
15671580
}
15681581
}
15691582

@@ -1684,11 +1697,29 @@ mod tests {
16841697
);
16851698
}
16861699

1700+
#[test]
1701+
#[cfg(windows)]
1702+
fn test_maybe_convert_env_for_msys_shell_honors_cygdrive_prefix_for_git_bash() {
1703+
// The cygdrive automount root is configurable in MSYS2 / Git Bash too (not just
1704+
// Cygwin). A Git Bash user with a non-default fstab mount supplies it via
1705+
// MISE_CYGDRIVE_PREFIX; without it the default would (wrongly) be `/c/...`.
1706+
let mut env = env_with_path(r"C:\foo;D:\bar");
1707+
env.insert("MISE_CYGDRIVE_PREFIX".to_string(), "/mnt".to_string());
1708+
let out =
1709+
maybe_convert_env_for_msys_shell(Path::new(r"C:\Program Files\Git\bin\bash.exe"), &env);
1710+
assert_eq!(
1711+
out.get(&*crate::env::PATH_KEY).unwrap(),
1712+
"/mnt/c/foo:/mnt/d/bar"
1713+
);
1714+
}
1715+
16871716
#[test]
16881717
#[cfg(windows)]
16891718
fn test_maybe_convert_env_for_msys_shell_rejects_relative_cygdrive_prefix() {
16901719
// A prefix without a leading slash (e.g. `mnt`) would yield relative PATH
1691-
// entries bash ignores; fall back to the default `/cygdrive` instead.
1720+
// entries bash ignores; fall back to the shell's default instead. For the
1721+
// Cygwin binary used here that default is `/cygdrive` (Git Bash would fall
1722+
// back to an empty prefix, i.e. the `/c/...` form).
16921723
let mut env = env_with_path(r"C:\foo;D:\bar");
16931724
env.insert("MISE_CYGDRIVE_PREFIX".to_string(), "mnt".to_string());
16941725
let out = maybe_convert_env_for_msys_shell(Path::new(r"C:\cygwin64\bin\bash.exe"), &env);

0 commit comments

Comments
 (0)