1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-28 16:02:01 +03:00

WIP refactor

This commit is contained in:
Jesse Duffield
2018-08-12 19:50:55 +10:00
parent dcd461d29f
commit c01bc09442
6 changed files with 159 additions and 81 deletions

View File

@ -3,17 +3,23 @@ package commands
import ( import (
"fmt" "fmt"
"os" "os"
"strings"
"time"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
git "gopkg.in/src-d/go-git.v4" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/git"
gitconfig "github.com/tcnksm/go-gitconfig"
gogit "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing/object"
) )
// GitCommand is our main git interface // GitCommand is our main git interface
type GitCommand struct { type GitCommand struct {
Log *logrus.Logger Log *logrus.Logger
OSCommand *OSCommand OSCommand *OSCommand
Worktree *git.Worktree Worktree *gogit.Worktree
Repo *git.Repository Repo *gogit.Repository
} }
// NewGitCommand it runs git commands // NewGitCommand it runs git commands
@ -32,6 +38,7 @@ func (c *GitCommand) SetupGit() {
c.setupWorktree() c.setupWorktree()
} }
// GitIgnore adds a file to the .gitignore of the repo
func (c *GitCommand) GitIgnore(filename string) { func (c *GitCommand) GitIgnore(filename string) {
if _, err := c.OSCommand.RunDirectCommand("echo '" + filename + "' >> .gitignore"); err != nil { if _, err := c.OSCommand.RunDirectCommand("echo '" + filename + "' >> .gitignore"); err != nil {
panic(err) panic(err)
@ -55,7 +62,6 @@ func (c *GitCommand) navigateToRepoRootDirectory() {
} }
func (c *GitCommand) setupWorktree() { func (c *GitCommand) setupWorktree() {
var err error
r, err := git.PlainOpen(".") r, err := git.PlainOpen(".")
if err != nil { if err != nil {
panic(err) panic(err)
@ -63,9 +69,151 @@ func (c *GitCommand) setupWorktree() {
c.Repo = r c.Repo = r
w, err := r.Worktree() w, err := r.Worktree()
c.Worktree = w
if err != nil { if err != nil {
panic(err) panic(err)
} }
c.Worktree = w c.Worktree = w
} }
// ResetHard does the equivalent of `git reset --hard HEAD`
func (c *GitCommand) ResetHard() error {
return c.Worktree.Reset(&gogit.ResetOptions{Mode: git.HardReset})
}
// UpstreamDifferenceCount checks how many pushables/pullables there are for the
// current branch
func (c *GitCommand) UpstreamDifferenceCount() (string, string) {
pushableCount, err := c.OSCommand.runDirectCommand("git rev-list @{u}..head --count")
if err != nil {
return "?", "?"
}
pullableCount, err := c.OSCommand.runDirectCommand("git rev-list head..@{u} --count")
if err != nil {
return "?", "?"
}
return strings.TrimSpace(pushableCount), strings.TrimSpace(pullableCount)
}
// GetCommitsToPush Returns the sha's of the commits that have not yet been pushed
// to the remote branch of the current branch
func (c *GitCommand) GetCommitsToPush() []string {
pushables, err := c.OSCommand.runDirectCommand("git rev-list @{u}..head --abbrev-commit")
if err != nil {
return make([]string, 0)
}
return splitLines(pushables)
}
// GetGitBranches returns a list of branches for the current repo, with recency
// values stored against those that are in the reflog
func (c *GitCommand) GetGitBranches() []Branch {
builder := git.newBranchListBuilder()
return builder.build()
}
// BranchIncluded states whether a branch is included in a list of branches,
// with a case insensitive comparison on name
func (c *GitCommand) BranchIncluded(branchName string, branches []Branch) bool {
for _, existingBranch := range branches {
if strings.ToLower(existingBranch.Name) == strings.ToLower(branchName) {
return true
}
}
return false
}
// RenameCommit renames the topmost commit with the given name
func (c *GitCommand) RenameCommit(name string) (string, error) {
return c.OSCommand.runDirectCommand("git commit --allow-empty --amend -m \"" + name + "\"")
}
func (c *GitCommand) Fetch() (string, error) {
return c.OSCommand.runDirectCommand("git fetch")
}
func (c *GitCommand) ResetToCommit(sha string) (string, error) {
return c.OSCommand.runDirectCommand("git reset " + sha)
}
func (c *GitCommand) NewBranch(name string) (string, error) {
return c.OSCommand.runDirectCommand("git checkout -b " + name)
}
func (c *GitCommand) DeleteBranch(branch string) (string, error) {
return runCommand("git branch -d " + branch)
}
func (c *GitCommand) ListStash() (string, error) {
return c.OSCommand.runDirectCommand("git stash list")
}
func (c *GitCommand) Merge(branchName string) (string, error) {
return c.OSCommand.runDirectCommand("git merge --no-edit " + branchName)
}
func (c *GitCommand) AbortMerge() (string, error) {
return c.OSCommand.runDirectCommand("git merge --abort")
}
func gitCommit(g *gocui.Gui, message string) (string, error) {
gpgsign, _ := gitconfig.Global("commit.gpgsign")
if gpgsign != "" {
runSubProcess(g, "git", "commit")
return "", nil
}
userName, err := gitconfig.Username()
if userName == "" {
return "", errNoUsername
}
userEmail, err := gitconfig.Email()
_, err = w.Commit(message, &git.CommitOptions{
Author: &object.Signature{
Name: userName,
Email: userEmail,
When: time.Now(),
},
})
if err != nil {
return err.Error(), err
}
return "", nil
}
func gitPull() (string, error) {
return runDirectCommand("git pull --no-edit")
}
func gitPush() (string, error) {
return runDirectCommand("git push -u origin " + state.Branches[0].Name)
}
func gitSquashPreviousTwoCommits(message string) (string, error) {
return runDirectCommand("git reset --soft HEAD^ && git commit --amend -m \"" + message + "\"")
}
func gitSquashFixupCommit(branchName string, shaValue string) (string, error) {
var err error
commands := []string{
"git checkout -q " + shaValue,
"git reset --soft " + shaValue + "^",
"git commit --amend -C " + shaValue + "^",
"git rebase --onto HEAD " + shaValue + " " + branchName,
}
ret := ""
for _, command := range commands {
devLog(command)
output, err := runDirectCommand(command)
ret += output
if err != nil {
devLog(ret)
break
}
}
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)
}
return ret, err
}

View File

@ -1,4 +1,4 @@
package main package commands
import ( import (
@ -279,7 +279,7 @@ func verifyInGitRepo() {
} }
func getCommits() []Commit { func getCommits() []Commit {
pushables := gitCommitsToPush() pushables := git.GetCommitsToPush()
log := getLog() log := getLog()
commits := make([]Commit, 0) commits := make([]Commit, 0)
// now we can split it up and turn it into commits // now we can split it up and turn it into commits
@ -447,73 +447,3 @@ func gitSquashFixupCommit(branchName string, shaValue string) (string, error) {
} }
return ret, err return ret, err
} }
func gitRenameCommit(message string) (string, error) {
return runDirectCommand("git commit --allow-empty --amend -m \"" + message + "\"")
}
func gitFetch() (string, error) {
return runDirectCommand("git fetch")
}
func gitResetToCommit(sha string) (string, error) {
return runDirectCommand("git reset " + sha)
}
func gitNewBranch(name string) (string, error) {
return runDirectCommand("git checkout -b " + name)
}
func gitDeleteBranch(branch string) (string, error) {
return runCommand("git branch -d " + branch)
}
func gitListStash() (string, error) {
return runDirectCommand("git stash list")
}
func gitMerge(branchName string) (string, error) {
return runDirectCommand("git merge --no-edit " + branchName)
}
func gitAbortMerge() (string, error) {
return runDirectCommand("git merge --abort")
}
func gitUpstreamDifferenceCount() (string, string) {
pushableCount, err := runDirectCommand("git rev-list @{u}..head --count")
if err != nil {
return "?", "?"
}
pullableCount, err := runDirectCommand("git rev-list head..@{u} --count")
if err != nil {
return "?", "?"
}
return strings.TrimSpace(pushableCount), strings.TrimSpace(pullableCount)
}
func gitCommitsToPush() []string {
pushables, err := runDirectCommand("git rev-list @{u}..head --abbrev-commit")
if err != nil {
return make([]string, 0)
}
return splitLines(pushables)
}
func getGitBranches() []Branch {
builder := newBranchListBuilder()
return builder.build()
}
func branchIncluded(branchName string, branches []Branch) bool {
for _, existingBranch := range branches {
if strings.ToLower(existingBranch.Name) == strings.ToLower(branchName) {
return true
}
}
return false
}
func gitResetHard() error {
return w.Reset(&git.ResetOptions{Mode: git.HardReset})
}

View File

@ -123,7 +123,7 @@ func refreshBranches(g *gocui.Gui) error {
if err != nil { if err != nil {
panic(err) panic(err)
} }
state.Branches = getGitBranches() state.Branches = git.GetGitBranches()
v.Clear() v.Clear()
for _, branch := range state.Branches { for _, branch := range state.Branches {
fmt.Fprintln(v, branch.getDisplayString()) fmt.Fprintln(v, branch.getDisplayString())

View File

@ -148,7 +148,7 @@ func handleRenameCommit(g *gocui.Gui, v *gocui.View) error {
return createErrorPanel(g, "Can only rename topmost commit") return createErrorPanel(g, "Can only rename topmost commit")
} }
createPromptPanel(g, v, "Rename Commit", func(g *gocui.Gui, v *gocui.View) error { createPromptPanel(g, v, "Rename Commit", func(g *gocui.Gui, v *gocui.View) error {
if output, err := gitRenameCommit(v.Buffer()); err != nil { if output, err := git.RenameCommit(v.Buffer()); err != nil {
return createErrorPanel(g, output) return createErrorPanel(g, output)
} }
if err := refreshCommits(g); err != nil { if err := refreshCommits(g); err != nil {

View File

@ -354,7 +354,7 @@ func handleAbortMerge(g *gocui.Gui, v *gocui.View) error {
func handleResetHard(g *gocui.Gui, v *gocui.View) error { func handleResetHard(g *gocui.Gui, v *gocui.View) error {
return createConfirmationPanel(g, v, "Clear file panel", "Are you sure you want `reset --hard HEAD`? You may lose changes", func(g *gocui.Gui, v *gocui.View) error { return createConfirmationPanel(g, v, "Clear file panel", "Are you sure you want `reset --hard HEAD`? You may lose changes", func(g *gocui.Gui, v *gocui.View) error {
if err := gitResetHard(); err != nil { if err := git.ResetHard(); err != nil {
createErrorPanel(g, err.Error()) createErrorPanel(g, err.Error())
} }
return refreshFiles(g) return refreshFiles(g)

View File

@ -17,7 +17,7 @@ func refreshStatus(g *gocui.Gui) error {
// contents end up cleared // contents end up cleared
g.Update(func(*gocui.Gui) error { g.Update(func(*gocui.Gui) error {
v.Clear() v.Clear()
pushables, pullables := gitUpstreamDifferenceCount() pushables, pullables := git.UpstreamDifferenceCount()
fmt.Fprint(v, "↑"+pushables+"↓"+pullables) fmt.Fprint(v, "↑"+pushables+"↓"+pullables)
branches := state.Branches branches := state.Branches
if err := updateHasMergeConflictStatus(); err != nil { if err := updateHasMergeConflictStatus(); err != nil {