Skip to content

Commit bd727ff

Browse files
neumieclaude
andcommitted
fix(worktree): abort close when before_remove hook fails to spawn
Show an error in the dialog instead of silently proceeding. The hook is configured for a reason — if it can't run, the close should stop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2eddd12 commit bd727ff

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

crates/okena-views-git/src/close_worktree_dialog.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,10 +434,6 @@ impl CloseWorktreeDialog {
434434
let has_before_remove_hook =
435435
project_hooks.worktree.before_remove.is_some() || global_hooks.worktree.before_remove.is_some();
436436

437-
// Track whether the deferred (PTY) path succeeded so we can fall
438-
// through to immediate removal if the hook terminal failed to spawn.
439-
let mut deferred = false;
440-
441437
if has_before_remove_hook && runner.is_some() {
442438
// Fire hook as visible PTY terminal and defer removal
443439
let ok = cx.update(|cx| {
@@ -478,14 +474,19 @@ impl CloseWorktreeDialog {
478474
});
479475
true
480476
} else {
481-
log::warn!("before_worktree_remove hook terminal failed to spawn, falling through to immediate removal");
477+
// Hook terminal failed to spawn — abort, don't remove
478+
let _ = this.update(cx, |this, cx| {
479+
this.error_message = Some("before_worktree_remove hook failed to start".into());
480+
this.processing = ProcessingState::Idle;
481+
cx.notify();
482+
});
482483
false
483484
}
484485
});
485-
deferred = ok;
486-
}
487-
488-
if !deferred {
486+
if !ok {
487+
return;
488+
}
489+
} else {
489490
// No hook or no runner — run headlessly then remove immediately
490491
if has_before_remove_hook {
491492
let before_remove_result = smol::unblock({

0 commit comments

Comments
 (0)