mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-31 14:24:25 +03:00
Merge branch 'master' into feature/informative-commit-colors
This commit is contained in:
@ -14,9 +14,9 @@ type Branch struct {
|
||||
Recency string
|
||||
}
|
||||
|
||||
// GetDisplayString returns the dispaly string of branch
|
||||
func (b *Branch) GetDisplayString() string {
|
||||
return utils.WithPadding(b.Recency, 4) + utils.ColoredString(b.Name, b.GetColor())
|
||||
// GetDisplayStrings returns the dispaly string of branch
|
||||
func (b *Branch) GetDisplayStrings() []string {
|
||||
return []string{b.Recency, utils.ColoredString(b.Name, b.GetColor())}
|
||||
}
|
||||
|
||||
// GetColor branch color
|
||||
|
30
pkg/commands/commit.go
Normal file
30
pkg/commands/commit.go
Normal file
@ -0,0 +1,30 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// Commit : A git commit
|
||||
type Commit struct {
|
||||
Sha string
|
||||
Name string
|
||||
Pushed bool
|
||||
Merged bool
|
||||
DisplayString string
|
||||
}
|
||||
|
||||
func (c *Commit) GetDisplayStrings() []string {
|
||||
red := color.New(color.FgRed)
|
||||
yellow := color.New(color.FgGreen)
|
||||
green := color.New(color.FgYellow)
|
||||
white := color.New(color.FgWhite)
|
||||
|
||||
shaColor := yellow
|
||||
if c.Pushed {
|
||||
shaColor = red
|
||||
} else if !c.Merged {
|
||||
shaColor = green
|
||||
}
|
||||
|
||||
return []string{shaColor.Sprint(c.Sha), white.Sprint(c.Name)}
|
||||
}
|
36
pkg/commands/file.go
Normal file
36
pkg/commands/file.go
Normal file
@ -0,0 +1,36 @@
|
||||
package commands
|
||||
|
||||
import "github.com/fatih/color"
|
||||
|
||||
// File : A file from git status
|
||||
// duplicating this for now
|
||||
type File struct {
|
||||
Name string
|
||||
HasStagedChanges bool
|
||||
HasUnstagedChanges bool
|
||||
Tracked bool
|
||||
Deleted bool
|
||||
HasMergeConflicts bool
|
||||
DisplayString string
|
||||
Type string // one of 'file', 'directory', and 'other'
|
||||
}
|
||||
|
||||
// GetDisplayStrings returns the display string of a file
|
||||
func (f *File) GetDisplayStrings() []string {
|
||||
// potentially inefficient to be instantiating these color
|
||||
// objects with each render
|
||||
red := color.New(color.FgRed)
|
||||
green := color.New(color.FgGreen)
|
||||
if !f.Tracked && !f.HasStagedChanges {
|
||||
return []string{red.Sprint(f.DisplayString)}
|
||||
}
|
||||
|
||||
output := green.Sprint(f.DisplayString[0:1])
|
||||
output += red.Sprint(f.DisplayString[1:3])
|
||||
if f.HasUnstagedChanges {
|
||||
output += red.Sprint(f.Name)
|
||||
} else {
|
||||
output += green.Sprint(f.Name)
|
||||
}
|
||||
return []string{output}
|
||||
}
|
@ -65,6 +65,7 @@ type GitCommand struct {
|
||||
Tr *i18n.Localizer
|
||||
getGlobalGitConfig func(string) (string, error)
|
||||
getLocalGitConfig func(string) (string, error)
|
||||
removeFile func(string) error
|
||||
}
|
||||
|
||||
// NewGitCommand it runs git commands
|
||||
@ -104,17 +105,17 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer)
|
||||
}
|
||||
|
||||
// GetStashEntries stash entryies
|
||||
func (c *GitCommand) GetStashEntries() []StashEntry {
|
||||
func (c *GitCommand) GetStashEntries() []*StashEntry {
|
||||
rawString, _ := c.OSCommand.RunCommandWithOutput("git stash list --pretty='%gs'")
|
||||
stashEntries := []StashEntry{}
|
||||
stashEntries := []*StashEntry{}
|
||||
for i, line := range utils.SplitLines(rawString) {
|
||||
stashEntries = append(stashEntries, stashEntryFromLine(line, i))
|
||||
}
|
||||
return stashEntries
|
||||
}
|
||||
|
||||
func stashEntryFromLine(line string, index int) StashEntry {
|
||||
return StashEntry{
|
||||
func stashEntryFromLine(line string, index int) *StashEntry {
|
||||
return &StashEntry{
|
||||
Name: line,
|
||||
Index: index,
|
||||
DisplayString: line,
|
||||
@ -127,10 +128,10 @@ func (c *GitCommand) GetStashEntryDiff(index int) (string, error) {
|
||||
}
|
||||
|
||||
// GetStatusFiles git status files
|
||||
func (c *GitCommand) GetStatusFiles() []File {
|
||||
func (c *GitCommand) GetStatusFiles() []*File {
|
||||
statusOutput, _ := c.GitStatus()
|
||||
statusStrings := utils.SplitLines(statusOutput)
|
||||
files := []File{}
|
||||
files := []*File{}
|
||||
|
||||
for _, statusString := range statusStrings {
|
||||
change := statusString[0:2]
|
||||
@ -140,7 +141,7 @@ func (c *GitCommand) GetStatusFiles() []File {
|
||||
_, untracked := map[string]bool{"??": true, "A ": true, "AM": true}[change]
|
||||
_, hasNoStagedChanges := map[string]bool{" ": true, "U": true, "?": true}[stagedChange]
|
||||
|
||||
file := File{
|
||||
file := &File{
|
||||
Name: filename,
|
||||
DisplayString: statusString,
|
||||
HasStagedChanges: !hasNoStagedChanges,
|
||||
@ -168,7 +169,7 @@ func (c *GitCommand) StashSave(message string) error {
|
||||
}
|
||||
|
||||
// MergeStatusFiles merge status files
|
||||
func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []File) []File {
|
||||
func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []*File) []*File {
|
||||
if len(oldFiles) == 0 {
|
||||
return newFiles
|
||||
}
|
||||
@ -176,7 +177,7 @@ func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []File) []File {
|
||||
appendedIndexes := []int{}
|
||||
|
||||
// retain position of files we already could see
|
||||
result := []File{}
|
||||
result := []*File{}
|
||||
for _, oldFile := range oldFiles {
|
||||
for newIndex, newFile := range newFiles {
|
||||
if oldFile.Name == newFile.Name {
|
||||
@ -231,13 +232,18 @@ 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.RunCommandWithOutput("git rev-list @{u}..head --abbrev-commit")
|
||||
// to the remote branch of the current branch, a map is returned to ease look up
|
||||
func (c *GitCommand) GetCommitsToPush() map[string]bool {
|
||||
pushables := map[string]bool{}
|
||||
o, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..head --abbrev-commit")
|
||||
if err != nil {
|
||||
return []string{}
|
||||
return pushables
|
||||
}
|
||||
return utils.SplitLines(pushables)
|
||||
for _, p := range utils.SplitLines(o) {
|
||||
pushables[p] = true
|
||||
}
|
||||
|
||||
return pushables
|
||||
}
|
||||
|
||||
// RenameCommit renames the topmost commit with the given name
|
||||
@ -407,18 +413,18 @@ func (c *GitCommand) IsInMergeState() (bool, error) {
|
||||
}
|
||||
|
||||
// RemoveFile directly
|
||||
func (c *GitCommand) RemoveFile(file File) error {
|
||||
func (c *GitCommand) RemoveFile(file *File) error {
|
||||
// if the file isn't tracked, we assume you want to delete it
|
||||
if file.HasStagedChanges {
|
||||
if err := c.OSCommand.RunCommand("git reset -- " + file.Name); err != nil {
|
||||
if err := c.OSCommand.RunCommand(fmt.Sprintf("git reset -- %s", file.Name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !file.Tracked {
|
||||
return os.RemoveAll(file.Name)
|
||||
return c.removeFile(file.Name)
|
||||
}
|
||||
// if the file is tracked, we assume you want to just check it out
|
||||
return c.OSCommand.RunCommand("git checkout -- " + file.Name)
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git checkout -- %s", file.Name))
|
||||
}
|
||||
|
||||
// Checkout checks out a branch, with --force if you set the force arg to true
|
||||
@ -427,7 +433,7 @@ func (c *GitCommand) Checkout(branch string, force bool) error {
|
||||
if force {
|
||||
forceArg = "--force "
|
||||
}
|
||||
return c.OSCommand.RunCommand("git checkout " + forceArg + branch)
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git checkout %s %s", forceArg, branch))
|
||||
}
|
||||
|
||||
// AddPatch prepares a subprocess for adding a patch by patch
|
||||
@ -450,16 +456,7 @@ func (c *GitCommand) PrepareCommitAmendSubProcess() *exec.Cmd {
|
||||
// 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.RunCommandWithOutput("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 " + branchName)
|
||||
}
|
||||
|
||||
func includesString(list []string, a string) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 %s", branchName))
|
||||
}
|
||||
|
||||
func (c *GitCommand) getMergeBase() string {
|
||||
@ -472,17 +469,18 @@ func (c *GitCommand) getMergeBase() string {
|
||||
}
|
||||
|
||||
// GetCommits obtains the commits of the current branch
|
||||
func (c *GitCommand) GetCommits() []Commit {
|
||||
func (c *GitCommand) GetCommits() []*Commit {
|
||||
pushables := c.GetCommitsToPush()
|
||||
log := c.GetLog()
|
||||
// now we can split it up and turn it into commits
|
||||
|
||||
lines := utils.SplitLines(log)
|
||||
commits := make([]Commit, len(lines))
|
||||
commits := make([]*Commit, len(lines))
|
||||
// now we can split it up and turn it into commits
|
||||
for i, line := range lines {
|
||||
splitLine := strings.Split(line, " ")
|
||||
sha := splitLine[0]
|
||||
pushed := !includesString(pushables, sha)
|
||||
commits[i] = Commit{
|
||||
_, pushed := pushables[sha]
|
||||
commits[i] = &Commit{
|
||||
Sha: sha,
|
||||
Name: strings.Join(splitLine[1:], " "),
|
||||
Pushed: pushed,
|
||||
@ -493,7 +491,7 @@ func (c *GitCommand) GetCommits() []Commit {
|
||||
return commits
|
||||
}
|
||||
|
||||
func (c *GitCommand) setCommitMergedStatuses(commits []Commit) []Commit {
|
||||
func (c *GitCommand) setCommitMergedStatuses(commits []*Commit) []*Commit {
|
||||
ancestor := c.getMergeBase()
|
||||
if ancestor == "" {
|
||||
return commits
|
||||
@ -518,6 +516,7 @@ func (c *GitCommand) GetLog() string {
|
||||
// assume if there is an error there are no commits yet for this branch
|
||||
return ""
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -536,7 +535,7 @@ func (c *GitCommand) Show(sha string) string {
|
||||
}
|
||||
|
||||
// Diff returns the diff of a file
|
||||
func (c *GitCommand) Diff(file File) string {
|
||||
func (c *GitCommand) Diff(file *File) string {
|
||||
cachedArg := ""
|
||||
fileName := c.OSCommand.Quote(file.Name)
|
||||
if file.HasStagedChanges && !file.HasUnstagedChanges {
|
||||
|
@ -1,33 +1,5 @@
|
||||
package commands
|
||||
|
||||
// File : A staged/unstaged file
|
||||
type File struct {
|
||||
Name string
|
||||
HasStagedChanges bool
|
||||
HasUnstagedChanges bool
|
||||
Tracked bool
|
||||
Deleted bool
|
||||
HasMergeConflicts bool
|
||||
DisplayString string
|
||||
Type string // one of 'file', 'directory', and 'other'
|
||||
}
|
||||
|
||||
// Commit : A git commit
|
||||
type Commit struct {
|
||||
Sha string
|
||||
Name string
|
||||
Pushed bool
|
||||
Merged bool
|
||||
DisplayString string
|
||||
}
|
||||
|
||||
// StashEntry : A git stash entry
|
||||
type StashEntry struct {
|
||||
Index int
|
||||
Name string
|
||||
DisplayString string
|
||||
}
|
||||
|
||||
// Conflict : A git conflict with a start middle and end corresponding to line
|
||||
// numbers in the file where the conflict bars appear
|
||||
type Conflict struct {
|
||||
|
@ -61,6 +61,7 @@ func newDummyGitCommand() *GitCommand {
|
||||
Tr: i18n.NewLocalizer(newDummyLog()),
|
||||
getGlobalGitConfig: func(string) (string, error) { return "", nil },
|
||||
getLocalGitConfig: func(string) (string, error) { return "", nil },
|
||||
removeFile: func(string) error { return nil },
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +276,7 @@ func TestGitCommandGetStashEntries(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
command func(string, ...string) *exec.Cmd
|
||||
test func([]StashEntry)
|
||||
test func([]*StashEntry)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
@ -284,7 +285,7 @@ func TestGitCommandGetStashEntries(t *testing.T) {
|
||||
func(string, ...string) *exec.Cmd {
|
||||
return exec.Command("echo")
|
||||
},
|
||||
func(entries []StashEntry) {
|
||||
func(entries []*StashEntry) {
|
||||
assert.Len(t, entries, 0)
|
||||
},
|
||||
},
|
||||
@ -293,8 +294,8 @@ func TestGitCommandGetStashEntries(t *testing.T) {
|
||||
func(string, ...string) *exec.Cmd {
|
||||
return exec.Command("echo", "WIP on add-pkg-commands-test: 55c6af2 increase parallel build\nWIP on master: bb86a3f update github template")
|
||||
},
|
||||
func(entries []StashEntry) {
|
||||
expected := []StashEntry{
|
||||
func(entries []*StashEntry) {
|
||||
expected := []*StashEntry{
|
||||
{
|
||||
0,
|
||||
"WIP on add-pkg-commands-test: 55c6af2 increase parallel build",
|
||||
@ -341,7 +342,7 @@ func TestGitCommandGetStatusFiles(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
command func(string, ...string) *exec.Cmd
|
||||
test func([]File)
|
||||
test func([]*File)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
@ -350,7 +351,7 @@ func TestGitCommandGetStatusFiles(t *testing.T) {
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
return exec.Command("echo")
|
||||
},
|
||||
func(files []File) {
|
||||
func(files []*File) {
|
||||
assert.Len(t, files, 0)
|
||||
},
|
||||
},
|
||||
@ -362,10 +363,10 @@ func TestGitCommandGetStatusFiles(t *testing.T) {
|
||||
"MM file1.txt\nA file3.txt\nAM file2.txt\n?? file4.txt",
|
||||
)
|
||||
},
|
||||
func(files []File) {
|
||||
func(files []*File) {
|
||||
assert.Len(t, files, 4)
|
||||
|
||||
expected := []File{
|
||||
expected := []*File{
|
||||
{
|
||||
Name: "file1.txt",
|
||||
HasStagedChanges: true,
|
||||
@ -463,22 +464,22 @@ func TestGitCommandCommitAmend(t *testing.T) {
|
||||
func TestGitCommandMergeStatusFiles(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
oldFiles []File
|
||||
newFiles []File
|
||||
test func([]File)
|
||||
oldFiles []*File
|
||||
newFiles []*File
|
||||
test func([]*File)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
"Old file and new file are the same",
|
||||
[]File{},
|
||||
[]File{
|
||||
[]*File{},
|
||||
[]*File{
|
||||
{
|
||||
Name: "new_file.txt",
|
||||
},
|
||||
},
|
||||
func(files []File) {
|
||||
expected := []File{
|
||||
func(files []*File) {
|
||||
expected := []*File{
|
||||
{
|
||||
Name: "new_file.txt",
|
||||
},
|
||||
@ -490,7 +491,7 @@ func TestGitCommandMergeStatusFiles(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"Several files to merge, with some identical",
|
||||
[]File{
|
||||
[]*File{
|
||||
{
|
||||
Name: "new_file1.txt",
|
||||
},
|
||||
@ -501,7 +502,7 @@ func TestGitCommandMergeStatusFiles(t *testing.T) {
|
||||
Name: "new_file3.txt",
|
||||
},
|
||||
},
|
||||
[]File{
|
||||
[]*File{
|
||||
{
|
||||
Name: "new_file4.txt",
|
||||
},
|
||||
@ -512,8 +513,8 @@ func TestGitCommandMergeStatusFiles(t *testing.T) {
|
||||
Name: "new_file1.txt",
|
||||
},
|
||||
},
|
||||
func(files []File) {
|
||||
expected := []File{
|
||||
func(files []*File) {
|
||||
expected := []*File{
|
||||
{
|
||||
Name: "new_file1.txt",
|
||||
},
|
||||
@ -551,7 +552,7 @@ func TestGitCommandUpstreamDifferentCount(t *testing.T) {
|
||||
{
|
||||
"Can't retrieve pushable count",
|
||||
func(string, ...string) *exec.Cmd {
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
func(pushableCount string, pullableCount string) {
|
||||
assert.EqualValues(t, "?", pushableCount)
|
||||
@ -562,7 +563,7 @@ func TestGitCommandUpstreamDifferentCount(t *testing.T) {
|
||||
"Can't retrieve pullable count",
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
if args[1] == "head..@{u}" {
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
}
|
||||
|
||||
return exec.Command("echo")
|
||||
@ -601,17 +602,17 @@ func TestGitCommandGetCommitsToPush(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
command func(string, ...string) *exec.Cmd
|
||||
test func([]string)
|
||||
test func(map[string]bool)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
"Can't retrieve pushable commits",
|
||||
func(string, ...string) *exec.Cmd {
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
func(pushables []string) {
|
||||
assert.EqualValues(t, []string{}, pushables)
|
||||
func(pushables map[string]bool) {
|
||||
assert.EqualValues(t, map[string]bool{}, pushables)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -619,9 +620,9 @@ func TestGitCommandGetCommitsToPush(t *testing.T) {
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
return exec.Command("echo", "8a2bb0e\n78976bc")
|
||||
},
|
||||
func(pushables []string) {
|
||||
func(pushables map[string]bool) {
|
||||
assert.Len(t, pushables, 2)
|
||||
assert.EqualValues(t, []string{"8a2bb0e", "78976bc"}, pushables)
|
||||
assert.EqualValues(t, map[string]bool{"8a2bb0e": true, "78976bc": true}, pushables)
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -872,7 +873,7 @@ func TestGitCommandCommit(t *testing.T) {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"commit", "-m", "test"}, args)
|
||||
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
func(string) (string, error) {
|
||||
return "false", nil
|
||||
@ -935,7 +936,7 @@ func TestGitCommandPush(t *testing.T) {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"push", "-u", "origin", "test"}, args)
|
||||
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
false,
|
||||
func(err error) {
|
||||
@ -967,7 +968,7 @@ func TestGitCommandSquashPreviousTwoCommits(t *testing.T) {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"reset", "--soft", "HEAD^"}, args)
|
||||
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
func(err error) {
|
||||
assert.NotNil(t, err)
|
||||
@ -983,7 +984,7 @@ func TestGitCommandSquashPreviousTwoCommits(t *testing.T) {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"commit", "--amend", "-m", "test"}, args)
|
||||
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
func(err error) {
|
||||
assert.NotNil(t, err)
|
||||
@ -1031,7 +1032,7 @@ func TestGitCommandSquashFixupCommit(t *testing.T) {
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
if len(args) > 0 && args[0] == "checkout" {
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
}
|
||||
|
||||
return exec.Command("echo")
|
||||
@ -1165,7 +1166,7 @@ func TestGitCommandIsInMergeState(t *testing.T) {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"status", "--untracked-files=all"}, args)
|
||||
|
||||
return exec.Command("exit", "1")
|
||||
return exec.Command("test")
|
||||
},
|
||||
func(isInMergeState bool, err error) {
|
||||
assert.Error(t, err)
|
||||
@ -1219,11 +1220,344 @@ func TestGitCommandIsInMergeState(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitCommandRemoveFile(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
command func() (func(string, ...string) *exec.Cmd, *[][]string)
|
||||
test func(*[][]string, error)
|
||||
file *File
|
||||
removeFile func(string) error
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
"An error occurred when resetting",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("test")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.Error(t, err)
|
||||
assert.Len(t, *cmdsCalled, 1)
|
||||
assert.EqualValues(t, *cmdsCalled, [][]string{
|
||||
{"reset", "--", "test"},
|
||||
})
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
HasStagedChanges: true,
|
||||
},
|
||||
func(string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
"An error occurred when removing file",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("test")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, "an error occurred when removing file")
|
||||
assert.Len(t, *cmdsCalled, 0)
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
Tracked: false,
|
||||
},
|
||||
func(string) error {
|
||||
return fmt.Errorf("an error occurred when removing file")
|
||||
},
|
||||
},
|
||||
{
|
||||
"An error occurred with checkout",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("test")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.Error(t, err)
|
||||
assert.Len(t, *cmdsCalled, 1)
|
||||
assert.EqualValues(t, *cmdsCalled, [][]string{
|
||||
{"checkout", "--", "test"},
|
||||
})
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
Tracked: true,
|
||||
HasStagedChanges: false,
|
||||
},
|
||||
func(string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
"Checkout only",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, *cmdsCalled, 1)
|
||||
assert.EqualValues(t, *cmdsCalled, [][]string{
|
||||
{"checkout", "--", "test"},
|
||||
})
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
Tracked: true,
|
||||
HasStagedChanges: false,
|
||||
},
|
||||
func(string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
"Reset and checkout",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, *cmdsCalled, 2)
|
||||
assert.EqualValues(t, *cmdsCalled, [][]string{
|
||||
{"reset", "--", "test"},
|
||||
{"checkout", "--", "test"},
|
||||
})
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
Tracked: true,
|
||||
HasStagedChanges: true,
|
||||
},
|
||||
func(string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
"Reset and remove",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, *cmdsCalled, 1)
|
||||
assert.EqualValues(t, *cmdsCalled, [][]string{
|
||||
{"reset", "--", "test"},
|
||||
})
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
Tracked: false,
|
||||
HasStagedChanges: true,
|
||||
},
|
||||
func(filename string) error {
|
||||
assert.Equal(t, "test", filename)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
"Remove only",
|
||||
func() (func(string, ...string) *exec.Cmd, *[][]string) {
|
||||
cmdsCalled := [][]string{}
|
||||
return func(cmd string, args ...string) *exec.Cmd {
|
||||
cmdsCalled = append(cmdsCalled, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
}, &cmdsCalled
|
||||
},
|
||||
func(cmdsCalled *[][]string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, *cmdsCalled, 0)
|
||||
},
|
||||
&File{
|
||||
Name: "test",
|
||||
Tracked: false,
|
||||
HasStagedChanges: false,
|
||||
},
|
||||
func(filename string) error {
|
||||
assert.Equal(t, "test", filename)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
var cmdsCalled *[][]string
|
||||
gitCmd := newDummyGitCommand()
|
||||
gitCmd.OSCommand.command, cmdsCalled = s.command()
|
||||
gitCmd.removeFile = s.removeFile
|
||||
s.test(cmdsCalled, gitCmd.RemoveFile(s.file))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitCommandCheckout(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
command func(string, ...string) *exec.Cmd
|
||||
test func(error)
|
||||
force bool
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
"Checkout",
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"checkout", "test"}, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
},
|
||||
func(err error) {
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Checkout forced",
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"checkout", "--force", "test"}, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
},
|
||||
func(err error) {
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
gitCmd := newDummyGitCommand()
|
||||
gitCmd.OSCommand.command = s.command
|
||||
s.test(gitCmd.Checkout("test", s.force))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitCommandGetBranchGraph(t *testing.T) {
|
||||
gitCmd := newDummyGitCommand()
|
||||
gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
assert.EqualValues(t, []string{"log", "--graph", "--color", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "-100", "test"}, args)
|
||||
|
||||
return exec.Command("echo")
|
||||
}
|
||||
|
||||
_, err := gitCmd.GetBranchGraph("test")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGitCommandGetCommits(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
command func(string, ...string) *exec.Cmd
|
||||
test func([]*Commit)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
"No data found",
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
|
||||
switch args[0] {
|
||||
case "rev-list":
|
||||
assert.EqualValues(t, []string{"rev-list", "@{u}..head", "--abbrev-commit"}, args)
|
||||
return exec.Command("echo")
|
||||
case "log":
|
||||
assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args)
|
||||
return exec.Command("echo")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
func(commits []*Commit) {
|
||||
assert.Len(t, commits, 0)
|
||||
},
|
||||
},
|
||||
{
|
||||
"GetCommits returns 2 commits, 1 pushed the other not",
|
||||
func(cmd string, args ...string) *exec.Cmd {
|
||||
assert.EqualValues(t, "git", cmd)
|
||||
|
||||
switch args[0] {
|
||||
case "rev-list":
|
||||
assert.EqualValues(t, []string{"rev-list", "@{u}..head", "--abbrev-commit"}, args)
|
||||
return exec.Command("echo", "8a2bb0e")
|
||||
case "log":
|
||||
assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args)
|
||||
return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
func(commits []*Commit) {
|
||||
assert.Len(t, commits, 2)
|
||||
assert.EqualValues(t, []*Commit{
|
||||
{
|
||||
Sha: "8a2bb0e",
|
||||
Name: "commit 1",
|
||||
Pushed: true,
|
||||
DisplayString: "8a2bb0e commit 1",
|
||||
},
|
||||
{
|
||||
Sha: "78976bc",
|
||||
Name: "commit 2",
|
||||
Pushed: false,
|
||||
DisplayString: "78976bc commit 2",
|
||||
},
|
||||
}, commits)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
gitCmd := newDummyGitCommand()
|
||||
gitCmd.OSCommand.command = s.command
|
||||
s.test(gitCmd.GetCommits())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitCommandDiff(t *testing.T) {
|
||||
gitCommand := newDummyGitCommand()
|
||||
assert.NoError(t, test.GenerateRepo("lots_of_diffs.sh"))
|
||||
|
||||
files := []File{
|
||||
files := []*File{
|
||||
{
|
||||
Name: "deleted_staged",
|
||||
HasStagedChanges: false,
|
||||
|
13
pkg/commands/stash_entry.go
Normal file
13
pkg/commands/stash_entry.go
Normal file
@ -0,0 +1,13 @@
|
||||
package commands
|
||||
|
||||
// StashEntry : A git stash entry
|
||||
type StashEntry struct {
|
||||
Index int
|
||||
Name string
|
||||
DisplayString string
|
||||
}
|
||||
|
||||
// GetDisplayStrings returns the dispaly string of branch
|
||||
func (s *StashEntry) GetDisplayStrings() []string {
|
||||
return []string{s.DisplayString}
|
||||
}
|
Reference in New Issue
Block a user