summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2018-08-12 19:50:55 +1000
committerJesse Duffield <jessedduffield@gmail.com>2018-08-12 19:50:55 +1000
commitc01bc094423cf8a0a861ee8b3bd5432cd958339d (patch)
treedd61c036761c808e45bb6d620beb863cf075d621
parentdcd461d29f21a9626d5298a03283b6d8b46312c3 (diff)
WIP refactor
-rw-r--r--pkg/commands/git.go158
-rw-r--r--pkg/commands/gitcommands.go74
-rw-r--r--pkg/gui/panels/branches_panel.go2
-rw-r--r--pkg/gui/panels/commits_panel.go2
-rw-r--r--pkg/gui/panels/files_panel.go2
-rw-r--r--pkg/gui/panels/status_panel.go2
6 files changed, 159 insertions, 81 deletions
diff --git a/pkg/commands/git.go b/pkg/commands/git.go
index 17855b98e..23a7d90f9 100644
--- a/pkg/commands/git.go
+++ b/pkg/commands/git.go
@@ -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
+}
diff --git a/pkg/commands/gitcommands.go b/pkg/commands/gitcommands.go
index bdc23fef2..f6eb4a357 100644
--- a/pkg/commands/gitcommands.go
+++ b/pkg/commands/gitcommands.go
@@ -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})
-}
diff --git a/pkg/gui/panels/branches_panel.go b/pkg/gui/panels/branches_panel.go
index a73d28bb3..82b8542ad 100644
--- a/pkg/gui/panels/branches_panel.go
+++ b/pkg/gui/panels/branches_panel.go
@@ -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())
diff --git a/pkg/gui/panels/commits_panel.go b/pkg/gui/panels/commits_panel.go
index 1a9976ffe..5b02ae115 100644
--- a/pkg/gui/panels/commits_panel.go
+++ b/pkg/gui/panels/commits_panel.go
@@ -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 {
diff --git a/pkg/gui/panels/files_panel.go b/pkg/gui/panels/files_panel.go
index 4de8caca7..fb4fc8196 100644
--- a/pkg/gui/panels/files_panel.go
+++ b/pkg/gui/panels/files_panel.go
@@ -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)
diff --git a/pkg/gui/panels/status_panel.go b/pkg/gui/panels/status_panel.go
index f3fcb8078..a58375ce0 100644
--- a/pkg/gui/panels/status_panel.go
+++ b/pkg/gui/panels/status_panel.go
@@ -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 {