diff options
author | Andrei Miulescu <lusu777@gmail.com> | 2018-08-12 21:04:47 +1000 |
---|---|---|
committer | Andrei Miulescu <lusu777@gmail.com> | 2018-08-12 21:04:47 +1000 |
commit | e8eb78617c17d8b743fcb17c0790c42e11cd5db5 (patch) | |
tree | 44f4f66047b7be5217d77f7fb34e34fb750e7f99 /pkg/commands | |
parent | e65ddd7b6facfaf3ebc8b022f26066bdf96a28b0 (diff) |
Mid refactor change some more stuff
Diffstat (limited to 'pkg/commands')
-rw-r--r-- | pkg/commands/git.go | 175 | ||||
-rw-r--r-- | pkg/commands/git_structs.go | 34 | ||||
-rw-r--r-- | pkg/commands/os.go | 27 |
3 files changed, 169 insertions, 67 deletions
diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 1afe4ae8a..5bcf2334e 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -10,7 +10,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/git" + "github.com/jesseduffield/lazygit/pkg/utils" gitconfig "github.com/tcnksm/go-gitconfig" gogit "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing/object" @@ -51,7 +51,7 @@ func (c *GitCommand) GitIgnore(filename string) { func (c *GitCommand) GetStashEntries() []StashEntry { stashEntries := make([]StashEntry, 0) rawString, _ := c.OSCommand.RunDirectCommand("git stash list --pretty='%gs'") - for i, line := range splitLines(rawString) { + for i, line := range utils.SplitLines(rawString) { stashEntries = append(stashEntries, stashEntryFromLine(line, i)) } return stashEntries @@ -67,7 +67,7 @@ func stashEntryFromLine(line string, index int) StashEntry { // GetStashEntryDiff stash diff func (c *GitCommand) GetStashEntryDiff(index int) (string, error) { - return runCommand("git stash show -p --color stash@{" + fmt.Sprint(index) + "}") + return c.OSCommand.RunCommand("git stash show -p --color stash@{" + fmt.Sprint(index) + "}") } func includes(array []string, str string) bool { @@ -81,8 +81,8 @@ func includes(array []string, str string) bool { // GetStatusFiles git status files func (c *GitCommand) GetStatusFiles() []GitFile { - statusOutput, _ := getGitStatus() - statusStrings := splitLines(statusOutput) + statusOutput, _ := c.GitStatus() + statusStrings := utils.SplitLines(statusOutput) gitFiles := make([]GitFile, 0) for _, statusString := range statusStrings { @@ -90,7 +90,7 @@ func (c *GitCommand) GetStatusFiles() []GitFile { stagedChange := change[0:1] unstagedChange := statusString[1:2] filename := statusString[3:] - tracked := !f([]string{"??", "A "}, change) + tracked := !includes([]string{"??", "A "}, change) gitFile := GitFile{ Name: filename, DisplayString: statusString, @@ -102,7 +102,7 @@ func (c *GitCommand) GetStatusFiles() []GitFile { } gitFiles = append(gitFiles, gitFile) } - objectLog(gitFiles) + c.Log.Info(gitFiles) // TODO: use a dumper-esque log here return gitFiles } @@ -162,6 +162,11 @@ func (c *GitCommand) verifyInGitRepo() { } } +// GetBranchName branch name +func (c *GitCommand) GetBranchName() (string, error) { + return c.OSCommand.RunDirectCommand("git symbolic-ref --short HEAD") +} + func (c *GitCommand) navigateToRepoRootDirectory() { _, err := os.Stat(".git") for os.IsNotExist(err) { @@ -172,7 +177,7 @@ func (c *GitCommand) navigateToRepoRootDirectory() { } func (c *GitCommand) setupWorktree() { - r, err := git.PlainOpen(".") + r, err := gogit.PlainOpen(".") if err != nil { panic(err) } @@ -187,17 +192,17 @@ func (c *GitCommand) setupWorktree() { // ResetHard does the equivalent of `git reset --hard HEAD` func (c *GitCommand) ResetHard() error { - return c.Worktree.Reset(&gogit.ResetOptions{Mode: git.HardReset}) + return c.Worktree.Reset(&gogit.ResetOptions{Mode: gogit.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") + 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") + pullableCount, err := c.OSCommand.RunDirectCommand("git rev-list head..@{u} --count") if err != nil { return "?", "?" } @@ -207,18 +212,11 @@ func (c *GitCommand) UpstreamDifferenceCount() (string, string) { // 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") + 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() + return utils.SplitLines(pushables) } // BranchIncluded states whether a branch is included in a list of branches, @@ -234,60 +232,49 @@ func (c *GitCommand) BranchIncluded(branchName string, branches []Branch) bool { // 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 + "\"") + 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") + 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) + 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) + 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) + return c.OSCommand.RunCommand("git branch -d " + branch) } // ListStash list stash func (c *GitCommand) ListStash() (string, error) { - return c.OSCommand.runDirectCommand("git stash list") + 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) + 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 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 - }) + return c.OSCommand.RunDirectCommand("git merge --abort") } // 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") + sub, err := c.OSCommand.RunSubProcess("git", "commit") return "", nil } userName, err := gitconfig.Username() @@ -295,7 +282,7 @@ func (c *GitCommand) GitCommit(g *gocui.Gui, message string) (string, error) { return "", errNoUsername } userEmail, err := gitconfig.Email() - _, err = w.Commit(message, &git.CommitOptions{ + _, err = c.Worktree.Commit(message, &gogit.CommitOptions{ Author: &object.Signature{ Name: userName, Email: userEmail, @@ -321,7 +308,7 @@ func (c *GitCommand) GitPush() (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 + "\"") + return c.OSCommand.RunDirectCommand("git reset --soft HEAD^ && git commit --amend -m \"" + message + "\"") } // SquashFixupCommit squashes a 'FIXUP' commit into the commit beneath it, @@ -336,18 +323,18 @@ func (c *GitCommand) SquashFixupCommit(branchName string, shaValue string) (stri } ret := "" for _, command := range commands { - devLog(command) - output, err := c.OSCommand.runDirectCommand(command) + c.Log.Info(command) + output, err := c.OSCommand.RunDirectCommand(command) ret += output if err != nil { - devLog(ret) + c.Log.Info(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 - output, _ = c.OSCommand.RunDirectCommand("git branch -d " + shaValue) + output, _ := c.OSCommand.RunDirectCommand("git branch -d " + shaValue) ret += output output, _ = c.OSCommand.RunDirectCommand("git checkout " + branchName) ret += output @@ -357,12 +344,12 @@ func (c *GitCommand) SquashFixupCommit(branchName string, shaValue string) (stri // CatFile obtain the contents of a file func (c *GitCommand) CatFile(file string) (string, error) { - return c.OSCommand.runDirectCommand("cat " + file) + return c.OSCommand.RunDirectCommand("cat " + file) } // StageFile stages a file func (c *GitCommand) StageFile(file string) error { - _, err := c.OSCommand.runCommand("git add " + file) + _, err := c.OSCommand.RunCommand("git add " + file) return err } @@ -374,18 +361,18 @@ func (c *GitCommand) UnStageFile(file string, tracked bool) error { } else { command = "git rm --cached " } - _, err := c.OSCommand.runCommand(command + file) + _, 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") + 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") + output, err := c.OSCommand.RunCommand("git status --untracked-files=all") if err != nil { return false, err } @@ -396,11 +383,11 @@ func (c *GitCommand) IsInMergeState() (bool, error) { 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) + _, 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) + _, err := c.OSCommand.RunCommand("git checkout " + file.Name) return err } @@ -410,24 +397,24 @@ func (c *GitCommand) Checkout(branch string, force bool) (string, error) { if force { forceArg = "--force " } - return c.OSCommand.runCommand("git checkout " + forceArg + branch) + 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) +func (c *GitCommand) AddPatch(g *gocui.Gui, filename string) (*exec.Cmd, error) { + return c.OSCommand.RunSubProcess("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) + 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 { +// 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) @@ -454,3 +441,73 @@ func includesInt(list []int, a int) bool { } return false } + +// GetCommits obtains the commits of the current branch +func (c *GitCommand) GetCommits() []Commit { + pushables := gogit.GetCommitsToPush() + log := getLog() + commits := make([]Commit, 0) + // now we can split it up and turn it into commits + lines := utils.RplitLines(log) + for _, line := range lines { + splitLine := strings.Split(line, " ") + sha := splitLine[0] + pushed := includesString(pushables, sha) + commits = append(commits, Commit{ + Sha: sha, + Name: strings.Join(splitLine[1:], " "), + Pushed: pushed, + DisplayString: strings.Join(splitLine, " "), + }) + } + return commits +} + +// GetLog gets the git log (currently limited to 30 commits for performance +// until we work out lazy loading +func (c *GitCommand) GetLog() string { + // currently limiting to 30 for performance reasons + // TODO: add lazyloading when you scroll down + result, err := c.OSCommand.RunDirectCommand("git log --oneline -30") + if err != nil { + // assume if there is an error there are no commits yet for this branch + return "" + } + return result +} + +// Ignore adds a file to the gitignore for the repo +func (c *GitCommand) Ignore(filename string) { + if _, err := c.OSCommand.RunDirectCommand("echo '" + filename + "' >> .gitignore"); err != nil { + panic(err) + } +} + +// Show shows the diff of a commit +func (c *GitCommand) Show(sha string) string { + result, err := c.OSCommand.RunDirectCommand("git show --color " + sha) + if err != nil { + panic(err) + } + return result +} + +// Diff returns the diff of a file +func (c *GitCommand) Diff(file GitFile) string { + cachedArg := "" + if file.HasStagedChanges && !file.HasUnstagedChanges { + cachedArg = "--cached " + } + deletedArg := "" + if file.Deleted { + deletedArg = "-- " + } + trackedArg := "" + if !file.Tracked && !file.HasStagedChanges { + trackedArg = "--no-index /dev/null " + } + command := "git diff --color " + cachedArg + deletedArg + trackedArg + file.Name + // for now we assume an error means the file was deleted + s, _ := c.OSCommand.RunCommand(command) + return s +} diff --git a/pkg/commands/git_structs.go b/pkg/commands/git_structs.go new file mode 100644 index 000000000..dd28d15fa --- /dev/null +++ b/pkg/commands/git_structs.go @@ -0,0 +1,34 @@ +package commands + +// File : A staged/unstaged file +// TODO: decide whether to give all of these the Git prefix +type GitFile struct { + Name string + HasStagedChanges bool + HasUnstagedChanges bool + Tracked bool + Deleted bool + HasMergeConflicts bool + DisplayString string +} + +// Commit : A git commit +type Commit struct { + Sha string + Name string + Pushed bool + DisplayString string +} + +// StashEntry : A git stash entry +type StashEntry struct { + Index int + Name string + DisplayString string +} + +// Branch : A git branch +type Branch struct { + Name string + Recency string +} diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 4e7c136a9..e7fe4515f 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -85,7 +85,8 @@ func getPlatform() platform { } } -func (c *OSCommand) getOpenCommand() (string, string, error) { +// GetOpenCommand get open command +func (c *OSCommand) GetOpenCommand() (string, string, error) { //NextStep open equivalents: xdg-open (linux), cygstart (cygwin), open (OSX) trailMap := map[string]string{ "xdg-open": " &>/dev/null &", @@ -93,7 +94,7 @@ func (c *OSCommand) getOpenCommand() (string, string, error) { "open": "", } for name, trail := range trailMap { - if out, _ := c.runCommand("which " + name); out != "exit status 1" { + if out, _ := c.RunCommand("which " + name); out != "exit status 1" { return name, trail, nil } } @@ -103,22 +104,22 @@ func (c *OSCommand) getOpenCommand() (string, string, error) { // VsCodeOpenFile opens the file in code, with the -r flag to open in the // current window func (c *OSCommand) VsCodeOpenFile(g *gocui.Gui, filename string) (string, error) { - return c.runCommand("code -r " + filename) + return c.RunCommand("code -r " + filename) } // SublimeOpenFile opens the filein sublime // may be deprecated in the future func (c *OSCommand) SublimeOpenFile(g *gocui.Gui, filename string) (string, error) { - return c.runCommand("subl " + filename) + return c.RunCommand("subl " + filename) } // OpenFile opens a file with the given func (c *OSCommand) OpenFile(g *gocui.Gui, filename string) (string, error) { - cmdName, cmdTrail, err := getOpenCommand() + cmdName, cmdTrail, err := c.GetOpenCommand() if err != nil { return "", err } - return c.runCommand(cmdName + " " + filename + cmdTrail) + return c.RunCommand(cmdName + " " + filename + cmdTrail) } // EditFile opens a file in a subprocess using whatever editor is available, @@ -132,13 +133,23 @@ func (c *OSCommand) editFile(g *gocui.Gui, filename string) (string, error) { editor = os.Getenv("EDITOR") } if editor == "" { - if _, err := c.OSCommand.runCommand("which vi"); err == nil { + if _, err := c.RunCommand("which vi"); err == nil { editor = "vi" } } if editor == "" { return "", createErrorPanel(g, "No editor defined in $VISUAL, $EDITOR, or git config.") } - runSubProcess(g, editor, filename) + c.RunSubProcess(editor, filename) return "", nil } + +// RunSubProcess iniRunSubProcessrocess then tells the Gui to switch to it +func (c *OSCommand) RunSubProcess(cmdName string, commandArgs ...string) (*exec.Cmd, error) { + subprocess := exec.Command(cmdName, commandArgs...) + subprocess.Stdin = os.Stdin + subprocess.Stdout = os.Stdout + subprocess.Stderr = os.Stderr + + return subprocess, nil +} |