2018-05-26 05:23:39 +02:00
package main
import (
// "io"
// "io/ioutil"
// "strings"
2018-06-01 15:23:31 +02:00
"errors"
2018-05-26 05:23:39 +02:00
"strings"
"github.com/fatih/color"
2018-06-05 10:47:31 +02:00
"github.com/jesseduffield/gocui"
2018-05-26 05:23:39 +02:00
)
2018-06-01 15:23:31 +02:00
var (
// ErrNoFiles : when there are no modified files in the repo
ErrNoFiles = errors . New ( "No changed files" )
)
2018-05-26 05:23:39 +02:00
func stagedFiles ( files [ ] GitFile ) [ ] GitFile {
result := make ( [ ] GitFile , 0 )
for _ , file := range files {
if file . HasStagedChanges {
result = append ( result , file )
}
}
return result
}
func handleFilePress ( g * gocui . Gui , v * gocui . View ) error {
2018-06-01 15:23:31 +02:00
file , err := getSelectedFile ( v )
if err != nil {
return err
}
2018-05-26 05:23:39 +02:00
if file . HasUnstagedChanges {
stageFile ( file . Name )
} else {
unStageFile ( file . Name )
}
if err := refreshFiles ( g ) ; err != nil {
return err
}
if err := handleFileSelect ( g , v ) ; err != nil {
return err
}
return nil
}
2018-06-01 15:23:31 +02:00
func getSelectedFile ( v * gocui . View ) ( GitFile , error ) {
2018-05-26 05:23:39 +02:00
if len ( state . GitFiles ) == 0 {
2018-06-01 15:23:31 +02:00
return GitFile { } , ErrNoFiles
2018-05-26 05:23:39 +02:00
}
2018-06-01 15:23:31 +02:00
lineNumber := getItemPosition ( v )
return state . GitFiles [ lineNumber ] , nil
2018-05-26 05:23:39 +02:00
}
func handleFileRemove ( g * gocui . Gui , v * gocui . View ) error {
2018-06-01 15:23:31 +02:00
file , err := getSelectedFile ( v )
if err != nil {
return err
}
2018-05-26 05:23:39 +02:00
var deleteVerb string
if file . Tracked {
deleteVerb = "checkout"
} else {
deleteVerb = "delete"
}
2018-05-27 08:32:09 +02:00
return createConfirmationPanel ( g , v , strings . Title ( deleteVerb ) + " file" , "Are you sure you want to " + deleteVerb + " " + file . Name + " (you will lose your changes)? (y/n)" , func ( g * gocui . Gui , v * gocui . View ) error {
2018-05-26 05:23:39 +02:00
if err := removeFile ( file ) ; err != nil {
panic ( err )
}
return refreshFiles ( g )
} , nil )
}
2018-06-01 15:23:31 +02:00
func handleIgnoreFile ( g * gocui . Gui , v * gocui . View ) error {
file , err := getSelectedFile ( v )
if err != nil {
return err
}
if file . Tracked {
return createErrorPanel ( g , "Cannot ignore tracked files" )
}
gitIgnore ( file . Name )
return refreshFiles ( g )
}
2018-05-26 05:23:39 +02:00
func handleFileSelect ( g * gocui . Gui , v * gocui . View ) error {
2018-06-01 15:23:31 +02:00
baseString := "tab: switch to branches, space: toggle staged, c: commit changes, o: open, s: open in sublime, i: ignore"
item , err := getSelectedFile ( v )
if err != nil {
if err != ErrNoFiles {
return err
}
renderString ( g , "main" , "No changed files" )
colorLog ( color . FgRed , "error" )
return renderString ( g , "options" , baseString )
}
2018-05-26 05:23:39 +02:00
var optionsString string
if item . Tracked {
2018-06-01 15:23:31 +02:00
optionsString = baseString + ", r: checkout"
2018-05-26 05:23:39 +02:00
} else {
2018-06-01 15:23:31 +02:00
optionsString = baseString + ", r: delete"
2018-05-26 05:23:39 +02:00
}
renderString ( g , "options" , optionsString )
diff := getDiff ( item )
return renderString ( g , "main" , diff )
}
2018-06-01 15:23:31 +02:00
func genericFileOpen ( g * gocui . Gui , v * gocui . View , open func ( string ) ( string , error ) ) error {
file , err := getSelectedFile ( v )
if err != nil {
return err
}
_ , err = open ( file . Name )
2018-05-26 05:23:39 +02:00
return err
}
2018-06-01 15:23:31 +02:00
func handleFileOpen ( g * gocui . Gui , v * gocui . View ) error {
return genericFileOpen ( g , v , openFile )
}
2018-05-26 05:23:39 +02:00
func handleSublimeFileOpen ( g * gocui . Gui , v * gocui . View ) error {
2018-06-01 15:23:31 +02:00
return genericFileOpen ( g , v , sublimeOpenFile )
2018-05-26 05:23:39 +02:00
}
func refreshFiles ( g * gocui . Gui ) error {
filesView , err := g . View ( "files" )
if err != nil {
return err
}
// get files to stage
gitFiles := getGitStatusFiles ( )
state . GitFiles = mergeGitStatusFiles ( state . GitFiles , gitFiles )
filesView . Clear ( )
red := color . New ( color . FgRed )
green := color . New ( color . FgGreen )
for _ , gitFile := range state . GitFiles {
if ! gitFile . Tracked {
red . Fprintln ( filesView , gitFile . DisplayString )
continue
}
green . Fprint ( filesView , gitFile . DisplayString [ 0 : 1 ] )
red . Fprint ( filesView , gitFile . DisplayString [ 1 : 3 ] )
if gitFile . HasUnstagedChanges {
red . Fprintln ( filesView , gitFile . Name )
} else {
green . Fprintln ( filesView , gitFile . Name )
}
}
correctCursor ( filesView )
2018-06-02 01:06:02 +02:00
handleFileSelect ( g , filesView )
2018-05-26 05:23:39 +02:00
return nil
}
2018-05-26 07:44:44 +02:00
2018-05-27 08:32:09 +02:00
func pullFiles ( g * gocui . Gui , v * gocui . View ) error {
devLog ( "pulling..." )
createSimpleConfirmationPanel ( g , v , "" , "Pulling..." )
go func ( ) {
if output , err := gitPull ( ) ; err != nil {
createSimpleConfirmationPanel ( g , v , "Error" , output )
} else {
closeConfirmationPrompt ( g )
2018-06-01 15:23:31 +02:00
refreshCommits ( g )
refreshFiles ( g )
refreshStatus ( g )
devLog ( "pulled." )
2018-05-27 08:32:09 +02:00
}
} ( )
2018-06-01 15:23:31 +02:00
return nil
2018-05-26 07:44:44 +02:00
}
2018-05-27 08:32:09 +02:00
func pushFiles ( g * gocui . Gui , v * gocui . View ) error {
devLog ( "pushing..." )
createSimpleConfirmationPanel ( g , v , "" , "Pushing..." )
go func ( ) {
if output , err := gitPush ( ) ; err != nil {
createSimpleConfirmationPanel ( g , v , "Error" , output )
} else {
closeConfirmationPrompt ( g )
2018-06-01 15:23:31 +02:00
refreshCommits ( g )
refreshStatus ( g )
devLog ( "pushed." )
2018-05-27 08:32:09 +02:00
}
} ( )
return nil
}