Move the menu for removing a worktree to BranchesHelper

The files panel is going to show it too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-15 20:51:34 +02:00
co-authored by Claude Opus 5.5
parent 0380dd4851
commit 875641557b
2 changed files with 61 additions and 57 deletions
@@ -231,6 +231,66 @@ func (self *BranchesHelper) promptWorktreeBranchDelete(
})
}
// RemoveWorktreeMenu shows the menu for removing a worktree, optionally along
// with the branch that it has checked out.
func (self *BranchesHelper) RemoveWorktreeMenu(worktree *models.Worktree) error {
if worktree.IsMain {
return errors.New(self.c.Tr.CantDeleteMainWorktree)
}
if worktree.IsCurrent {
return errors.New(self.c.Tr.CantDeleteCurrentWorktree)
}
removeWorktreeItem := &types.MenuItem{
Label: self.c.Tr.RemoveWorktree,
Keys: menuKey('w'),
OnPress: func() error {
return self.worktreeHelper.Remove(worktree, nil)
},
}
branch, branchFound := lo.Find(self.c.Model().Branches, func(branch *models.Branch) bool {
return branch.Name == worktree.Branch
})
// A worktree with a detached HEAD has no branch to delete
detachedReason := &types.DisabledReason{Text: self.c.Tr.WorktreeNotCheckedOutOnBranch}
removeWorktreeAndBranchItem := &types.MenuItem{
Label: self.c.Tr.RemoveWorktreeAndDeleteBranch,
Keys: menuKey('b'),
OnPress: func() error {
return self.RemoveWorktreeAndDeleteBranch(worktree, branch)
},
}
if !branchFound {
removeWorktreeAndBranchItem.DisabledReason = detachedReason
}
removeWorktreeAndBothBranchesItem := &types.MenuItem{
Label: self.c.Tr.RemoveWorktreeAndDeleteBothBranches,
Keys: menuKey('r'),
OnPress: func() error {
return self.RemoveWorktreeAndDeleteBothBranches(worktree, branch)
},
}
if !branchFound {
removeWorktreeAndBothBranchesItem.DisabledReason = detachedReason
} else if !branch.IsTrackingRemote() || branch.UpstreamGone {
removeWorktreeAndBothBranchesItem.DisabledReason = &types.DisabledReason{
Text: self.c.Tr.UpstreamNotSetError,
}
}
return self.c.Menu(types.CreateMenuOptions{
Title: utils.ResolvePlaceholderString(
self.c.Tr.RemoveWorktreeMenuTitle,
map[string]string{"worktreeName": worktree.Name},
),
Items: []*types.MenuItem{removeWorktreeItem, removeWorktreeAndBranchItem, removeWorktreeAndBothBranchesItem},
})
}
// RemoveWorktreeAndDeleteBranch removes the worktree and deletes the local branch
// it has checked out, force-warning first if the branch isn't fully merged. It's
// the worktrees-panel counterpart to deleting a worktree-checked-out branch from
+1 -57
View File
@@ -1,7 +1,6 @@
package controllers
import (
"errors"
"fmt"
"strings"
"text/tabwriter"
@@ -11,7 +10,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
type WorktreesController struct {
@@ -123,61 +121,7 @@ func (self *WorktreesController) add() error {
}
func (self *WorktreesController) remove(worktree *models.Worktree) error {
if worktree.IsMain {
return errors.New(self.c.Tr.CantDeleteMainWorktree)
}
if worktree.IsCurrent {
return errors.New(self.c.Tr.CantDeleteCurrentWorktree)
}
removeWorktreeItem := &types.MenuItem{
Label: self.c.Tr.RemoveWorktree,
Keys: menuKey('w'),
OnPress: func() error {
return self.c.Helpers().Worktree.Remove(worktree, nil)
},
}
branch, branchFound := lo.Find(self.c.Model().Branches, func(branch *models.Branch) bool {
return branch.Name == worktree.Branch
})
// A worktree with a detached HEAD has no branch to delete
detachedReason := &types.DisabledReason{Text: self.c.Tr.WorktreeNotCheckedOutOnBranch}
removeWorktreeAndBranchItem := &types.MenuItem{
Label: self.c.Tr.RemoveWorktreeAndDeleteBranch,
Keys: menuKey('b'),
OnPress: func() error {
return self.c.Helpers().BranchesHelper.RemoveWorktreeAndDeleteBranch(worktree, branch)
},
}
if !branchFound {
removeWorktreeAndBranchItem.DisabledReason = detachedReason
}
removeWorktreeAndBothBranchesItem := &types.MenuItem{
Label: self.c.Tr.RemoveWorktreeAndDeleteBothBranches,
Keys: menuKey('r'),
OnPress: func() error {
return self.c.Helpers().BranchesHelper.RemoveWorktreeAndDeleteBothBranches(worktree, branch)
},
}
if !branchFound {
removeWorktreeAndBothBranchesItem.DisabledReason = detachedReason
} else if !branch.IsTrackingRemote() || branch.UpstreamGone {
removeWorktreeAndBothBranchesItem.DisabledReason = &types.DisabledReason{
Text: self.c.Tr.UpstreamNotSetError,
}
}
return self.c.Menu(types.CreateMenuOptions{
Title: utils.ResolvePlaceholderString(
self.c.Tr.RemoveWorktreeMenuTitle,
map[string]string{"worktreeName": worktree.Name},
),
Items: []*types.MenuItem{removeWorktreeItem, removeWorktreeAndBranchItem, removeWorktreeAndBothBranchesItem},
})
return self.c.Helpers().BranchesHelper.RemoveWorktreeMenu(worktree)
}
func (self *WorktreesController) GetOnDoubleClick() func() error {