diff --git a/.changeset/posix-use-on-cd-tests.md b/.changeset/posix-use-on-cd-tests.md new file mode 100644 index 000000000..15299b369 --- /dev/null +++ b/.changeset/posix-use-on-cd-tests.md @@ -0,0 +1,5 @@ +--- +"fnm": patch +--- + +Make bash `--use-on-cd` hook use POSIX `[ -f ]` tests so it works under dash/sh diff --git a/src/shell/bash.rs b/src/shell/bash.rs index 667c96b8b..9a1eff236 100644 --- a/src/shell/bash.rs +++ b/src/shell/bash.rs @@ -26,15 +26,17 @@ impl Shell for Bash { } fn use_on_cd(&self, config: &crate::config::FnmConfig) -> anyhow::Result { + // Use POSIX `[ ]` tests (not bash `[[ ]]`) so the hook still works when + // eval'd under dash/sh — see https://github.com/Schniz/fnm/issues/1591 let version_file_exists_condition = if config.resolve_engines() { - "-f .node-version || -f .nvmrc || -f package.json" + "[ -f .node-version ] || [ -f .nvmrc ] || [ -f package.json ]" } else { - "-f .node-version || -f .nvmrc" + "[ -f .node-version ] || [ -f .nvmrc ]" }; let autoload_hook = match config.version_file_strategy() { VersionFileStrategy::Local => formatdoc!( r" - if [[ {version_file_exists_condition} ]]; then + if {version_file_exists_condition}; then fnm use --silent-if-unchanged fi ", @@ -59,3 +61,21 @@ impl Shell for Bash { )) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn use_on_cd_emits_posix_file_tests() { + let output = Bash.use_on_cd(&crate::config::FnmConfig::default()).unwrap(); + assert!( + output.contains("[ -f .node-version ] || [ -f .nvmrc ]"), + "expected POSIX [ -f ] tests, got:\n{output}" + ); + assert!( + !output.contains("[["), + "bash use-on-cd hook must not emit [[ for dash/sh compatibility" + ); + } +}