fix(zsh): prefer builtin cd for symlink-relative paths

This commit is contained in:
lawrence3699 2026-04-19 22:11:59 +10:00
parent 67ca1bc959
commit 694b7dfc81
No known key found for this signature in database
2 changed files with 54 additions and 2 deletions

View File

@ -36,6 +36,10 @@ make_template!(Zsh, "zsh.txt");
#[cfg(feature = "nix-dev")]
#[cfg(test)]
mod tests {
use std::fs;
#[cfg(unix)]
use std::os::unix::fs::{PermissionsExt, symlink};
use askama::Template;
use assert_cmd::Command;
use rstest::rstest;
@ -343,4 +347,44 @@ mod tests {
.stdout("")
.stderr("");
}
#[cfg(unix)]
#[test]
fn zsh_prefers_builtin_cd_for_symlink_relative_paths() {
let tempdir = tempfile::tempdir().unwrap();
let tempdir = tempdir.path();
let bin_dir = tempdir.join("bin");
let query_log = tempdir.join("query.log");
fs::create_dir_all(&bin_dir).unwrap();
fs::create_dir_all(tempdir.join("foo/bar")).unwrap();
symlink("foo/bar", tempdir.join("baz")).unwrap();
let zoxide = bin_dir.join("zoxide");
fs::write(
&zoxide,
format!("#!/bin/sh\nprintf '%s\\n' \"$*\" >> {}\nexit 1\n", query_log.display()),
)
.unwrap();
let mut permissions = fs::metadata(&zoxide).unwrap().permissions();
permissions.set_mode(0o755);
fs::set_permissions(&zoxide, permissions).unwrap();
let opts =
Opts { cmd: Some("z"), hook: InitHook::None, echo: false, resolve_symlinks: false };
let source = Zsh(&opts).render().unwrap();
let script = format!("{source}\ncd -- \"$REPRO/baz\"\nz ../foo\nprintf '%s\\n' \"$PWD\"\n");
let path = std::env::var("PATH").unwrap();
Command::new("zsh")
.env("PATH", format!("{}:{path}", bin_dir.display()))
.env("REPRO", tempdir)
.args(["-e", "-u", "-o", "pipefail", "--no-globalrcs", "--no-rcs", "-c", &script])
.assert()
.success()
.stdout(format!("{}/foo\n", tempdir.display()))
.stderr("");
assert_eq!(fs::read_to_string(query_log).unwrap_or_default(), "");
}
}

View File

@ -88,8 +88,16 @@ function __zoxide_z() {
__zoxide_doctor
if [[ "$#" -eq 0 ]]; then
__zoxide_cd ~
elif [[ "$#" -eq 1 ]] && { [[ -d "$1" ]] || [[ "$1" = '-' ]] || [[ "$1" =~ ^[-+][0-9]+$ ]]; }; then
__zoxide_cd "$1"
elif [[ "$#" -eq 1 ]]; then
if [[ "$1" = '-' ]] || [[ "$1" =~ ^[-+][0-9]+$ ]]; then
__zoxide_cd "$1"
elif [[ -d "$1" ]]; then
__zoxide_cd "$1"
elif ! __zoxide_cd "$1" 2>/dev/null; then
\builtin local result
# shellcheck disable=SC2312
result="$(\command zoxide query --exclude "$(__zoxide_pwd)" -- "$@")" && __zoxide_cd "${result}"
fi
elif [[ "$#" -eq 2 ]] && [[ "$1" = "--" ]]; then
__zoxide_cd "$2"
else