Skip to content

postCreate hooks silently stop if a hook reads from stdin #164

Description

@acevif

Bug

If a postCreate hook runs a command that reads from stdin, all subsequent hooks are silently skipped.

Root cause

run_hooks iterates over hooks using a heredoc:

while IFS= read -r hook; do
  ( eval "$hook" )   # subshell inherits stdin = the heredoc
done <<EOF
$hooks
EOF

Each hook's subshell inherits the parent's stdin, which is the heredoc itself. A command that reads stdin drains the remaining lines, so subsequent read -r hook calls get nothing and the loop exits early.

Minimal reproduction

.gtrconfig:

[hooks]
    postCreate = "echo 'hook 1: before stdin read'"
    postCreate = "cat"
    postCreate = "echo 'hook 3: this should run but does not'"

Output of gtr new test-branch:

[OK] Hook 1: echo 'hook 1: before stdin read'
hook 1: before stdin read
[OK] Hook 1 completed successfully
[OK] Hook 2: cat
echo 'hook 3: this should run but does not'
[OK] Hook 2 completed successfully

[OK] Worktree created: ...

Hook 3 never runs. Its command text is visibly consumed and printed by cat.

Suggested fix

https://github.com/coderabbitai/git-worktree-runner/blob/v2.6.0/lib/hooks.sh#L35-L44

Before:

    # Run hook in subshell with properly quoted environment exports
    if (
      # Export each KEY=VALUE exactly as passed, safely quoted
      for kv in "${envs[@]}"; do
        # shellcheck disable=SC2163
        export "$kv"
      done
      # Execute the hook
      eval "$hook"
    ); then

After:

    # Run hook in subshell with properly quoted environment exports
    if (
      # Export each KEY=VALUE exactly as passed, safely quoted
      for kv in "${envs[@]}"; do
        # shellcheck disable=SC2163
        export "$kv"
      done
      # Execute the hook
      eval "$hook"
    ) </dev/null; then

Workaround

Add </dev/null to any hook that may read from stdin:

[hooks]
    postCreate = "your-command </dev/null"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions