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

Merge branch 'master' into fix/tests

This commit is contained in:
Jesse Duffield
2018-09-03 21:20:17 +10:00
committed by GitHub
19 changed files with 219 additions and 142 deletions

View File

@ -422,6 +422,11 @@ func (c *GitCommand) PrepareCommitSubProcess() *exec.Cmd {
return c.OSCommand.PrepareSubProcess("git", "commit")
}
// PrepareCommitAmendSubProcess prepares a subprocess for `git commit --amend --allow-empty`
func (c *GitCommand) PrepareCommitAmendSubProcess() *exec.Cmd {
return c.OSCommand.PrepareSubProcess("git", "commit", "--amend", "--allow-empty")
}
// 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

View File

@ -189,6 +189,19 @@ func TestGitCommandStashSave(t *testing.T) {
assert.NoError(t, gitCmd.StashSave("A stash message"))
}
func TestGitCommandCommitAmend(t *testing.T) {
gitCmd := newDummyGitCommand()
gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"commit", "--amend", "--allow-empty"}, args)
return exec.Command("echo")
}
_, err := gitCmd.PrepareCommitAmendSubProcess().CombinedOutput()
assert.NoError(t, err)
}
func TestGitCommandMergeStatusFiles(t *testing.T) {
type scenario struct {
oldFiles []File

View File

@ -6,7 +6,8 @@ import (
"os/exec"
"strings"
"github.com/davecgh/go-spew/spew"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/mgutz/str"
@ -20,22 +21,25 @@ type Platform struct {
shell string
shellArg string
escapedQuote string
openCommand string
}
// OSCommand holds all the os commands
type OSCommand struct {
Log *logrus.Entry
Platform *Platform
Config config.AppConfigurer
command func(string, ...string) *exec.Cmd
getGlobalGitConfig func(string) (string, error)
getenv func(string) string
}
// NewOSCommand os command runner
func NewOSCommand(log *logrus.Entry) *OSCommand {
func NewOSCommand(log *logrus.Entry, config config.AppConfigurer) *OSCommand {
return &OSCommand{
Log: log,
Platform: getPlatform(),
Config: config,
command: exec.Command,
getGlobalGitConfig: gitconfig.Global,
getenv: os.Getenv,
@ -47,7 +51,6 @@ func (c *OSCommand) RunCommandWithOutput(command string) (string, error) {
c.Log.WithField("command", command).Info("RunCommand")
splitCmd := str.ToArgv(command)
c.Log.Info(splitCmd)
return sanitisedCommandOutput(
c.command(splitCmd[0], splitCmd[1:]...).CombinedOutput(),
)
@ -74,12 +77,9 @@ func (c *OSCommand) FileType(path string) string {
// RunDirectCommand wrapper around direct commands
func (c *OSCommand) RunDirectCommand(command string) (string, error) {
c.Log.WithField("command", command).Info("RunDirectCommand")
args := str.ToArgv(c.Platform.shellArg + " " + command)
c.Log.Info(spew.Sdump(args))
return sanitisedCommandOutput(
exec.
Command(c.Platform.shell, args...).
c.command(c.Platform.shell, c.Platform.shellArg, command).
CombinedOutput(),
)
}
@ -89,51 +89,24 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) {
if err != nil {
// errors like 'exit status 1' are not very useful so we'll create an error
// from the combined output
if outputString == "" {
return "", err
}
return outputString, errors.New(outputString)
}
return outputString, nil
}
// 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 &",
"cygstart": "",
"open": "",
}
for name, trail := range trailMap {
if err := c.RunCommand("which " + name); err == nil {
return name, trail, nil
}
}
return "", "", errors.New("Unsure what command to use to open this file")
}
// VsCodeOpenFile opens the file in code, with the -r flag to open in the
// current window
// each of these open files needs to have the same function signature because
// they're being passed as arguments into another function,
// but only editFile actually returns a *exec.Cmd
func (c *OSCommand) VsCodeOpenFile(filename string) (*exec.Cmd, error) {
return nil, c.RunCommand("code -r " + filename)
}
// SublimeOpenFile opens the filein sublime
// may be deprecated in the future
func (c *OSCommand) SublimeOpenFile(filename string) (*exec.Cmd, error) {
return nil, c.RunCommand("subl " + filename)
}
// OpenFile opens a file with the given
func (c *OSCommand) OpenFile(filename string) error {
cmdName, cmdTrail, err := c.getOpenCommand()
if err != nil {
return err
commandTemplate := c.Config.GetUserConfig().GetString("os.openCommand")
templateValues := map[string]string{
"filename": c.Quote(filename),
}
return c.RunCommand(cmdName + " " + c.Quote(filename) + cmdTrail) // TODO: test on linux
command := utils.ResolvePlaceholderString(commandTemplate, templateValues)
err := c.RunCommand(command)
return err
}
// EditFile opens a file in a subprocess using whatever editor is available,

View File

@ -12,5 +12,6 @@ func getPlatform() *Platform {
shell: "bash",
shellArg: "-c",
escapedQuote: "\"",
openCommand: "open {{filename}}",
}
}

View File

@ -5,11 +5,28 @@ import (
"os/exec"
"testing"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
yaml "gopkg.in/yaml.v2"
)
func newDummyOSCommand() *OSCommand {
return NewOSCommand(newDummyLog())
return NewOSCommand(newDummyLog(), newDummyAppConfig())
}
func newDummyAppConfig() *config.AppConfig {
appConfig := &config.AppConfig{
Name: "lazygit",
Version: "unversioned",
Commit: "",
BuildDate: "",
Debug: false,
BuildSource: "",
UserConfig: viper.New(),
}
_ = yaml.Unmarshal([]byte{}, appConfig.AppState)
return appConfig
}
func TestOSCommandRunCommandWithOutput(t *testing.T) {
@ -59,44 +76,6 @@ func TestOSCommandRunCommand(t *testing.T) {
}
}
func TestOSCommandGetOpenCommand(t *testing.T) {
type scenario struct {
command func(string, ...string) *exec.Cmd
test func(string, string, error)
}
scenarios := []scenario{
{
func(name string, arg ...string) *exec.Cmd {
return exec.Command("exit", "1")
},
func(name string, trail string, err error) {
assert.EqualError(t, err, "Unsure what command to use to open this file")
},
},
{
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "which", name)
assert.Len(t, arg, 1)
assert.Regexp(t, "xdg-open|cygstart|open", arg[0])
return exec.Command("echo")
},
func(name string, trail string, err error) {
assert.NoError(t, err)
assert.Regexp(t, "xdg-open|cygstart|open", name)
assert.Regexp(t, " \\&\\>/dev/null \\&|", trail)
},
},
}
for _, s := range scenarios {
OSCmd := newDummyOSCommand()
OSCmd.command = s.command
s.test(OSCmd.getOpenCommand())
}
}
func TestOSCommandOpenFile(t *testing.T) {
type scenario struct {
filename string
@ -111,29 +90,25 @@ func TestOSCommandOpenFile(t *testing.T) {
return exec.Command("exit", "1")
},
func(err error) {
assert.EqualError(t, err, "Unsure what command to use to open this file")
assert.Error(t, err)
},
},
{
"test",
func(name string, arg ...string) *exec.Cmd {
if name == "which" {
return exec.Command("echo")
}
switch len(arg) {
case 1:
assert.Regexp(t, "open|cygstart", name)
assert.EqualValues(t, "test", arg[0])
case 3:
assert.Equal(t, "xdg-open", name)
assert.EqualValues(t, "test", arg[0])
assert.Regexp(t, " \\&\\>/dev/null \\&|", arg[1])
assert.EqualValues(t, "&", arg[2])
default:
assert.Fail(t, "Unexisting command given")
}
assert.Equal(t, "open", name)
assert.Equal(t, []string{"test"}, arg)
return exec.Command("echo")
},
func(err error) {
assert.NoError(t, err)
},
},
{
"filename with spaces",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "open", name)
assert.Equal(t, []string{"filename with spaces"}, arg)
return exec.Command("echo")
},
func(err error) {
@ -145,6 +120,7 @@ func TestOSCommandOpenFile(t *testing.T) {
for _, s := range scenarios {
OSCmd := newDummyOSCommand()
OSCmd.command = s.command
OSCmd.Config.GetUserConfig().Set("os.openCommand", "open {{filename}}")
s.test(OSCmd.OpenFile(s.filename))
}

View File

@ -5,6 +5,6 @@ func getPlatform() *Platform {
os: "windows",
shell: "cmd",
shellArg: "/c",
escapedQuote: "\\\"",
escapedQuote: `\"`,
}
}