mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-28 16:02:01 +03:00
WIP refactor
This commit is contained in:
@ -3,17 +3,23 @@ package commands
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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
|
||||
type GitCommand struct {
|
||||
Log *logrus.Logger
|
||||
OSCommand *OSCommand
|
||||
Worktree *git.Worktree
|
||||
Repo *git.Repository
|
||||
Worktree *gogit.Worktree
|
||||
Repo *gogit.Repository
|
||||
}
|
||||
|
||||
// NewGitCommand it runs git commands
|
||||
@ -32,6 +38,7 @@ func (c *GitCommand) SetupGit() {
|
||||
c.setupWorktree()
|
||||
}
|
||||
|
||||
// GitIgnore adds a file to the .gitignore of the repo
|
||||
func (c *GitCommand) GitIgnore(filename string) {
|
||||
if _, err := c.OSCommand.RunDirectCommand("echo '" + filename + "' >> .gitignore"); err != nil {
|
||||
panic(err)
|
||||
@ -55,7 +62,6 @@ func (c *GitCommand) navigateToRepoRootDirectory() {
|
||||
}
|
||||
|
||||
func (c *GitCommand) setupWorktree() {
|
||||
var err error
|
||||
r, err := git.PlainOpen(".")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -63,9 +69,151 @@ func (c *GitCommand) setupWorktree() {
|
||||
c.Repo = r
|
||||
|
||||
w, err := r.Worktree()
|
||||
c.Worktree = w
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package commands
|
||||
|
||||
import (
|
||||
|
||||
@ -279,7 +279,7 @@ func verifyInGitRepo() {
|
||||
}
|
||||
|
||||
func getCommits() []Commit {
|
||||
pushables := gitCommitsToPush()
|
||||
pushables := git.GetCommitsToPush()
|
||||
log := getLog()
|
||||
commits := make([]Commit, 0)
|
||||
// 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
|
||||
}
|
||||
|
||||
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})
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ func refreshBranches(g *gocui.Gui) error {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
state.Branches = getGitBranches()
|
||||
state.Branches = git.GetGitBranches()
|
||||
v.Clear()
|
||||
for _, branch := range state.Branches {
|
||||
fmt.Fprintln(v, branch.getDisplayString())
|
||||
|
@ -148,7 +148,7 @@ func handleRenameCommit(g *gocui.Gui, v *gocui.View) error {
|
||||
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 {
|
||||
if output, err := git.RenameCommit(v.Buffer()); err != nil {
|
||||
return createErrorPanel(g, output)
|
||||
}
|
||||
if err := refreshCommits(g); err != nil {
|
||||
|
@ -354,7 +354,7 @@ func handleAbortMerge(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 {
|
||||
if err := gitResetHard(); err != nil {
|
||||
if err := git.ResetHard(); err != nil {
|
||||
createErrorPanel(g, err.Error())
|
||||
}
|
||||
return refreshFiles(g)
|
||||
|
@ -17,7 +17,7 @@ func refreshStatus(g *gocui.Gui) error {
|
||||
// contents end up cleared
|
||||
g.Update(func(*gocui.Gui) error {
|
||||
v.Clear()
|
||||
pushables, pullables := gitUpstreamDifferenceCount()
|
||||
pushables, pullables := git.UpstreamDifferenceCount()
|
||||
fmt.Fprint(v, "↑"+pushables+"↓"+pullables)
|
||||
branches := state.Branches
|
||||
if err := updateHasMergeConflictStatus(); err != nil {
|
||||
|
Reference in New Issue
Block a user