1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-12 11:15:00 +02:00
lazygit/pkg/gui/commit_files_panel.go

256 lines
7.1 KiB
Go

package gui
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
)
const (
// these are the possible ref types for refs that you can view files of.
// for local commits, we're allowed to build a patch and do things involving rebasing
// with that patch
REF_TYPE_LOCAL_COMMIT = iota
// for other kinds of commits like reflog commits, we can't do anything rebasey
REF_TYPE_OTHER_COMMIT
// for stash entries we can't do anything rebasey, and the command for
// obtaining the files is slightly different
REF_TYPE_STASH
)
func (gui *Gui) getSelectedCommitFile() *commands.CommitFile {
selectedLine := gui.State.Panels.CommitFiles.SelectedLineIdx
if selectedLine == -1 {
return nil
}
return gui.State.CommitFiles[selectedLine]
}
func (gui *Gui) handleCommitFileSelect() error {
gui.handleEscapeLineByLinePanel()
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
// TODO: consider making it so that we can also render strings to our own view through some common interface, or just render this to the main view for consistency
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
cmd := gui.OSCommand.ExecutableFromString(
gui.GitCommand.ShowCommitFileCmdStr(commitFile.Parent, commitFile.Name, false),
)
task := gui.createRunPtyTask(cmd)
return gui.refreshMain(refreshMainOpts{
main: &viewUpdateOpts{
title: "Patch",
task: task,
},
secondary: gui.secondaryPatchPanelUpdateOpts(),
})
}
func (gui *Gui) handleCheckoutCommitFile(g *gocui.Gui, v *gocui.View) error {
file := gui.State.CommitFiles[gui.State.Panels.CommitFiles.SelectedLineIdx]
if err := gui.GitCommand.CheckoutFile(file.Parent, file.Name); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}
func (gui *Gui) handleDiscardOldFileChange(g *gocui.Gui, v *gocui.View) error {
if ok, err := gui.validateNormalWorkingTreeState(); !ok {
return err
}
fileName := gui.State.CommitFiles[gui.State.Panels.CommitFiles.SelectedLineIdx].Name
return gui.ask(askOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DiscardFileChangesTitle"),
prompt: gui.Tr.SLocalize("DiscardFileChangesPrompt"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("RebasingStatus"), func() error {
if err := gui.GitCommand.DiscardOldFileChanges(gui.State.Commits, gui.State.Panels.Commits.SelectedLineIdx, fileName); err != nil {
if err := gui.handleGenericMergeCommandResult(err); err != nil {
return err
}
}
return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI})
})
},
})
}
func (gui *Gui) refreshCommitFilesView() error {
if err := gui.refreshPatchBuildingPanel(-1); err != nil {
return err
}
isStash := gui.State.Panels.CommitFiles.refType == REF_TYPE_STASH
refName := gui.State.Panels.CommitFiles.refName
diffing := gui.State.Modes.Diffing
var files []*commands.CommitFile
var err error
if diffing.Active() {
from := diffing.Ref
to := refName
if diffing.Reverse {
from, to = to, from
}
files, err = gui.GitCommand.GetFilesInDiff(from, to, refName, gui.GitCommand.PatchManager)
} else {
files, err = gui.GitCommand.GetFilesInRef(refName, isStash, gui.GitCommand.PatchManager)
}
if err != nil {
return gui.surfaceError(err)
}
gui.State.CommitFiles = files
return gui.postRefreshUpdate(gui.Contexts.CommitFiles.Context)
}
func (gui *Gui) handleOpenOldCommitFile(g *gocui.Gui, v *gocui.View) error {
file := gui.getSelectedCommitFile()
if file == nil {
return nil
}
return gui.openFile(file.Name)
}
func (gui *Gui) handleEditCommitFile(g *gocui.Gui, v *gocui.View) error {
file := gui.getSelectedCommitFile()
if file == nil {
return nil
}
return gui.editFile(file.Name)
}
func (gui *Gui) handleToggleFileForPatch(g *gocui.Gui, v *gocui.View) error {
if ok, err := gui.validateNormalWorkingTreeState(); !ok {
return err
}
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
toggleTheFile := func() error {
if !gui.GitCommand.PatchManager.Active() {
if err := gui.startPatchManager(); err != nil {
return err
}
}
if err := gui.GitCommand.PatchManager.ToggleFileWhole(commitFile.Name); err != nil {
return err
}
if gui.GitCommand.PatchManager.IsEmpty() {
gui.GitCommand.PatchManager.Reset()
}
return gui.refreshCommitFilesView()
}
if gui.GitCommand.PatchManager.Active() && gui.GitCommand.PatchManager.Parent != commitFile.Parent {
return gui.ask(askOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DiscardPatch"),
prompt: gui.Tr.SLocalize("DiscardPatchConfirm"),
handleConfirm: func() error {
gui.GitCommand.PatchManager.Reset()
return toggleTheFile()
},
})
}
return toggleTheFile()
}
func (gui *Gui) startPatchManager() error {
canRebase := gui.State.Panels.CommitFiles.refType == REF_TYPE_LOCAL_COMMIT
gui.GitCommand.PatchManager.Start(gui.State.Panels.CommitFiles.refName, canRebase)
return nil
}
func (gui *Gui) handleEnterCommitFile(g *gocui.Gui, v *gocui.View) error {
return gui.enterCommitFile(-1)
}
func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
if ok, err := gui.validateNormalWorkingTreeState(); !ok {
return err
}
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
enterTheFile := func(selectedLineIdx int) error {
if !gui.GitCommand.PatchManager.Active() {
if err := gui.startPatchManager(); err != nil {
return err
}
}
if err := gui.switchContext(gui.Contexts.PatchBuilding.Context); err != nil {
return err
}
return gui.refreshPatchBuildingPanel(selectedLineIdx)
}
if gui.GitCommand.PatchManager.Active() && gui.GitCommand.PatchManager.Parent != commitFile.Parent {
return gui.ask(askOpts{
returnToView: gui.getCommitFilesView(),
returnFocusOnClose: false,
title: gui.Tr.SLocalize("DiscardPatch"),
prompt: gui.Tr.SLocalize("DiscardPatchConfirm"),
handleConfirm: func() error {
gui.GitCommand.PatchManager.Reset()
return enterTheFile(selectedLineIdx)
},
handleClose: func() error {
return gui.switchContext(gui.Contexts.CommitFiles.Context)
},
})
}
return enterTheFile(selectedLineIdx)
}
func (gui *Gui) switchToCommitFilesContext(refName string, refType int, context Context, windowName string) error {
// sometimes the commitFiles view is already shown in another window, so we need to ensure that window
// no longer considers the commitFiles view as its main view.
gui.resetWindowForView("commitFiles")
gui.State.Panels.CommitFiles.SelectedLineIdx = 0
gui.State.Panels.CommitFiles.refName = refName
gui.State.Panels.CommitFiles.refType = refType
gui.Contexts.CommitFiles.Context.SetParentContext(context)
gui.Contexts.CommitFiles.Context.SetWindowName(windowName)
if err := gui.refreshCommitFilesView(); err != nil {
return err
}
return gui.switchContext(gui.Contexts.CommitFiles.Context)
}