diff --git a/lib/commands/init.sh b/lib/commands/init.sh index a06f223..16b7109 100644 --- a/lib/commands/init.sh +++ b/lib/commands/init.sh @@ -126,7 +126,7 @@ __FUNC___run_post_cd_hooks() { [ -z "$_gtr_hook" ] && continue case "$_gtr_seen" in *"|$_gtr_hook|"*) continue ;; esac _gtr_seen="$_gtr_seen|$_gtr_hook|" - eval "$_gtr_hook" || echo "__FUNC__: postCd hook failed: $_gtr_hook" >&2 + eval "$_gtr_hook" &2 done <<< "$_gtr_hooks" unset WORKTREE_PATH REPO_ROOT BRANCH fi @@ -303,7 +303,7 @@ __FUNC___run_post_cd_hooks() { [ -z "$_gtr_hook" ] && continue case "$_gtr_seen" in *"|$_gtr_hook|"*) continue ;; esac _gtr_seen="$_gtr_seen|$_gtr_hook|" - eval "$_gtr_hook" || echo "__FUNC__: postCd hook failed: $_gtr_hook" >&2 + eval "$_gtr_hook" &2 done <<< "$_gtr_hooks" unset WORKTREE_PATH REPO_ROOT BRANCH fi diff --git a/lib/hooks.sh b/lib/hooks.sh index 75184d8..9a867dd 100644 --- a/lib/hooks.sh +++ b/lib/hooks.sh @@ -41,7 +41,7 @@ run_hooks() { done # Execute the hook eval "$hook" - ); then + ) > "$REPO_ROOT/order"' + git config --add gtr.hook.postCreate 'cat' + git config --add gtr.hook.postCreate 'echo third >> "$REPO_ROOT/order"' + run_hooks postCreate REPO_ROOT="$TEST_REPO" + [ "$(head -1 "$TEST_REPO/order")" = "first" ] + [ "$(tail -1 "$TEST_REPO/order")" = "third" ] +} + +@test "run_hooks continues after hook that reads stdin (preRemove)" { + git config --add gtr.hook.preRemove 'echo first >> "$REPO_ROOT/order"' + git config --add gtr.hook.preRemove 'cat' + git config --add gtr.hook.preRemove 'echo third >> "$REPO_ROOT/order"' + run_hooks preRemove REPO_ROOT="$TEST_REPO" + [ "$(head -1 "$TEST_REPO/order")" = "first" ] + [ "$(tail -1 "$TEST_REPO/order")" = "third" ] +} + +@test "run_hooks continues after hook that reads stdin (postRemove)" { + git config --add gtr.hook.postRemove 'echo first >> "$REPO_ROOT/order"' + git config --add gtr.hook.postRemove 'cat' + git config --add gtr.hook.postRemove 'echo third >> "$REPO_ROOT/order"' + run_hooks postRemove REPO_ROOT="$TEST_REPO" + [ "$(head -1 "$TEST_REPO/order")" = "first" ] + [ "$(tail -1 "$TEST_REPO/order")" = "third" ] +} + @test "run_hooks REPO_ROOT and BRANCH env vars available" { git config --add gtr.hook.postCreate 'echo "$REPO_ROOT|$BRANCH" > "$REPO_ROOT/vars"' run_hooks postCreate REPO_ROOT="$TEST_REPO" BRANCH="test-branch" @@ -134,3 +161,12 @@ teardown() { (cd "$TEST_REPO" && run_hooks_export postCd REPO_ROOT="$TEST_REPO") [ -z "${LEAK_TEST:-}" ] } + +@test "run_hooks_export continues after hook that reads stdin (postCd)" { + git config --add gtr.hook.postCd 'echo first >> "$REPO_ROOT/order"' + git config --add gtr.hook.postCd 'cat' + git config --add gtr.hook.postCd 'echo third >> "$REPO_ROOT/order"' + (cd "$TEST_REPO" && run_hooks_export postCd REPO_ROOT="$TEST_REPO") + [ "$(head -1 "$TEST_REPO/order")" = "first" ] + [ "$(tail -1 "$TEST_REPO/order")" = "third" ] +} diff --git a/tests/init.bats b/tests/init.bats index 1bf4726..70339df 100644 --- a/tests/init.bats +++ b/tests/init.bats @@ -70,6 +70,52 @@ printf 'REPLY=%s\n' "${COMPREPLY[*]}" BASH } +run_generated_post_cd_hooks() { + local shell_name="$1" + + "$shell_name" -s -- "$PROJECT_ROOT" "$shell_name" <<'SCRIPT' +PROJECT_ROOT="$1" +shell_name="$2" + +log_info() { :; } +log_warn() { :; } +log_error() { :; } +show_command_help() { :; } +compdef() { :; } + +# shellcheck disable=SC1090 +. "$PROJECT_ROOT/lib/commands/init.sh" + +repo=$(mktemp -d) +cleanup() { + rm -rf "$repo" +} +trap cleanup EXIT + +git -C "$repo" init --quiet +git -C "$repo" config user.name "Test User" +git -C "$repo" config user.email "test@example.com" +git -C "$repo" commit --allow-empty -m "init" --quiet + +git -C "$repo" config --add gtr.hook.postCd 'echo first >> "$REPO_ROOT/order"' +git -C "$repo" config --add gtr.hook.postCd 'cat' +git -C "$repo" config --add gtr.hook.postCd 'echo third >> "$REPO_ROOT/order"' + +eval "$(cmd_init "$shell_name")" +gtr_run_post_cd_hooks "$repo" + +printf 'ORDER=' +paste -sd, "$repo/order" +printf '\n' +SCRIPT +} + +require_runtime_shell() { + local shell_name="$1" + + command -v "$shell_name" >/dev/null 2>&1 || skip "$shell_name is not installed" +} + # ── Default function name ──────────────────────────────────────────────────── @test "bash output defines gtr() function by default" { @@ -253,6 +299,22 @@ BASH [[ "$output" == *'could not determine new directory for --cd'* ]] } +@test "bash generated postCd hooks continue after stdin read" { + require_runtime_shell bash + run run_generated_post_cd_hooks bash + + [ "$status" -eq 0 ] + [ "$output" = "ORDER=first,third" ] +} + +@test "zsh generated postCd hooks continue after stdin read" { + require_runtime_shell zsh + run run_generated_post_cd_hooks zsh + + [ "$status" -eq 0 ] + [ "$output" = "ORDER=first,third" ] +} + @test "fish output uses worktree diff to locate the new directory for --cd" { run cmd_init fish [ "$status" -eq 0 ]