@@ -110,6 +110,71 @@ printf '\n'
110110SCRIPT
111111}
112112
113+ run_generated_fish_gtrconfig_post_cd_hooks () {
114+ local trust_state=" $1 "
115+ local root repo wt xdg init_file
116+
117+ root=$( mktemp -d)
118+ repo=" $root /repo"
119+ wt=" $root /wt"
120+ xdg=" $root /xdg"
121+ init_file=" $root /gtr.fish"
122+
123+ git init --quiet " $repo "
124+ git -C " $repo " config user.name " Test User"
125+ git -C " $repo " config user.email " test@example.com"
126+ git -C " $repo " commit --allow-empty -m " init" --quiet
127+ git -C " $repo " worktree add --quiet " $wt " -b feature
128+
129+ cat > " $repo /.gtrconfig" << 'CFG '
130+ [hooks]
131+ postCd = pwd > "$WORKTREE_PATH/hook-pwd"
132+ postCd = echo second >> "$WORKTREE_PATH/hook-order"
133+ [defaults]
134+ ai = codex
135+ CFG
136+
137+ cmd_init fish > " $init_file "
138+
139+ if [ " $trust_state " = " trusted" ]; then
140+ (
141+ export XDG_CONFIG_HOME=" $xdg "
142+ # shellcheck disable=SC1091
143+ . " $PROJECT_ROOT /lib/hooks.sh"
144+ _hooks_mark_trusted " $repo /.gtrconfig"
145+ )
146+ fi
147+
148+ XDG_CONFIG_HOME=" $xdg " fish -c '
149+ source "$argv[1]"
150+ set -l wt "$argv[2]"
151+ set -l root "$argv[3]"
152+
153+ cd /
154+ gtr_run_post_cd_hooks "$wt" > "$root/stdout" 2> "$root/stderr"
155+ set -l rc $status
156+
157+ printf "RC=%s\n" "$rc"
158+ printf "PWD=%s\n" "$PWD"
159+ printf "WT=%s\n" "$wt"
160+ if test -f "$wt/hook-pwd"
161+ printf "HOOK_PWD=%s\n" (cat "$wt/hook-pwd")
162+ else
163+ printf "HOOK_PWD=<missing>\n"
164+ end
165+ if test -f "$wt/hook-order"
166+ printf "HOOK_ORDER=%s\n" (paste -sd, "$wt/hook-order")
167+ else
168+ printf "HOOK_ORDER=<missing>\n"
169+ end
170+ printf "STDERR=%s\n" (cat "$root/stderr")
171+ ' -- " $init_file " " $wt " " $root "
172+ local rc=$?
173+
174+ rm -rf " $root "
175+ return " $rc "
176+ }
177+
113178require_runtime_shell () {
114179 local shell_name=" $1 "
115180
@@ -320,6 +385,41 @@ require_runtime_shell() {
320385 [ " $output " = " /tmp/repo" ]
321386}
322387
388+ @test " fish generated postCd skips untrusted gtrconfig hooks without changing cwd" {
389+ require_runtime_shell fish
390+
391+ run run_generated_fish_gtrconfig_post_cd_hooks untrusted
392+
393+ [ " $status " -eq 0 ]
394+ [[ " $output " == * " RC=0" * ]]
395+ [[ " $output " == * " HOOK_PWD=<missing>" * ]]
396+ [[ " $output " == * " HOOK_ORDER=<missing>" * ]]
397+ [[ " $output " == * " STDERR=gtr: Untrusted .gtrconfig hooks skipped" * ]]
398+
399+ local pwd_line wt_line
400+ pwd_line=$( printf ' %s\n' " $output " | sed -n ' s/^PWD=//p' )
401+ wt_line=$( printf ' %s\n' " $output " | sed -n ' s/^WT=//p' )
402+ [ " $pwd_line " = " $wt_line " ]
403+ }
404+
405+ @test " fish generated postCd trusts multi-entry gtrconfig hooks without changing cwd" {
406+ require_runtime_shell fish
407+
408+ run run_generated_fish_gtrconfig_post_cd_hooks trusted
409+
410+ [ " $status " -eq 0 ]
411+ [[ " $output " == * " RC=0" * ]]
412+ [[ " $output " == * " HOOK_ORDER=second" * ]]
413+ [[ " $output " == * " STDERR=" * ]]
414+
415+ local pwd_line wt_line hook_pwd_line
416+ pwd_line=$( printf ' %s\n' " $output " | sed -n ' s/^PWD=//p' )
417+ wt_line=$( printf ' %s\n' " $output " | sed -n ' s/^WT=//p' )
418+ hook_pwd_line=$( printf ' %s\n' " $output " | sed -n ' s/^HOOK_PWD=//p' )
419+ [ " $pwd_line " = " $wt_line " ]
420+ [ " $hook_pwd_line " = " $wt_line " ]
421+ }
422+
323423# ── new --cd wrapper support ────────────────────────────────────────────────
324424
325425@test " bash output intercepts new --cd and strips flag before delegating" {
0 commit comments