2022-01-30 02:10:00 +02:00
|
|
|
package controllers
|
|
|
|
|
|
|
|
import (
|
2022-02-13 09:04:09 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
2022-01-30 02:10:00 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
2023-02-19 04:11:33 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
2022-01-30 02:10:00 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// splitting this action out into its own file because it's self-contained
|
|
|
|
|
2022-02-13 09:04:09 +02:00
|
|
|
type FilesRemoveController struct {
|
|
|
|
baseController
|
|
|
|
*controllerCommon
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ types.IController = &FilesRemoveController{}
|
|
|
|
|
|
|
|
func NewFilesRemoveController(
|
|
|
|
common *controllerCommon,
|
|
|
|
) *FilesRemoveController {
|
|
|
|
return &FilesRemoveController{
|
|
|
|
baseController: baseController{},
|
|
|
|
controllerCommon: common,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *FilesRemoveController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
|
|
|
bindings := []*types.Binding{
|
|
|
|
{
|
|
|
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
|
|
|
Handler: self.checkSelectedFileNode(self.remove),
|
|
|
|
Description: self.c.Tr.LcViewDiscardOptions,
|
|
|
|
OpensMenu: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return bindings
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *FilesRemoveController) remove(node *filetree.FileNode) error {
|
2022-01-30 02:10:00 +02:00
|
|
|
var menuItems []*types.MenuItem
|
|
|
|
if node.File == nil {
|
|
|
|
menuItems = []*types.MenuItem{
|
|
|
|
{
|
2022-05-08 06:23:32 +02:00
|
|
|
Label: self.c.Tr.LcDiscardAllChanges,
|
2022-01-30 02:10:00 +02:00
|
|
|
OnPress: func() error {
|
|
|
|
self.c.LogAction(self.c.Tr.Actions.DiscardAllChangesInDirectory)
|
|
|
|
if err := self.git.WorkingTree.DiscardAllDirChanges(node); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
|
|
|
},
|
2023-02-19 04:11:33 +02:00
|
|
|
Key: 'x',
|
|
|
|
Tooltip: utils.ResolvePlaceholderString(
|
|
|
|
self.c.Tr.DiscardAllTooltip,
|
|
|
|
map[string]string{
|
|
|
|
"path": node.GetPath(),
|
|
|
|
},
|
|
|
|
),
|
2022-01-30 02:10:00 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if node.GetHasStagedChanges() && node.GetHasUnstagedChanges() {
|
|
|
|
menuItems = append(menuItems, &types.MenuItem{
|
2022-05-08 06:23:32 +02:00
|
|
|
Label: self.c.Tr.LcDiscardUnstagedChanges,
|
2022-01-30 02:10:00 +02:00
|
|
|
OnPress: func() error {
|
|
|
|
self.c.LogAction(self.c.Tr.Actions.DiscardUnstagedChangesInDirectory)
|
|
|
|
if err := self.git.WorkingTree.DiscardUnstagedDirChanges(node); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
|
|
|
},
|
2023-02-19 04:11:33 +02:00
|
|
|
Key: 'u',
|
|
|
|
Tooltip: utils.ResolvePlaceholderString(
|
|
|
|
self.c.Tr.DiscardUnstagedTooltip,
|
|
|
|
map[string]string{
|
|
|
|
"path": node.GetPath(),
|
|
|
|
},
|
|
|
|
),
|
2022-01-30 02:10:00 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
file := node.File
|
|
|
|
|
2022-02-06 06:54:26 +02:00
|
|
|
submodules := self.model.Submodules
|
2022-01-30 02:10:00 +02:00
|
|
|
if file.IsSubmodule(submodules) {
|
|
|
|
submodule := file.SubmoduleConfig(submodules)
|
|
|
|
|
|
|
|
menuItems = []*types.MenuItem{
|
|
|
|
{
|
2022-05-08 06:23:32 +02:00
|
|
|
Label: self.c.Tr.LcSubmoduleStashAndReset,
|
2022-01-30 02:10:00 +02:00
|
|
|
OnPress: func() error {
|
|
|
|
return self.ResetSubmodule(submodule)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
menuItems = []*types.MenuItem{
|
|
|
|
{
|
2022-05-08 06:23:32 +02:00
|
|
|
Label: self.c.Tr.LcDiscardAllChanges,
|
2022-01-30 02:10:00 +02:00
|
|
|
OnPress: func() error {
|
|
|
|
self.c.LogAction(self.c.Tr.Actions.DiscardAllChangesInFile)
|
|
|
|
if err := self.git.WorkingTree.DiscardAllFileChanges(file); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
|
|
|
},
|
2023-02-19 04:11:33 +02:00
|
|
|
Key: 'x',
|
|
|
|
Tooltip: utils.ResolvePlaceholderString(
|
|
|
|
self.c.Tr.DiscardAllTooltip,
|
|
|
|
map[string]string{
|
|
|
|
"path": node.GetPath(),
|
|
|
|
},
|
|
|
|
),
|
2022-01-30 02:10:00 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if file.HasStagedChanges && file.HasUnstagedChanges {
|
|
|
|
menuItems = append(menuItems, &types.MenuItem{
|
2022-05-08 06:23:32 +02:00
|
|
|
Label: self.c.Tr.LcDiscardUnstagedChanges,
|
2022-01-30 02:10:00 +02:00
|
|
|
OnPress: func() error {
|
|
|
|
self.c.LogAction(self.c.Tr.Actions.DiscardAllUnstagedChangesInFile)
|
|
|
|
if err := self.git.WorkingTree.DiscardUnstagedFileChanges(file); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
|
|
|
},
|
2023-02-19 04:11:33 +02:00
|
|
|
Key: 'u',
|
|
|
|
Tooltip: utils.ResolvePlaceholderString(
|
|
|
|
self.c.Tr.DiscardUnstagedTooltip,
|
|
|
|
map[string]string{
|
|
|
|
"path": node.GetPath(),
|
|
|
|
},
|
|
|
|
),
|
2022-01-30 02:10:00 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.c.Menu(types.CreateMenuOptions{Title: node.GetPath(), Items: menuItems})
|
|
|
|
}
|
2022-02-13 09:04:09 +02:00
|
|
|
|
|
|
|
func (self *FilesRemoveController) ResetSubmodule(submodule *models.SubmoduleConfig) error {
|
|
|
|
return self.c.WithWaitingStatus(self.c.Tr.LcResettingSubmoduleStatus, func() error {
|
|
|
|
self.c.LogAction(self.c.Tr.Actions.ResetSubmodule)
|
|
|
|
|
|
|
|
file := self.helpers.WorkingTree.FileForSubmodule(submodule)
|
|
|
|
if file != nil {
|
|
|
|
if err := self.git.WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := self.git.Submodule.Stash(submodule); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
if err := self.git.Submodule.Reset(submodule); err != nil {
|
|
|
|
return self.c.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.SUBMODULES}})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *FilesRemoveController) checkSelectedFileNode(callback func(*filetree.FileNode) error) func() error {
|
|
|
|
return func() error {
|
2022-03-19 00:31:52 +02:00
|
|
|
node := self.context().GetSelected()
|
2022-02-13 09:04:09 +02:00
|
|
|
if node == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *FilesRemoveController) Context() types.Context {
|
|
|
|
return self.context()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *FilesRemoveController) context() *context.WorkingTreeContext {
|
|
|
|
return self.contexts.Files
|
|
|
|
}
|