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 )
2018-08-11 07:31:55 +02:00
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 )
}
2018-08-11 07:04:02 +02:00
// 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" )
}
2018-08-11 07:04:02 +02:00
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
}
2018-08-11 07:04:02 +02:00
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 )
}
2018-08-11 07:31:55 +02:00
return refreshStatus ( g )
2018-08-11 07:04:02 +02:00
} , 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 {
2018-08-09 12:29:58 +02:00
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
}