1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-30 03:23:08 +03:00

staging lines and hunks

This commit is contained in:
Jesse Duffield
2018-12-05 19:33:46 +11:00
parent 658e5a9faf
commit c0f9795910
21 changed files with 703 additions and 99 deletions

View File

@ -3,7 +3,6 @@ package commands
import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
@ -486,7 +485,6 @@ func (c *GitCommand) getMergeBase() (string, error) {
output, err := c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git merge-base HEAD %s", baseBranch))
if err != nil {
// swallowing error because it's not a big deal; probably because there are no commits yet
c.Log.Error(err)
}
return output, nil
}
@ -595,24 +593,13 @@ func (c *GitCommand) Diff(file *File, plain bool) string {
}
func (c *GitCommand) ApplyPatch(patch string) (string, error) {
content := []byte(patch)
tmpfile, err := ioutil.TempFile("", "patch")
filename, err := c.OSCommand.CreateTempFile("patch", patch)
if err != nil {
c.Log.Error(err)
return "", errors.New("Could not create patch file") // TODO: i18n
}
defer os.Remove(tmpfile.Name()) // clean up
if _, err := tmpfile.Write(content); err != nil {
c.Log.Error(err)
return "", err
}
if err := tmpfile.Close(); err != nil {
c.Log.Error(err)
return "", err
}
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git apply --cached %s", tmpfile.Name()))
defer func() { _ = c.OSCommand.RemoveFile(filename) }()
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git apply --cached %s", filename))
}

View File

@ -1770,6 +1770,7 @@ func TestGitCommandDiff(t *testing.T) {
testName string
command func(string, ...string) *exec.Cmd
file *File
plain bool
}
scenarios := []scenario{
@ -1786,6 +1787,22 @@ func TestGitCommandDiff(t *testing.T) {
HasStagedChanges: false,
Tracked: true,
},
false,
},
{
"Default case",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"diff", "--", "test.txt"}, args)
return exec.Command("echo")
},
&File{
Name: "test.txt",
HasStagedChanges: false,
Tracked: true,
},
true,
},
{
"All changes staged",
@ -1801,6 +1818,7 @@ func TestGitCommandDiff(t *testing.T) {
HasUnstagedChanges: false,
Tracked: true,
},
false,
},
{
"File not tracked and file has no staged changes",
@ -1815,6 +1833,7 @@ func TestGitCommandDiff(t *testing.T) {
HasStagedChanges: false,
Tracked: false,
},
false,
},
}
@ -1822,7 +1841,7 @@ func TestGitCommandDiff(t *testing.T) {
t.Run(s.testName, func(t *testing.T) {
gitCmd := newDummyGitCommand()
gitCmd.OSCommand.command = s.command
gitCmd.Diff(s.file, false)
gitCmd.Diff(s.file, s.plain)
})
}
}
@ -1979,3 +1998,61 @@ func TestGitCommandCurrentBranchName(t *testing.T) {
})
}
}
func TestGitCommandApplyPatch(t *testing.T) {
type scenario struct {
testName string
command func(string, ...string) *exec.Cmd
test func(string, error)
}
scenarios := []scenario{
{
"valid case",
func(cmd string, args ...string) *exec.Cmd {
assert.Equal(t, "git", cmd)
assert.EqualValues(t, []string{"apply", "--cached"}, args[0:2])
filename := args[2]
content, err := ioutil.ReadFile(filename)
assert.NoError(t, err)
assert.Equal(t, "test", string(content))
return exec.Command("echo", "done")
},
func(output string, err error) {
assert.NoError(t, err)
assert.EqualValues(t, "done\n", output)
},
},
{
"command returns error",
func(cmd string, args ...string) *exec.Cmd {
assert.Equal(t, "git", cmd)
assert.EqualValues(t, []string{"apply", "--cached"}, args[0:2])
filename := args[2]
// TODO: Ideally we want to mock out OSCommand here so that we're not
// double handling testing it's CreateTempFile functionality,
// but it is going to take a bit of work to make a proper mock for it
// so I'm leaving it for another PR
content, err := ioutil.ReadFile(filename)
assert.NoError(t, err)
assert.Equal(t, "test", string(content))
return exec.Command("test")
},
func(output string, err error) {
assert.Error(t, err)
},
},
}
for _, s := range scenarios {
t.Run(s.testName, func(t *testing.T) {
gitCmd := newDummyGitCommand()
gitCmd.OSCommand.command = s.command
s.test(gitCmd.ApplyPatch("test"))
})
}
}

View File

@ -2,6 +2,7 @@ package commands
import (
"errors"
"io/ioutil"
"os"
"os/exec"
"strings"
@ -176,3 +177,28 @@ func (c *OSCommand) AppendLineToFile(filename, line string) error {
_, err = f.WriteString("\n" + line)
return err
}
// CreateTempFile writes a string to a new temp file and returns the file's name
func (c *OSCommand) CreateTempFile(filename, content string) (string, error) {
tmpfile, err := ioutil.TempFile("", filename)
if err != nil {
c.Log.Error(err)
return "", err
}
if _, err := tmpfile.Write([]byte(content)); err != nil {
c.Log.Error(err)
return "", err
}
if err := tmpfile.Close(); err != nil {
c.Log.Error(err)
return "", err
}
return tmpfile.Name(), nil
}
// RemoveFile removes a file at the specified path
func (c *OSCommand) RemoveFile(filename string) error {
return os.Remove(filename)
}

View File

@ -1,6 +1,7 @@
package commands
import (
"io/ioutil"
"os"
"os/exec"
"testing"
@ -364,3 +365,34 @@ func TestOSCommandFileType(t *testing.T) {
_ = os.RemoveAll(s.path)
}
}
func TestOSCommandCreateTempFile(t *testing.T) {
type scenario struct {
testName string
filename string
content string
test func(string, error)
}
scenarios := []scenario{
{
"valid case",
"filename",
"content",
func(path string, err error) {
assert.NoError(t, err)
content, err := ioutil.ReadFile(path)
assert.NoError(t, err)
assert.Equal(t, "content", string(content))
},
},
}
for _, s := range scenarios {
t.Run(s.testName, func(t *testing.T) {
s.test(newDummyOSCommand().CreateTempFile(s.filename, s.content))
})
}
}