Repository navigation
refactor(commands): unify hook template-variable assembly into TemplateVars - #2470
Conversation
…ateVars` Switch and merge sites previously each rebuilt `Vec<(&str, &str)>` of hook template variables ad hoc, with subtly different rules and bespoke borrow gymnastics (notably `pr_number_buf: &mut String`). The deprecated `worktree` alias for `worktree_path` was duplicated at three sites. Introduce `commands::template_vars::TemplateVars` as the canonical builder and route all 4 switch sites + 2 merge sites + the picker through it. The struct owns its strings, encodes the deprecated `worktree` alias once in `as_extra_vars()`, and offers a `for_post_switch` constructor that reads directly off `SwitchResult` / `SwitchBranchInfo`. Side effect: post-switch hooks fired from the picker now receive `target` / `target_worktree_path` like hooks fired from `wt switch foo` — closing a pre-existing asymmetry where interactive switching exposed strictly fewer template variables than the non-interactive path. Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # src/commands/merge.rs
worktrunk-bot
left a comment
There was a problem hiding this comment.
Refactor cleanly consolidates the switch/merge template-var assembly. The owned-strings approach removes the pr_number_buf borrow gymnastics and the for_post_switch constructor handles all three SwitchResult variants in one place. Tests cover the directional-pair / Active-override / pr / detached cases. The picker behavior change (now emits target / target_worktree_path) is the right direction and is called out in the PR body.
A few observations:
-
src/commands/worktree/switch.rs:913still referencesswitch_extra_vars("…SwitchResult — switch_extra_vars then forwards it…"), but that function is removed by this PR. The comment lives just outside the diff hunks; happy to push a one-line follow-up if useful, otherwise it's a trivial inline edit. -
Subtle behavior shift in
merge.rs: whenenv.worktree_path.file_name()isNoneor non-UTF-8, the old code emittedworktree_name = "unknown"(unwrap_or("unknown"));with_active_worktreenow omits the variable instead. In practiceenv.worktree_pathalways has a filename, so this is a corner case — but it means a{{ worktree_name }}template would shift from rendering"unknown"to failing as undefined. New behavior is arguably more honest; flagging since it isn't called out in the description. -
PostRemoveContext(src/commands/worktree/hooks.rs:42-106) is a sibling implementation that overlaps meaningfully withTemplateVars(worktree_path + deprecatedworktreealias, worktree_name with theunwrap_or("unknown")fallback, commit/short_commit). The new module's docstring positions itself as canonical and the PR's "out of scope" calls outhook_commands.rsbut not this one — worth noting whether foldingPostRemoveContextintoTemplateVarsis on the same follow-up runway. -
The
lintjob is failing oncargo fmtfor the post-mergeannouncer.registercall (suggestion below).
|
Thanks for the review. Addressed in the follow-up commit:
|
- `cargo fmt` applied to the post-merge `announcer.register` call.
- Comment in `worktree/switch.rs` referencing the removed
`switch_extra_vars` updated to point to `TemplateVars::for_post_switch`.
- Restored the `unwrap_or("unknown")` fallback for `worktree_name` inside
`TemplateVars::with_active_worktree` (regression test added). Pre-refactor
merge.rs always emitted `worktree_name`; the previous version of this PR
silently dropped it for paths without a UTF-8 filename — defensive parity
matters more than honesty here.
Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Switch and merge sites previously each rebuilt
Vec<(&str, &str)>of hook template variables ad hoc, with subtly different rules and bespoke borrow gymnastics (notablypr_number_buf: &mut String). The deprecatedworktreealias forworktree_pathwas duplicated at three sites.This PR introduces
commands::template_vars::TemplateVarsas the canonical builder and routes all 4 switch sites + 2 merge sites + the picker through it. The struct owns its strings, encodes the deprecatedworktreealias once inas_extra_vars(), and offers afor_post_switchconstructor that reads directly offSwitchResult/SwitchBranchInfo.Behavior change
Post-switch hooks fired from the picker now receive
target/target_worktree_pathlike hooks fired fromwt switch foo— closing a pre-existing asymmetry where interactive switching exposed strictly fewer template variables than the non-interactive path. There's no design reason interactive switching should hand hooks less context; this looks like an oversight in the original picker integration.Where to start reviewing
src/commands/template_vars.rs— the new module (~170 lines of production code, 11 unit tests).src/commands/handle_switch.rs— 3 of the migrated sites; biggest reduction (-73 net lines). Theswitch_extra_varshelper with itspr_number_bufborrow hack is gone.src/commands/merge.rs— the post-mergefeature_varscapture-before-removal pattern, which was the strongest motivator for owning strings rather than borrowing.src/commands/picker/mod.rs— small but the only behavior-changing site.Out of scope
hook_commands.rs::build_manual_hook_extra_varsis being heavily refactored onhook-dispatch-unify; that branch will land first. After both merge, applyingTemplateVarsthere is a trivial follow-up.