mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Let worktree removal/detach chain follow-up work
Split the actual worktree removal out of the confirmation in Remove into a non-confirming helper, and give both Remove and Detach an optional `then` continuation that runs after a successful removal in place of the default refresh. Upcoming flows need to delete the worktree's branch once the worktree is out of the way; threading a continuation through (rather than the caller firing branch deletion independently) keeps it ordered after the git command that actually frees the branch. No behavior change yet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d6016d6286
commit
9a8244110f
|
|
@ -184,13 +184,13 @@ func (self *BranchesHelper) promptWorktreeBranchDelete(selectedBranch *models.Br
|
|||
Label: self.c.Tr.DetachWorktree,
|
||||
Tooltip: self.c.Tr.DetachWorktreeTooltip,
|
||||
OnPress: func() error {
|
||||
return self.worktreeHelper.Detach(worktree)
|
||||
return self.worktreeHelper.Detach(worktree, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.RemoveWorktree,
|
||||
OnPress: func() error {
|
||||
return self.worktreeHelper.Remove(worktree, false)
|
||||
return self.worktreeHelper.Remove(worktree)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -119,56 +119,82 @@ func (self *WorktreeHelper) Switch(worktree *models.Worktree, contextKey types.C
|
|||
return self.reposHelper.DispatchSwitchTo(worktree.Path, self.c.Tr.ErrWorktreeMovedOrRemoved, contextKey)
|
||||
}
|
||||
|
||||
func (self *WorktreeHelper) Remove(worktree *models.Worktree, force bool) error {
|
||||
title := self.c.Tr.RemoveWorktreeTitle
|
||||
var templateStr string
|
||||
if force {
|
||||
templateStr = self.c.Tr.ForceRemoveWorktreePrompt
|
||||
} else {
|
||||
templateStr = self.c.Tr.RemoveWorktreePrompt
|
||||
}
|
||||
func (self *WorktreeHelper) Remove(worktree *models.Worktree) error {
|
||||
message := utils.ResolvePlaceholderString(
|
||||
templateStr,
|
||||
self.c.Tr.RemoveWorktreePrompt,
|
||||
map[string]string{
|
||||
"worktreeName": worktree.Name,
|
||||
},
|
||||
)
|
||||
|
||||
self.c.Confirm(types.ConfirmOpts{
|
||||
Title: title,
|
||||
Title: self.c.Tr.RemoveWorktreeTitle,
|
||||
Prompt: message,
|
||||
HandleConfirm: func() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RemovingWorktree, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.RemoveWorktree)
|
||||
if err := self.c.Git().Worktree.Delete(worktree.Path, force); err != nil {
|
||||
errMessage := err.Error()
|
||||
if !strings.Contains(errMessage, "--force") &&
|
||||
!strings.Contains(errMessage, "fatal: working trees containing submodules cannot be moved or removed") {
|
||||
return err
|
||||
}
|
||||
|
||||
if !force {
|
||||
return self.Remove(worktree, true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
|
||||
return nil
|
||||
})
|
||||
return self.remove(worktree, false, nil)
|
||||
},
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *WorktreeHelper) Detach(worktree *models.Worktree) error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.DetachingWorktree, func(gocui.Task) error {
|
||||
// remove deletes the worktree without confirming first; callers must have done
|
||||
// so (or shown a menu) already. If git refuses because the worktree is dirty or
|
||||
// contains submodules, we ask for confirmation and retry with --force. When then
|
||||
// is non-nil it runs in place of the default refresh after a successful removal,
|
||||
// letting callers chain further work such as deleting the worktree's branch.
|
||||
func (self *WorktreeHelper) remove(worktree *models.Worktree, force bool, then func(gocui.Task) error) error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RemovingWorktree, func(task gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.RemoveWorktree)
|
||||
if err := self.c.Git().Worktree.Delete(worktree.Path, force); err != nil {
|
||||
errMessage := err.Error()
|
||||
if !strings.Contains(errMessage, "--force") &&
|
||||
!strings.Contains(errMessage, "fatal: working trees containing submodules cannot be moved or removed") {
|
||||
return err
|
||||
}
|
||||
|
||||
if force {
|
||||
return err
|
||||
}
|
||||
|
||||
message := utils.ResolvePlaceholderString(
|
||||
self.c.Tr.ForceRemoveWorktreePrompt,
|
||||
map[string]string{
|
||||
"worktreeName": worktree.Name,
|
||||
},
|
||||
)
|
||||
self.c.Confirm(types.ConfirmOpts{
|
||||
Title: self.c.Tr.RemoveWorktreeTitle,
|
||||
Prompt: message,
|
||||
HandleConfirm: func() error {
|
||||
return self.remove(worktree, true, then)
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
if then != nil {
|
||||
return then(task)
|
||||
}
|
||||
|
||||
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (self *WorktreeHelper) Detach(worktree *models.Worktree, then func(gocui.Task) error) error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.DetachingWorktree, func(task gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.RemovingWorktree)
|
||||
|
||||
err := self.c.Git().Worktree.Detach(worktree.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if then != nil {
|
||||
return then(task)
|
||||
}
|
||||
|
||||
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
|
||||
return nil
|
||||
})
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ func (self *WorktreesController) remove(worktree *models.Worktree) error {
|
|||
return errors.New(self.c.Tr.CantDeleteCurrentWorktree)
|
||||
}
|
||||
|
||||
return self.c.Helpers().Worktree.Remove(worktree, false)
|
||||
return self.c.Helpers().Worktree.Remove(worktree)
|
||||
}
|
||||
|
||||
func (self *WorktreesController) GetOnDoubleClick() func() error {
|
||||
|
|
|
|||
Loading…
Reference in a new issue