mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-02 09:21:40 +02:00
194 lines
4.5 KiB
Go
194 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
|
|
// "io"
|
|
// "io/ioutil"
|
|
|
|
// "strings"
|
|
|
|
"errors"
|
|
"strings"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/jroimartin/gocui"
|
|
)
|
|
|
|
var (
|
|
// ErrNoFiles : when there are no modified files in the repo
|
|
ErrNoFiles = errors.New("No changed files")
|
|
)
|
|
|
|
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 {
|
|
file, err := getSelectedFile(v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func getSelectedFile(v *gocui.View) (GitFile, error) {
|
|
if len(state.GitFiles) == 0 {
|
|
return GitFile{}, ErrNoFiles
|
|
}
|
|
lineNumber := getItemPosition(v)
|
|
return state.GitFiles[lineNumber], nil
|
|
}
|
|
|
|
func handleFileRemove(g *gocui.Gui, v *gocui.View) error {
|
|
file, err := getSelectedFile(v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var deleteVerb string
|
|
if file.Tracked {
|
|
deleteVerb = "checkout"
|
|
} else {
|
|
deleteVerb = "delete"
|
|
}
|
|
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 {
|
|
if err := removeFile(file); err != nil {
|
|
panic(err)
|
|
}
|
|
return refreshFiles(g)
|
|
}, nil)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
func handleFileSelect(g *gocui.Gui, v *gocui.View) error {
|
|
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)
|
|
}
|
|
var optionsString string
|
|
if item.Tracked {
|
|
optionsString = baseString + ", r: checkout"
|
|
} else {
|
|
optionsString = baseString + ", r: delete"
|
|
}
|
|
renderString(g, "options", optionsString)
|
|
diff := getDiff(item)
|
|
return renderString(g, "main", diff)
|
|
}
|
|
|
|
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)
|
|
return err
|
|
}
|
|
|
|
func handleFileOpen(g *gocui.Gui, v *gocui.View) error {
|
|
return genericFileOpen(g, v, openFile)
|
|
}
|
|
func handleSublimeFileOpen(g *gocui.Gui, v *gocui.View) error {
|
|
return genericFileOpen(g, v, sublimeOpenFile)
|
|
}
|
|
|
|
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)
|
|
handleFileSelect(g, filesView)
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
refreshCommits(g)
|
|
refreshFiles(g)
|
|
refreshStatus(g)
|
|
devLog("pulled.")
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
refreshCommits(g)
|
|
refreshStatus(g)
|
|
devLog("pushed.")
|
|
}
|
|
}()
|
|
return nil
|
|
}
|