fix: refuse to delete the worktree the user is standing in - #11
Merged
Conversation
Introduces the badge symbol the loader and TUI will use to mark and refuse the worktree the user is standing in, mirroring BadgePrimary.
The loader now emits BadgeCurrent on the linked worktree the user is standing in, so the TUI can both show it and refuse to select it. The primary is suppressed (isMain) since it is already non-deletable and shows [primary]; a redundant [current] would only add noise.
The current worktree was selectable (only the primary was refused) even though the safety model already marks it NotDeletable, so a user could select it, delete it, and trigger a cryptic reload 128 once their CWD vanished. isSelectable now refuses BadgeCurrent too, and the row is dimmed like the primary with [current] shown so the refusal is self-explanatory. The bulk safe-select key is unaffected since it follows Deletable, which is already false for the current worktree.
Delete is a public DeleteFunc that does not track the current worktree, so a caller that handed in the worktree the process is standing in would remove the process's own CWD: os.RemoveAll succeeds, but the post-delete reload then runs git -C <gone-path> and exits 128, surfacing as a cryptic failure even though the deletion itself worked. The guard now captures the resolved CWD once and refuses any target that is the CWD or an ancestor of it (a subdir CWD vanishes with the worktree too), with a distinct errCurrentWorktree failure. This is defense-in-depth for the TUI non-selectability landed in the previous chunk.
Notes the new [current] badge in the badge enumeration and states that the primary and current worktrees are not selectable, matching the behavior landed in the preceding chunks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Deleting the worktree the user is currently standing in produced a cryptic
exit status 128:Fix
Two layers of defense:
TUI — make the current worktree non-selectable. The safety model already treats
IsCurrentasNotDeletable; the TUI now matches that by refusingBadgeCurrentinisSelectable, mirroring the existingBadgePrimaryrefusal. A new[current]badge (suppressed when the primary is also current, to avoid[primary] [current]noise) marks the row and dims it like the primary so the refusal is self-explanatory.Deleter — refuse to remove the CWD worktree.
deleter.Deleteis a publicDeleteFuncthat does not track the current worktree, so a non-TUI caller (or a future one) could still hit the same 128. The guard now captures the symlink-resolved CWD once and refuses any target that is the CWD or an ancestor of it (a subdir CWD vanishes with the worktree too), returning a distincterrCurrentWorktreeOpRemovefailure. This is defense-in-depth for the TUI change.Out of scope
The TUI failure banner still says only
N operation(s) failedwithout per-target reasons. The current-worktree path no longer reaches it, so it's left for a separate issue.