Skip to content

Unresolved <global> hook placeholder is executed as a shell command, breaking add and remove for users without that global hook #224

Description

@quigor

Summary

When a project's .workmux.yaml lists "<global>" in a hook list and the
machine's ~/.config/workmux/config.yaml has no corresponding key, the
placeholder is not resolved. It is handed to the shell verbatim, where bash
parses <global> as an input redirection and fails:

bash: -c: line 1: `<global>'

The failing hook then takes down the surrounding operation.

This matters because the two halves of <global> live in different places by
design: .workmux.yaml is committed and shared across a team, while
~/.config/workmux/config.yaml is per-machine. A repository that adopts the
documented - "<global>" pattern breaks workmux add for every contributor who
has not independently defined that same global hook — and the error names a
token from a file they may never have edited.

Reproduction

The global config path is derived from $HOME, so pointing HOME at an empty
directory stands in for a machine that has never defined a global hook. Nothing
outside the temporary directory is touched.

export HOME=$(mktemp -d)
mkdir -p "$HOME/repro" && cd "$HOME/repro" && git init -q -b main .
printf 'post_create:\n  - "<global>"\n  - echo project-hook\n' > .workmux.yaml
git add -A && git -c user.email=t@t -c user.name=t commit -qm init

workmux add -C probe

Actual:

bash: -c: line 1: syntax error near unexpected token `newline'
bash: -c: line 1: `<global>'
Error: Failed to create worktree environment for branch 'probe'

Caused by:
    0: Failed to run post-create command: '<global>'
    1: Shell command failed with exit code 2: <global>

The worktree is left unusable.

The same placeholder in pre_remove is worse — the failing hook aborts the
removal and leaves the worktree on disk:

export HOME=$(mktemp -d)
mkdir -p "$HOME/repro" && cd "$HOME/repro" && git init -q -b main .
printf 'pre_remove:\n  - "<global>"\n  - echo project-hook\n' > .workmux.yaml
git add -A && git -c user.email=t@t -c user.name=t commit -qm init

workmux add -C probe && workmux remove -f probe
Running pre-remove commands...
bash: -c: line 1: syntax error near unexpected token `newline'
bash: -c: line 1: `<global>'

Failed to remove 1 worktree(s):
  - probe: Failed to remove worktree
Error: Some worktrees could not be removed

$HOME/repro__worktrees/probe is still present afterwards. On a real machine,
recovering needs either a global hook definition or an edit to a tracked file.

Expected

<global> with nothing to inherit should resolve to an empty list and be
dropped, leaving the remaining project hooks to run. It should never reach a
shell as a literal argument.

Resolution appears to work correctly whenever the global key is present: with
a global pre_remove defined, a project list of ["<global>", "…"] logs
cleanup:running pre-remove hooks … count=2 and both hooks run. Only the
missing-key path is affected.

Environment

  • Reproduced on v0.1.236 (workmux-linux-amd64.tar.gz release binary) and
    on v0.1.234.
  • Linux, bash as the hook shell.

Minor, related

workmux config reference documents <global> under post_create
("Use <global> to inherit from global config") and under pre_merge, but
not under pre_remove, even though it is resolved there too. Worth adding for
symmetry.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions