mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-28 16:02:01 +03:00
Move some commands around
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -45,6 +47,114 @@ func (c *GitCommand) GitIgnore(filename string) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetStashEntries stash entryies
|
||||
func (c *GitCommand) GetStashEntries() []StashEntry {
|
||||
stashEntries := make([]StashEntry, 0)
|
||||
rawString, _ := c.OSCommand.RunDirectCommand("git stash list --pretty='%gs'")
|
||||
for i, line := range splitLines(rawString) {
|
||||
stashEntries = append(stashEntries, stashEntryFromLine(line, i))
|
||||
}
|
||||
return stashEntries
|
||||
}
|
||||
|
||||
func stashEntryFromLine(line string, index int) StashEntry {
|
||||
return StashEntry{
|
||||
Name: line,
|
||||
Index: index,
|
||||
DisplayString: line,
|
||||
}
|
||||
}
|
||||
|
||||
// GetStashEntryDiff stash diff
|
||||
func (c *GitCommand) GetStashEntryDiff(index int) (string, error) {
|
||||
return runCommand("git stash show -p --color stash@{" + fmt.Sprint(index) + "}")
|
||||
}
|
||||
|
||||
func includes(array []string, str string) bool {
|
||||
for _, arrayStr := range array {
|
||||
if arrayStr == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetStatusFiles git status files
|
||||
func (c *GitCommand) GetStatusFiles() []GitFile {
|
||||
statusOutput, _ := getGitStatus()
|
||||
statusStrings := splitLines(statusOutput)
|
||||
gitFiles := make([]GitFile, 0)
|
||||
|
||||
for _, statusString := range statusStrings {
|
||||
change := statusString[0:2]
|
||||
stagedChange := change[0:1]
|
||||
unstagedChange := statusString[1:2]
|
||||
filename := statusString[3:]
|
||||
tracked := !f([]string{"??", "A "}, change)
|
||||
gitFile := GitFile{
|
||||
Name: filename,
|
||||
DisplayString: statusString,
|
||||
HasStagedChanges: !includes([]string{" ", "U", "?"}, stagedChange),
|
||||
HasUnstagedChanges: unstagedChange != " ",
|
||||
Tracked: tracked,
|
||||
Deleted: unstagedChange == "D" || stagedChange == "D",
|
||||
HasMergeConflicts: change == "UU",
|
||||
}
|
||||
gitFiles = append(gitFiles, gitFile)
|
||||
}
|
||||
objectLog(gitFiles)
|
||||
return gitFiles
|
||||
}
|
||||
|
||||
// StashDo modify stash
|
||||
func (c *GitCommand) StashDo(index int, method string) (string, error) {
|
||||
return c.OSCommand.RunCommand("git stash " + method + " stash@{" + fmt.Sprint(index) + "}")
|
||||
}
|
||||
|
||||
// StashSave save stash
|
||||
func (c *GitCommand) StashSave(message string) (string, error) {
|
||||
output, err := c.OSCommand.RunCommand("git stash save \"" + message + "\"")
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
// if there are no local changes to save, the exit code is 0, but we want
|
||||
// to raise an error
|
||||
if output == "No local changes to save\n" {
|
||||
return output, errors.New(output)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// MergeStatusFiles merge status files
|
||||
func (c *GitCommand) MergeStatusFiles(oldGitFiles, newGitFiles []GitFile) []GitFile {
|
||||
if len(oldGitFiles) == 0 {
|
||||
return newGitFiles
|
||||
}
|
||||
|
||||
appendedIndexes := make([]int, 0)
|
||||
|
||||
// retain position of files we already could see
|
||||
result := make([]GitFile, 0)
|
||||
for _, oldGitFile := range oldGitFiles {
|
||||
for newIndex, newGitFile := range newGitFiles {
|
||||
if oldGitFile.Name == newGitFile.Name {
|
||||
result = append(result, newGitFile)
|
||||
appendedIndexes = append(appendedIndexes, newIndex)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append any new files to the end
|
||||
for index, newGitFile := range newGitFiles {
|
||||
if !includesInt(appendedIndexes, index) {
|
||||
result = append(result, newGitFile)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *GitCommand) verifyInGitRepo() {
|
||||
if output, err := c.OSCommand.RunCommand("git status"); err != nil {
|
||||
fmt.Println(output)
|
||||
@ -127,35 +237,54 @@ func (c *GitCommand) RenameCommit(name string) (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git commit --allow-empty --amend -m \"" + name + "\"")
|
||||
}
|
||||
|
||||
// Fetch fetch git repo
|
||||
func (c *GitCommand) Fetch() (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git fetch")
|
||||
}
|
||||
|
||||
// ResetToCommit reset to commit
|
||||
func (c *GitCommand) ResetToCommit(sha string) (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git reset " + sha)
|
||||
}
|
||||
|
||||
// NewBranch create new branch
|
||||
func (c *GitCommand) NewBranch(name string) (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git checkout -b " + name)
|
||||
}
|
||||
|
||||
// DeleteBranch delete branch
|
||||
func (c *GitCommand) DeleteBranch(branch string) (string, error) {
|
||||
return runCommand("git branch -d " + branch)
|
||||
}
|
||||
|
||||
// ListStash list stash
|
||||
func (c *GitCommand) ListStash() (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git stash list")
|
||||
}
|
||||
|
||||
// Merge merge
|
||||
func (c *GitCommand) Merge(branchName string) (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git merge --no-edit " + branchName)
|
||||
}
|
||||
|
||||
// AbortMerge abort merge
|
||||
func (c *GitCommand) AbortMerge() (string, error) {
|
||||
return c.OSCommand.runDirectCommand("git merge --abort")
|
||||
}
|
||||
|
||||
func gitCommit(g *gocui.Gui, message string) (string, error) {
|
||||
func runSubProcess(g *gocui.Gui, cmdName string, commandArgs ...string) {
|
||||
subprocess = exec.Command(cmdName, commandArgs...)
|
||||
subprocess.Stdin = os.Stdin
|
||||
subprocess.Stdout = os.Stdout
|
||||
subprocess.Stderr = os.Stderr
|
||||
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
return ErrSubprocess
|
||||
})
|
||||
}
|
||||
|
||||
// GitCommit commit to git
|
||||
func (c *GitCommand) GitCommit(g *gocui.Gui, message string) (string, error) {
|
||||
gpgsign, _ := gitconfig.Global("commit.gpgsign")
|
||||
if gpgsign != "" {
|
||||
runSubProcess(g, "git", "commit")
|
||||
@ -179,19 +308,25 @@ func gitCommit(g *gocui.Gui, message string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func gitPull() (string, error) {
|
||||
return runDirectCommand("git pull --no-edit")
|
||||
// GitPull pull from repo
|
||||
func (c *GitCommand) GitPull() (string, error) {
|
||||
return c.OSCommand.RunCommand("git pull --no-edit")
|
||||
}
|
||||
|
||||
func gitPush() (string, error) {
|
||||
return runDirectCommand("git push -u origin " + state.Branches[0].Name)
|
||||
// GitPush push to a branch
|
||||
func (c *GitCommand) GitPush() (string, error) {
|
||||
return c.OSCommand.RunDirectCommand("git push -u origin " + state.Branches[0].Name)
|
||||
}
|
||||
|
||||
func gitSquashPreviousTwoCommits(message string) (string, error) {
|
||||
// SquashPreviousTwoCommits squashes a commit down to the one below it
|
||||
// retaining the message of the higher commit
|
||||
func (c *GitCommand) SquashPreviousTwoCommits(message string) (string, error) {
|
||||
return runDirectCommand("git reset --soft HEAD^ && git commit --amend -m \"" + message + "\"")
|
||||
}
|
||||
|
||||
func gitSquashFixupCommit(branchName string, shaValue string) (string, error) {
|
||||
// SquashFixupCommit squashes a 'FIXUP' commit into the commit beneath it,
|
||||
// retaining the commit message of the lower commit
|
||||
func (c *GitCommand) SquashFixupCommit(branchName string, shaValue string) (string, error) {
|
||||
var err error
|
||||
commands := []string{
|
||||
"git checkout -q " + shaValue,
|
||||
@ -202,7 +337,7 @@ func gitSquashFixupCommit(branchName string, shaValue string) (string, error) {
|
||||
ret := ""
|
||||
for _, command := range commands {
|
||||
devLog(command)
|
||||
output, err := runDirectCommand(command)
|
||||
output, err := c.OSCommand.runDirectCommand(command)
|
||||
ret += output
|
||||
if err != nil {
|
||||
devLog(ret)
|
||||
@ -212,8 +347,110 @@ func gitSquashFixupCommit(branchName string, shaValue string) (string, error) {
|
||||
if err != nil {
|
||||
// We are already in an error state here so we're just going to append
|
||||
// the output of these commands
|
||||
ret += runDirectCommandIgnoringError("git branch -d " + shaValue)
|
||||
ret += runDirectCommandIgnoringError("git checkout " + branchName)
|
||||
output, _ = c.OSCommand.RunDirectCommand("git branch -d " + shaValue)
|
||||
ret += output
|
||||
output, _ = c.OSCommand.RunDirectCommand("git checkout " + branchName)
|
||||
ret += output
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// CatFile obtain the contents of a file
|
||||
func (c *GitCommand) CatFile(file string) (string, error) {
|
||||
return c.OSCommand.runDirectCommand("cat " + file)
|
||||
}
|
||||
|
||||
// StageFile stages a file
|
||||
func (c *GitCommand) StageFile(file string) error {
|
||||
_, err := c.OSCommand.runCommand("git add " + file)
|
||||
return err
|
||||
}
|
||||
|
||||
// UnStageFile unstages a file
|
||||
func (c *GitCommand) UnStageFile(file string, tracked bool) error {
|
||||
var command string
|
||||
if tracked {
|
||||
command = "git reset HEAD "
|
||||
} else {
|
||||
command = "git rm --cached "
|
||||
}
|
||||
_, err := c.OSCommand.runCommand(command + file)
|
||||
return err
|
||||
}
|
||||
|
||||
// GitStatus returns the plaintext short status of the repo
|
||||
func (c *GitCommand) GitStatus() (string, error) {
|
||||
return c.OSCommand.runCommand("git status --untracked-files=all --short")
|
||||
}
|
||||
|
||||
// IsInMergeState states whether we are still mid-merge
|
||||
func (c *GitCommand) IsInMergeState() (bool, error) {
|
||||
output, err := c.OSCommand.runCommand("git status --untracked-files=all")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.Contains(output, "conclude merge") || strings.Contains(output, "unmerged paths"), nil
|
||||
}
|
||||
|
||||
// RemoveFile directly
|
||||
func (c *GitCommand) RemoveFile(file GitFile) error {
|
||||
// if the file isn't tracked, we assume you want to delete it
|
||||
if !file.Tracked {
|
||||
_, err := c.OSCommand.runCommand("rm -rf ./" + file.Name)
|
||||
return err
|
||||
}
|
||||
// if the file is tracked, we assume you want to just check it out
|
||||
_, err := c.OSCommand.runCommand("git checkout " + file.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Checkout checks out a branch, with --force if you set the force arg to true
|
||||
func (c *GitCommand) Checkout(branch string, force bool) (string, error) {
|
||||
forceArg := ""
|
||||
if force {
|
||||
forceArg = "--force "
|
||||
}
|
||||
return c.OSCommand.runCommand("git checkout " + forceArg + branch)
|
||||
}
|
||||
|
||||
// AddPatch runs a subprocess for adding a patch by patch
|
||||
// this will eventually be swapped out for a better solution inside the Gui
|
||||
func (c *GitCommand) AddPatch(g *gocui.Gui, filename string) {
|
||||
runSubProcess(g, "git", "add", "--patch", filename)
|
||||
}
|
||||
|
||||
// GetBranchGraph gets the color-formatted graph of the log for the given branch
|
||||
// Currently it limits the result to 100 commits, but when we get async stuff
|
||||
// working we can do lazy loading
|
||||
func (c *GitCommand) GetBranchGraph(branchName string) (string, error) {
|
||||
return c.OSCommand.runCommand("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 " + branchName)
|
||||
}
|
||||
|
||||
// map (from https://gobyexample.com/collection-functions)
|
||||
func map(vs []string, f func(string) string) []string {
|
||||
vsm := make([]string, len(vs))
|
||||
for i, v := range vs {
|
||||
vsm[i] = f(v)
|
||||
}
|
||||
return vsm
|
||||
}
|
||||
|
||||
func includesString(list []string, a string) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// not sure how to genericise this because []interface{} doesn't accept e.g.
|
||||
// []int arguments
|
||||
func includesInt(list []int, a int) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
Reference in New Issue
Block a user