1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-11-30 09:16:47 +02:00
lazygit/commits_panel.go

177 lines
4.5 KiB
Go
Raw Normal View History

2018-05-27 08:32:09 +02:00
package main
import (
2018-08-06 07:37:14 +02:00
"errors"
2018-06-01 15:23:31 +02:00
2018-08-06 07:37:14 +02:00
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
2018-05-27 08:32:09 +02:00
)
2018-06-01 15:23:31 +02:00
var (
2018-08-06 07:37:14 +02:00
// ErrNoCommits : When no commits are found for the branch
ErrNoCommits = errors.New("No commits for this branch")
2018-06-01 15:23:31 +02:00
)
2018-05-27 08:32:09 +02:00
func refreshCommits(g *gocui.Gui) error {
2018-08-06 07:37:14 +02:00
g.Update(func(*gocui.Gui) error {
state.Commits = getCommits()
v, err := g.View("commits")
if err != nil {
panic(err)
}
v.Clear()
red := color.New(color.FgRed)
yellow := color.New(color.FgYellow)
white := color.New(color.FgWhite)
shaColor := white
for _, commit := range state.Commits {
if commit.Pushed {
shaColor = red
} else {
shaColor = yellow
}
shaColor.Fprint(v, commit.Sha+" ")
white.Fprintln(v, commit.Name)
}
refreshStatus(g)
if g.CurrentView().Name() == "commits" {
handleCommitSelect(g, v)
}
2018-08-06 07:37:14 +02:00
return nil
})
return nil
2018-05-27 08:32:09 +02:00
}
2018-06-02 05:51:03 +02:00
func handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error {
2018-08-06 07:37:14 +02:00
return createConfirmationPanel(g, commitView, "Reset To Commit", "Are you sure you want to reset to this commit?", func(g *gocui.Gui, v *gocui.View) error {
commit, err := getSelectedCommit(g)
if err != nil {
panic(err)
}
if output, err := gitResetToCommit(commit.Sha); err != nil {
return createErrorPanel(g, output)
}
if err := refreshCommits(g); err != nil {
panic(err)
}
if err := refreshFiles(g); err != nil {
panic(err)
}
resetOrigin(commitView)
return handleCommitSelect(g, nil)
}, nil)
2018-06-02 05:51:03 +02:00
}
2018-06-09 11:06:33 +02:00
func renderCommitsOptions(g *gocui.Gui) error {
2018-08-06 07:37:14 +02:00
return renderOptionsMap(g, map[string]string{
"s": "squash down",
"r": "rename",
"g": "reset to this commit",
2018-08-08 09:52:04 +02:00
"f": "fixup commit",
2018-08-06 07:37:14 +02:00
"← → ↑ ↓": "navigate",
})
2018-06-09 11:06:33 +02:00
}
2018-05-27 08:32:09 +02:00
func handleCommitSelect(g *gocui.Gui, v *gocui.View) error {
2018-08-06 07:37:14 +02:00
if err := renderCommitsOptions(g); err != nil {
return err
}
commit, err := getSelectedCommit(g)
if err != nil {
if err != ErrNoCommits {
return err
}
return renderString(g, "main", "No commits for this branch")
}
commitText := gitShow(commit.Sha)
return renderString(g, "main", commitText)
2018-05-27 08:32:09 +02:00
}
func handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error {
2018-08-06 07:37:14 +02:00
if getItemPosition(v) != 0 {
return createErrorPanel(g, "Can only squash topmost commit")
}
if len(state.Commits) == 1 {
return createErrorPanel(g, "You have no commits to squash with")
}
commit, err := getSelectedCommit(g)
if err != nil {
return err
}
if output, err := gitSquashPreviousTwoCommits(commit.Name); err != nil {
return createErrorPanel(g, output)
}
if err := refreshCommits(g); err != nil {
2018-08-08 09:52:04 +02:00
panic(err)
}
refreshStatus(g)
return handleCommitSelect(g, v)
}
// TODO: move to files panel
func anyUnStagedChanges(files []GitFile) bool {
for _, file := range files {
if file.Tracked && file.HasUnstagedChanges {
return true
}
}
return false
}
2018-08-08 09:52:04 +02:00
func handleCommitFixup(g *gocui.Gui, v *gocui.View) error {
if len(state.Commits) == 1 {
return createErrorPanel(g, "You have no commits to squash with")
}
objectLog(state.GitFiles)
if anyUnStagedChanges(state.GitFiles) {
return createErrorPanel(g, "Can't fixup while there are unstaged changes")
}
2018-08-08 09:52:04 +02:00
branch := state.Branches[0]
commit, err := getSelectedCommit(g)
if err != nil {
return err
}
createConfirmationPanel(g, v, "Fixup", "Are you sure you want to fixup this commit? The commit beneath will be squashed up into this one", func(g *gocui.Gui, v *gocui.View) error {
if output, err := gitSquashFixupCommit(branch.Name, commit.Sha); err != nil {
return createErrorPanel(g, output)
}
if err := refreshCommits(g); err != nil {
panic(err)
}
return refreshStatus(g)
}, nil)
return nil
2018-05-27 08:32:09 +02:00
}
func handleRenameCommit(g *gocui.Gui, v *gocui.View) error {
2018-08-06 07:37:14 +02:00
if getItemPosition(v) != 0 {
return createErrorPanel(g, "Can only rename topmost commit")
}
createPromptPanel(g, v, "Rename Commit", func(g *gocui.Gui, v *gocui.View) error {
if output, err := gitRenameCommit(v.Buffer()); err != nil {
return createErrorPanel(g, output)
}
if err := refreshCommits(g); err != nil {
panic(err)
}
return handleCommitSelect(g, v)
})
return nil
2018-05-27 08:32:09 +02:00
}
2018-06-02 05:51:03 +02:00
func getSelectedCommit(g *gocui.Gui) (Commit, error) {
2018-08-06 07:37:14 +02:00
v, err := g.View("commits")
if err != nil {
panic(err)
}
if len(state.Commits) == 0 {
return Commit{}, ErrNoCommits
}
lineNumber := getItemPosition(v)
if lineNumber > len(state.Commits)-1 {
devLog("potential error in getSelected Commit (mismatched ui and state)", state.Commits, lineNumber)
2018-08-06 07:37:14 +02:00
return state.Commits[len(state.Commits)-1], nil
}
return state.Commits[lineNumber], nil
2018-05-27 08:32:09 +02:00
}