Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion pkg/gui/controllers/branches_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,24 @@ func (self *BranchesController) delete(branches []*models.Branch) error {
return branch.IsTrackingRemote() && !branch.UpstreamGone
})

menuItems := []*types.MenuItem{}

// If a single branch is checked out by another worktree, offer to remove
// the worktree as the first (default) option in the delete menu.
if len(branches) == 1 {
worktree, ok := git_commands.WorktreeForBranch(branches[0], self.c.Model().Worktrees)
if ok && !worktree.IsCurrent {
branch := branches[0]
menuItems = append(menuItems, &types.MenuItem{
Label: self.c.Tr.RemoveWorktreeAndBranch,
Key: 'w',
OnPress: func() error {
return self.c.Helpers().Worktree.RemoveAndDeleteBranch(worktree, branch, false)
},
})
}
}

localDeleteItem := &types.MenuItem{
Label: lo.Ternary(len(branches) > 1, self.c.Tr.DeleteLocalBranches, self.c.Tr.DeleteLocalBranch),
Key: 'c',
Expand Down Expand Up @@ -599,6 +617,8 @@ func (self *BranchesController) delete(branches []*models.Branch) error {
}
}

menuItems = append(menuItems, localDeleteItem, remoteDeleteItem, deleteBothItem)

var menuTitle string
if len(branches) == 1 {
menuTitle = utils.ResolvePlaceholderString(
Expand All @@ -613,7 +633,7 @@ func (self *BranchesController) delete(branches []*models.Branch) error {

return self.c.Menu(types.CreateMenuOptions{
Title: menuTitle,
Items: []*types.MenuItem{localDeleteItem, remoteDeleteItem, deleteBothItem},
Items: menuItems,
})
}

Expand Down
22 changes: 21 additions & 1 deletion pkg/gui/controllers/helpers/worktree_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ func (self *WorktreeHelper) Switch(worktree *models.Worktree, contextKey types.C
}

func (self *WorktreeHelper) Remove(worktree *models.Worktree, force bool) error {
return self.removeWorktree(worktree, force, nil)
}

func (self *WorktreeHelper) RemoveAndDeleteBranch(worktree *models.Worktree, branch *models.Branch, force bool) error {
return self.removeWorktree(worktree, force, func() error {
self.c.LogAction(self.c.Tr.Actions.DeleteLocalBranch)
if err := self.c.Git().Branch.LocalDelete([]string{branch.Name}, true); err != nil {
return err
}
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
return nil
})
}

func (self *WorktreeHelper) removeWorktree(worktree *models.Worktree, force bool, afterRemove func() error) error {
title := self.c.Tr.RemoveWorktreeTitle
var templateStr string
if force {
Expand Down Expand Up @@ -193,10 +208,15 @@ func (self *WorktreeHelper) Remove(worktree *models.Worktree, force bool) error
}

if !force {
return self.Remove(worktree, true)
return self.removeWorktree(worktree, true, afterRemove)
}
return err
}
if afterRemove != nil {
if err := afterRemove(); err != nil {
return err
}
}
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
return nil
})
Expand Down
2 changes: 2 additions & 0 deletions pkg/i18n/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,7 @@ type TranslationSet struct {
DetachWorktreeTooltip string
Switching string
RemoveWorktree string
RemoveWorktreeAndBranch string
RemoveWorktreeTitle string
DetachWorktree string
DetachingWorktree string
Expand Down Expand Up @@ -1978,6 +1979,7 @@ func EnglishTranslationSet() *TranslationSet {
DetachWorktreeTooltip: "This will run `git checkout --detach` on the worktree so that it stops hogging the branch, but the worktree's working tree will be left alone.",
Switching: "Switching",
RemoveWorktree: "Remove worktree",
RemoveWorktreeAndBranch: "Remove worktree and delete local branch",
RemoveWorktreeTitle: "Remove worktree",
RemoveWorktreePrompt: "Are you sure you want to remove worktree '{{.worktreeName}}'?",
ForceRemoveWorktreePrompt: "'{{.worktreeName}}' contains modified or untracked files, or submodules (or all of these). Are you sure you want to remove it?",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ var DetachWorktreeFromBranch = NewIntegrationTest(NewIntegrationTestArgs{
NavigateToLine(Contains("newbranch")).
Press(keys.Universal.Remove).
Tap(func() {
t.ExpectPopup().
Menu().
t.ExpectPopup().Menu().
Title(Equals("Delete branch 'newbranch'?")).
Select(Contains("Delete local branch")).
Confirm()
Expand Down
16 changes: 4 additions & 12 deletions pkg/integration/tests/worktree/remove_worktree_from_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

var RemoveWorktreeFromBranch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Remove a worktree from the branches view",
Description: "Remove a worktree and delete its branch from the branches view",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
Expand All @@ -28,17 +28,10 @@ var RemoveWorktreeFromBranch = NewIntegrationTest(NewIntegrationTestArgs{
).
NavigateToLine(Contains("newbranch")).
Press(keys.Universal.Remove).
Tap(func() {
t.ExpectPopup().
Menu().
Title(Equals("Delete branch 'newbranch'?")).
Select(Contains("Delete local branch")).
Confirm()
}).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Branch newbranch is checked out by worktree linked-worktree")).
Select(Equals("Remove worktree")).
Title(Equals("Delete branch 'newbranch'?")).
Select(Contains("Remove worktree")).
Confirm()

t.ExpectPopup().Confirmation().
Expand All @@ -52,8 +45,7 @@ var RemoveWorktreeFromBranch = NewIntegrationTest(NewIntegrationTestArgs{
Confirm()
}).
Lines(
Contains("mybranch"),
Contains("newbranch").DoesNotContain("(worktree)").IsSelected(),
Contains("mybranch").IsSelected(),
)

t.Views().Worktrees().
Expand Down
Loading