From a5adfaee8ab29afd7aab434a3cf0a9d7e41f8879 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 21:09:53 +0200 Subject: [PATCH 01/21] remove useless returned variable --- pkg/app/app.go | 5 +---- pkg/commands/os.go | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/app/app.go b/pkg/app/app.go index 102ab4146..6b3a37ef0 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -46,10 +46,7 @@ func NewApp(config config.AppConfigurer) (*App, error) { } var err error app.Log = newLogger(config) - app.OSCommand, err = commands.NewOSCommand(app.Log) - if err != nil { - return app, err - } + app.OSCommand = commands.NewOSCommand(app.Log) app.Tr = i18n.NewLocalizer(app.Log) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 1eef36151..9ccd10eb6 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -30,12 +30,11 @@ type OSCommand struct { } // NewOSCommand os command runner -func NewOSCommand(log *logrus.Logger) (*OSCommand, error) { - osCommand := &OSCommand{ +func NewOSCommand(log *logrus.Logger) *OSCommand { + return &OSCommand{ Log: log, Platform: getPlatform(), } - return osCommand, nil } // RunCommandWithOutput wrapper around commands returning their output and error From 32f4d09e895411216be3b42a66c9e3a424658acd Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 21:48:09 +0200 Subject: [PATCH 02/21] move platform specific code to dedicated platform files --- pkg/commands/os.go | 20 -------------------- pkg/commands/os_default_platform.go | 16 ++++++++++++++++ pkg/commands/os_windows.go | 10 ++++++++++ 3 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 pkg/commands/os_default_platform.go create mode 100644 pkg/commands/os_windows.go diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 9ccd10eb6..29ec2c654 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -4,7 +4,6 @@ import ( "errors" "os" "os/exec" - "runtime" "strings" "github.com/davecgh/go-spew/spew" @@ -74,25 +73,6 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { return outputString, nil } -func getPlatform() *Platform { - switch runtime.GOOS { - case "windows": - return &Platform{ - os: "windows", - shell: "cmd", - shellArg: "/c", - escapedQuote: "\\\"", - } - default: - return &Platform{ - os: runtime.GOOS, - shell: "bash", - shellArg: "-c", - escapedQuote: "\"", - } - } -} - // GetOpenCommand get open command func (c *OSCommand) GetOpenCommand() (string, string, error) { //NextStep open equivalents: xdg-open (linux), cygstart (cygwin), open (OSX) diff --git a/pkg/commands/os_default_platform.go b/pkg/commands/os_default_platform.go new file mode 100644 index 000000000..f6ac1b515 --- /dev/null +++ b/pkg/commands/os_default_platform.go @@ -0,0 +1,16 @@ +// +build !windows + +package commands + +import ( + "runtime" +) + +func getPlatform() *Platform { + return &Platform{ + os: runtime.GOOS, + shell: "bash", + shellArg: "-c", + escapedQuote: "\"", + } +} diff --git a/pkg/commands/os_windows.go b/pkg/commands/os_windows.go new file mode 100644 index 000000000..28dd7a982 --- /dev/null +++ b/pkg/commands/os_windows.go @@ -0,0 +1,10 @@ +package commands + +func getPlatform() *Platform { + return &Platform{ + os: "windows", + shell: "cmd", + shellArg: "/c", + escapedQuote: "\\\"", + } +} From 7a74bc504bbfe99e7f74ba8981cfc771db4e98a3 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 21:48:42 +0200 Subject: [PATCH 03/21] avoid useless allocation --- pkg/commands/os.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 29ec2c654..f84fe5991 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -41,8 +41,10 @@ func (c *OSCommand) RunCommandWithOutput(command string) (string, error) { c.Log.WithField("command", command).Info("RunCommand") splitCmd := str.ToArgv(command) c.Log.Info(splitCmd) - cmdOut, err := exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput() - return sanitisedCommandOutput(cmdOut, err) + + return sanitisedCommandOutput( + exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput(), + ) } // RunCommand runs a command and just returns the error @@ -57,10 +59,11 @@ func (c *OSCommand) RunDirectCommand(command string) (string, error) { args := str.ToArgv(c.Platform.shellArg + " " + command) c.Log.Info(spew.Sdump(args)) - cmdOut, err := exec. - Command(c.Platform.shell, args...). - CombinedOutput() - return sanitisedCommandOutput(cmdOut, err) + return sanitisedCommandOutput( + exec. + Command(c.Platform.shell, args...). + CombinedOutput(), + ) } func sanitisedCommandOutput(output []byte, err error) (string, error) { From a891bc90b78921a64e3abb901c4976788890013a Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 22:05:05 +0200 Subject: [PATCH 04/21] simplify method --- pkg/commands/os.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index f84fe5991..93c42796a 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -153,8 +153,7 @@ func (c *OSCommand) Quote(message string) string { // Unquote removes wrapping quotations marks if they are present // this is needed for removing quotes from staged filenames with spaces func (c *OSCommand) Unquote(message string) string { - message = strings.Replace(message, `"`, "", -1) - return message + return strings.Replace(message, `"`, "", -1) } // AppendLineToFile adds a new line in file From 883fcf10838879839386091e6375c42b3f0b6a7d Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 22:17:34 +0200 Subject: [PATCH 05/21] remove useless returned variable --- pkg/commands/os.go | 8 ++++---- pkg/gui/files_panel.go | 2 +- pkg/gui/status_panel.go | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 93c42796a..bc53ccf29 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -108,13 +108,13 @@ func (c *OSCommand) SublimeOpenFile(filename string) (*exec.Cmd, error) { } // OpenFile opens a file with the given -func (c *OSCommand) OpenFile(filename string) (*exec.Cmd, error) { +func (c *OSCommand) OpenFile(filename string) error { cmdName, cmdTrail, err := c.GetOpenCommand() if err != nil { - return nil, err + return err } - err = c.RunCommand(cmdName + " " + c.Quote(filename) + cmdTrail) // TODO: test on linux - return nil, err + + return c.RunCommand(cmdName + " " + c.Quote(filename) + cmdTrail) // TODO: test on linux } // EditFile opens a file in a subprocess using whatever editor is available, diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 5791a9d15..2f5db9aff 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -256,7 +256,7 @@ func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error { if err != nil { return err } - return gui.genericFileOpen(g, v, file.Name, gui.OSCommand.OpenFile) + return gui.genericFileOpen(g, v, file.Name, func(filename string) (*exec.Cmd, error) { return nil, gui.OSCommand.OpenFile(filename) }) } func (gui *Gui) handleSublimeFileOpen(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index 88134096e..27e0aba5b 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -2,6 +2,7 @@ package gui import ( "fmt" + "os/exec" "github.com/fatih/color" "github.com/jesseduffield/gocui" @@ -66,7 +67,7 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleOpenConfig(g *gocui.Gui, v *gocui.View) error { filename := gui.Config.GetUserConfig().ConfigFileUsed() - return gui.genericFileOpen(g, v, filename, gui.OSCommand.OpenFile) + return gui.genericFileOpen(g, v, filename, func(filename string) (*exec.Cmd, error) { return nil, gui.OSCommand.OpenFile(filename) }) } func (gui *Gui) handleEditConfig(g *gocui.Gui, v *gocui.View) error { From 364c1ac5e75867bd0f016c01ebc8e52bcbf2ce63 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 22:33:25 +0200 Subject: [PATCH 06/21] remove useless returned variable --- pkg/commands/git.go | 6 +++--- pkg/commands/os.go | 9 +++++---- pkg/gui/files_panel.go | 16 ++++------------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 14f3a433a..ec257c441 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -265,7 +265,7 @@ func (c *GitCommand) UsingGpg() bool { func (c *GitCommand) Commit(g *gocui.Gui, message string) (*exec.Cmd, error) { command := "git commit -m " + c.OSCommand.Quote(message) if c.UsingGpg() { - return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command) + return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command), nil } return nil, c.OSCommand.RunCommand(command) } @@ -391,12 +391,12 @@ func (c *GitCommand) Checkout(branch string, force bool) error { // AddPatch prepares 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(filename string) (*exec.Cmd, error) { +func (c *GitCommand) AddPatch(filename string) *exec.Cmd { return c.OSCommand.PrepareSubProcess("git", "add", "--patch", filename) } // PrepareCommitSubProcess prepares a subprocess for `git commit` -func (c *GitCommand) PrepareCommitSubProcess() (*exec.Cmd, error) { +func (c *GitCommand) PrepareCommitSubProcess() *exec.Cmd { return c.OSCommand.PrepareSubProcess("git", "commit") } diff --git a/pkg/commands/os.go b/pkg/commands/os.go index bc53ccf29..095ad7b0a 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -121,6 +121,7 @@ func (c *OSCommand) OpenFile(filename string) error { // falling back to core.editor, VISUAL, EDITOR, then vi func (c *OSCommand) EditFile(filename string) (*exec.Cmd, error) { editor, _ := gitconfig.Global("core.editor") + if editor == "" { editor = os.Getenv("VISUAL") } @@ -135,13 +136,13 @@ func (c *OSCommand) EditFile(filename string) (*exec.Cmd, error) { if editor == "" { return nil, errors.New("No editor defined in $VISUAL, $EDITOR, or git config") } - return c.PrepareSubProcess(editor, filename) + + return c.PrepareSubProcess(editor, filename), nil } // PrepareSubProcess iniPrepareSubProcessrocess then tells the Gui to switch to it -func (c *OSCommand) PrepareSubProcess(cmdName string, commandArgs ...string) (*exec.Cmd, error) { - subprocess := exec.Command(cmdName, commandArgs...) - return subprocess, nil +func (c *OSCommand) PrepareSubProcess(cmdName string, commandArgs ...string) *exec.Cmd { + return exec.Command(cmdName, commandArgs...) } // Quote wraps a message in platform-specific quotation marks diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 2f5db9aff..eb1fff94d 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -85,11 +85,8 @@ func (gui *Gui) handleAddPatch(g *gocui.Gui, v *gocui.View) error { if !file.Tracked { return gui.createErrorPanel(g, gui.Tr.SLocalize("CannotGitAdd")) } - sub, err := gui.GitCommand.AddPatch(file.Name) - if err != nil { - return err - } - gui.SubProcess = sub + + gui.SubProcess = gui.GitCommand.AddPatch(file.Name) return gui.Errors.ErrSubProcess } @@ -218,16 +215,11 @@ func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) err } // PrepareSubProcess - prepare a subprocess for execution and tell the gui to switch to it -func (gui *Gui) PrepareSubProcess(g *gocui.Gui, commands ...string) error { - sub, err := gui.GitCommand.PrepareCommitSubProcess() - if err != nil { - return err - } - gui.SubProcess = sub +func (gui *Gui) PrepareSubProcess(g *gocui.Gui, commands ...string) { + gui.SubProcess = gui.GitCommand.PrepareCommitSubProcess() g.Update(func(g *gocui.Gui) error { return gui.Errors.ErrSubProcess }) - return nil } func (gui *Gui) genericFileOpen(g *gocui.Gui, v *gocui.View, filename string, open func(string) (*exec.Cmd, error)) error { From f91e2b12dbc02e3dc05f5ae746d16a702ba57c27 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Tue, 21 Aug 2018 23:17:44 +0200 Subject: [PATCH 07/21] add tests to pkg/commands --- pkg/commands/os_test.go | 80 +++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/pkg/commands/os_test.go b/pkg/commands/os_test.go index 29540aff6..128caa1b2 100644 --- a/pkg/commands/os_test.go +++ b/pkg/commands/os_test.go @@ -1,16 +1,76 @@ package commands -import "testing" +import ( + "testing" -func TestQuote(t *testing.T) { - osCommand := &OSCommand{ - Log: nil, - Platform: getPlatform(), + "github.com/Sirupsen/logrus" + + "github.com/stretchr/testify/assert" +) + +func TestRunCommandWithOutput(t *testing.T) { + type scenario struct { + command string + test func(string, error) } - test := "hello `test`" - expected := osCommand.Platform.escapedQuote + "hello \\`test\\`" + osCommand.Platform.escapedQuote - test = osCommand.Quote(test) - if test != expected { - t.Error("Expected " + expected + ", got " + test) + + scenarios := []scenario{ + { + "echo -n '123'", + func(output string, err error) { + assert.NoError(t, err) + assert.EqualValues(t, "123", output) + }, + }, + { + "rmdir unexisting-folder", + func(output string, err error) { + assert.Regexp(t, ".*No such file or directory.*", err.Error()) + }, + }, + } + + for _, s := range scenarios { + s.test(NewOSCommand(logrus.New()).RunCommandWithOutput(s.command)) } } + +func TestRunCommand(t *testing.T) { + type scenario struct { + command string + test func(error) + } + + scenarios := []scenario{ + { + "rmdir unexisting-folder", + func(err error) { + assert.Regexp(t, ".*No such file or directory.*", err.Error()) + }, + }, + } + + for _, s := range scenarios { + s.test(NewOSCommand(logrus.New()).RunCommand(s.command)) + } +} + +func TestQuote(t *testing.T) { + osCommand := NewOSCommand(logrus.New()) + + actual := osCommand.Quote("hello `test`") + + expected := osCommand.Platform.escapedQuote + "hello \\`test\\`" + osCommand.Platform.escapedQuote + + assert.EqualValues(t, expected, actual) +} + +func TestUnquote(t *testing.T) { + osCommand := NewOSCommand(logrus.New()) + + actual := osCommand.Unquote(`hello "test"`) + + expected := "hello test" + + assert.EqualValues(t, expected, actual) +} From 38f11f1f4a9df758a7ff030247a171711dca2339 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Wed, 22 Aug 2018 22:30:02 +0200 Subject: [PATCH 08/21] move dummy functions, rename functions --- pkg/commands/git_test.go | 17 +++++------------ pkg/commands/os_test.go | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index c930f76eb..0d076254a 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -9,28 +9,21 @@ import ( "github.com/jesseduffield/lazygit/pkg/test" ) -func getDummyLog() *logrus.Logger { +func newDummyLog() *logrus.Logger { log := logrus.New() log.Out = ioutil.Discard return log } -func getDummyOSCommand() *OSCommand { - return &OSCommand{ - Log: getDummyLog(), - Platform: getPlatform(), - } -} - -func getDummyGitCommand() *GitCommand { +func newDummyGitCommand() *GitCommand { return &GitCommand{ - Log: getDummyLog(), - OSCommand: getDummyOSCommand(), + Log: newDummyLog(), + OSCommand: newDummyOSCommand(), } } func TestDiff(t *testing.T) { - gitCommand := getDummyGitCommand() + gitCommand := newDummyGitCommand() if err := test.GenerateRepo("lots_of_diffs.sh"); err != nil { t.Error(err.Error()) } diff --git a/pkg/commands/os_test.go b/pkg/commands/os_test.go index 128caa1b2..9d5cc1354 100644 --- a/pkg/commands/os_test.go +++ b/pkg/commands/os_test.go @@ -3,12 +3,14 @@ package commands import ( "testing" - "github.com/Sirupsen/logrus" - "github.com/stretchr/testify/assert" ) -func TestRunCommandWithOutput(t *testing.T) { +func newDummyOSCommand() *OSCommand { + return NewOSCommand(newDummyLog()) +} + +func TestOSCommandRunCommandWithOutput(t *testing.T) { type scenario struct { command string test func(string, error) @@ -31,11 +33,11 @@ func TestRunCommandWithOutput(t *testing.T) { } for _, s := range scenarios { - s.test(NewOSCommand(logrus.New()).RunCommandWithOutput(s.command)) + s.test(newDummyOSCommand().RunCommandWithOutput(s.command)) } } -func TestRunCommand(t *testing.T) { +func TestOSCommandRunCommand(t *testing.T) { type scenario struct { command string test func(error) @@ -51,12 +53,12 @@ func TestRunCommand(t *testing.T) { } for _, s := range scenarios { - s.test(NewOSCommand(logrus.New()).RunCommand(s.command)) + s.test(newDummyOSCommand().RunCommand(s.command)) } } -func TestQuote(t *testing.T) { - osCommand := NewOSCommand(logrus.New()) +func TestOSCommandQuote(t *testing.T) { + osCommand := newDummyOSCommand() actual := osCommand.Quote("hello `test`") @@ -65,8 +67,8 @@ func TestQuote(t *testing.T) { assert.EqualValues(t, expected, actual) } -func TestUnquote(t *testing.T) { - osCommand := NewOSCommand(logrus.New()) +func TestOSCommandUnquote(t *testing.T) { + osCommand := newDummyOSCommand() actual := osCommand.Unquote(`hello "test"`) From 0b07cd19f7efd14ae4d73ad00d611932402d50ca Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Wed, 22 Aug 2018 22:30:47 +0200 Subject: [PATCH 09/21] switch GetOpenCommand scope to private --- pkg/commands/os.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 095ad7b0a..556c3bc06 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -76,8 +76,8 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { return outputString, nil } -// GetOpenCommand get open command -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 &", @@ -109,7 +109,7 @@ func (c *OSCommand) SublimeOpenFile(filename string) (*exec.Cmd, error) { // OpenFile opens a file with the given func (c *OSCommand) OpenFile(filename string) error { - cmdName, cmdTrail, err := c.GetOpenCommand() + cmdName, cmdTrail, err := c.getOpenCommand() if err != nil { return err } From 75e08993eacb88e98df30e1ee4dff500d2c19a3d Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Wed, 22 Aug 2018 22:31:35 +0200 Subject: [PATCH 10/21] extract dependencies --- pkg/commands/os.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 556c3bc06..8b9ecf7ec 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -24,15 +24,21 @@ type Platform struct { // OSCommand holds all the os commands type OSCommand struct { - Log *logrus.Logger - Platform *Platform + Log *logrus.Logger + Platform *Platform + command func(string, ...string) *exec.Cmd + getGlobalGitConfig func(string) (string, error) + getenv func(string) string } // NewOSCommand os command runner func NewOSCommand(log *logrus.Logger) *OSCommand { return &OSCommand{ - Log: log, - Platform: getPlatform(), + Log: log, + Platform: getPlatform(), + command: exec.Command, + getGlobalGitConfig: gitconfig.Global, + getenv: os.Getenv, } } @@ -43,7 +49,7 @@ func (c *OSCommand) RunCommandWithOutput(command string) (string, error) { c.Log.Info(splitCmd) return sanitisedCommandOutput( - exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput(), + c.command(splitCmd[0], splitCmd[1:]...).CombinedOutput(), ) } @@ -84,6 +90,7 @@ func (c *OSCommand) getOpenCommand() (string, string, error) { "cygstart": "", "open": "", } + for name, trail := range trailMap { if err := c.RunCommand("which " + name); err == nil { return name, trail, nil @@ -120,13 +127,13 @@ func (c *OSCommand) OpenFile(filename string) error { // EditFile opens a file in a subprocess using whatever editor is available, // falling back to core.editor, VISUAL, EDITOR, then vi func (c *OSCommand) EditFile(filename string) (*exec.Cmd, error) { - editor, _ := gitconfig.Global("core.editor") + editor, _ := c.getGlobalGitConfig("core.editor") if editor == "" { - editor = os.Getenv("VISUAL") + editor = c.getenv("VISUAL") } if editor == "" { - editor = os.Getenv("EDITOR") + editor = c.getenv("EDITOR") } if editor == "" { if err := c.RunCommand("which vi"); err == nil { @@ -142,7 +149,7 @@ func (c *OSCommand) EditFile(filename string) (*exec.Cmd, error) { // PrepareSubProcess iniPrepareSubProcessrocess then tells the Gui to switch to it func (c *OSCommand) PrepareSubProcess(cmdName string, commandArgs ...string) *exec.Cmd { - return exec.Command(cmdName, commandArgs...) + return c.command(cmdName, commandArgs...) } // Quote wraps a message in platform-specific quotation marks From ed2dcd9e461d99b7969dee73fb96233947ee0ecf Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Wed, 22 Aug 2018 22:31:43 +0200 Subject: [PATCH 11/21] add tests --- pkg/commands/os_test.go | 221 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) diff --git a/pkg/commands/os_test.go b/pkg/commands/os_test.go index 9d5cc1354..d78391d17 100644 --- a/pkg/commands/os_test.go +++ b/pkg/commands/os_test.go @@ -1,6 +1,7 @@ package commands import ( + "os/exec" "testing" "github.com/stretchr/testify/assert" @@ -57,6 +58,226 @@ 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 + command func(string, ...string) *exec.Cmd + test func(error) + } + + scenarios := []scenario{ + { + "test", + func(name string, arg ...string) *exec.Cmd { + return exec.Command("exit", "1") + }, + func(err error) { + assert.EqualError(t, err, "Unsure what command to use to open this file") + }, + }, + { + "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") + } + + return exec.Command("echo") + }, + func(err error) { + assert.NoError(t, err) + }, + }, + } + + for _, s := range scenarios { + OSCmd := newDummyOSCommand() + OSCmd.command = s.command + + s.test(OSCmd.OpenFile(s.filename)) + } +} + +func TestOSCommandEditFile(t *testing.T) { + type scenario struct { + filename string + command func(string, ...string) *exec.Cmd + getenv func(string) string + getGlobalGitConfig func(string) (string, error) + test func(*exec.Cmd, error) + } + + scenarios := []scenario{ + { + "test", + func(name string, arg ...string) *exec.Cmd { + return exec.Command("exit", "1") + }, + func(env string) string { + return "" + }, + func(cf string) (string, error) { + return "", nil + }, + func(cmd *exec.Cmd, err error) { + assert.EqualError(t, err, "No editor defined in $VISUAL, $EDITOR, or git config") + }, + }, + { + "test", + func(name string, arg ...string) *exec.Cmd { + if name == "which" { + return exec.Command("exit", "1") + } + + assert.EqualValues(t, "nano", name) + + return nil + }, + func(env string) string { + return "" + }, + func(cf string) (string, error) { + return "nano", nil + }, + func(cmd *exec.Cmd, err error) { + assert.NoError(t, err) + }, + }, + { + "test", + func(name string, arg ...string) *exec.Cmd { + if name == "which" { + return exec.Command("exit", "1") + } + + assert.EqualValues(t, "nano", name) + + return nil + }, + func(env string) string { + if env == "VISUAL" { + return "nano" + } + + return "" + }, + func(cf string) (string, error) { + return "", nil + }, + func(cmd *exec.Cmd, err error) { + assert.NoError(t, err) + }, + }, + { + "test", + func(name string, arg ...string) *exec.Cmd { + if name == "which" { + return exec.Command("exit", "1") + } + + assert.EqualValues(t, "emacs", name) + + return nil + }, + func(env string) string { + if env == "EDITOR" { + return "emacs" + } + + return "" + }, + func(cf string) (string, error) { + return "", nil + }, + func(cmd *exec.Cmd, err error) { + assert.NoError(t, err) + }, + }, + { + "test", + func(name string, arg ...string) *exec.Cmd { + if name == "which" { + return exec.Command("echo") + } + + assert.EqualValues(t, "vi", name) + + return nil + }, + func(env string) string { + return "" + }, + func(cf string) (string, error) { + return "", nil + }, + func(cmd *exec.Cmd, err error) { + assert.NoError(t, err) + }, + }, + } + + for _, s := range scenarios { + OSCmd := newDummyOSCommand() + OSCmd.command = s.command + OSCmd.getGlobalGitConfig = s.getGlobalGitConfig + OSCmd.getenv = s.getenv + + s.test(OSCmd.EditFile(s.filename)) + } +} + func TestOSCommandQuote(t *testing.T) { osCommand := newDummyOSCommand() From 23fe0290ad37197cb80ca464a7287cd78191e91a Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Thu, 23 Aug 2018 21:05:09 +0200 Subject: [PATCH 12/21] add openFile to gui struct --- pkg/gui/files_panel.go | 9 ++++++++- pkg/gui/status_panel.go | 4 +--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index eb1fff94d..760dee934 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -248,7 +248,7 @@ func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error { if err != nil { return err } - return gui.genericFileOpen(g, v, file.Name, func(filename string) (*exec.Cmd, error) { return nil, gui.OSCommand.OpenFile(filename) }) + return gui.openFile(file.Name) } func (gui *Gui) handleSublimeFileOpen(g *gocui.Gui, v *gocui.View) error { @@ -417,3 +417,10 @@ func (gui *Gui) handleResetHard(g *gocui.Gui, v *gocui.View) error { return gui.refreshFiles(g) }, nil) } + +func (gui *Gui) openFile(filename string) error { + if err := gui.OSCommand.OpenFile(filename); err != nil { + return gui.createErrorPanel(gui.g, err.Error()) + } + return nil +} diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index 27e0aba5b..bad543880 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -2,7 +2,6 @@ package gui import ( "fmt" - "os/exec" "github.com/fatih/color" "github.com/jesseduffield/gocui" @@ -66,8 +65,7 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleOpenConfig(g *gocui.Gui, v *gocui.View) error { - filename := gui.Config.GetUserConfig().ConfigFileUsed() - return gui.genericFileOpen(g, v, filename, func(filename string) (*exec.Cmd, error) { return nil, gui.OSCommand.OpenFile(filename) }) + return gui.openFile(gui.Config.GetUserConfig().ConfigFileUsed()) } func (gui *Gui) handleEditConfig(g *gocui.Gui, v *gocui.View) error { From 2273f4c0a527faf735ffb759b6d8030f8277dd2f Mon Sep 17 00:00:00 2001 From: antham Date: Sat, 25 Aug 2018 15:32:06 +0200 Subject: [PATCH 13/21] add compile step in circleci --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0eef1a409..c9b2fed58 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,6 +11,11 @@ jobs: name: Run tests command: | ./test.sh + - run: + name: Compile project on every platform + command: | + go get github.com/mitchellh/gox + gox - run: name: Push on codecov result command: | From caf99d2d6403e6d65ebf7fff045f65374e93cb13 Mon Sep 17 00:00:00 2001 From: antham Date: Sat, 25 Aug 2018 15:41:03 +0200 Subject: [PATCH 14/21] exclude openbsd cause of go-git bugs on this platform --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c9b2fed58..f300206b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ jobs: name: Compile project on every platform command: | go get github.com/mitchellh/gox - gox + gox -os "linux darwin freebsd netbsd windows" - run: name: Push on codecov result command: | From a23753dc188bfc36b8f5694d196ba604a5f5fe1e Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Sat, 25 Aug 2018 21:38:25 +0200 Subject: [PATCH 15/21] exclude darwin arm from building --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f300206b6..0f79df38a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ jobs: name: Compile project on every platform command: | go get github.com/mitchellh/gox - gox -os "linux darwin freebsd netbsd windows" + gox -os "linux freebsd netbsd windows" -osarch "darwin/i386 darwin/amd64" - run: name: Push on codecov result command: | From 4b19b4108ed2facb91efdf936c8c4bc5fe1f9ff1 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Sat, 25 Aug 2018 21:45:05 +0200 Subject: [PATCH 16/21] add circleci cache --- .circleci/config.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f79df38a..e57569829 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,6 +7,9 @@ jobs: working_directory: /go/src/github.com/jesseduffield/lazygit steps: - checkout + - restore_cache: + keys: + - v1-pkg-cache - run: name: Run tests command: | @@ -20,6 +23,10 @@ jobs: name: Push on codecov result command: | bash <(curl -s https://codecov.io/bash) + - save_cache: + key: v1-pkg-cache + paths: + - "/go/pkg" release: docker: From 2d9f7009fa64507c3f0dfe9817deed29cdbf4a9b Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Sun, 26 Aug 2018 02:17:46 +0200 Subject: [PATCH 17/21] add gofmt to circle --- .circleci/config.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index e57569829..eca323aed 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,6 +10,13 @@ jobs: - restore_cache: keys: - v1-pkg-cache + - run: + name: Run gofmt -s + command: | + if [ $(find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;|wc -l) -gt 0 ]; then + find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \; + exit 1; + fi - run: name: Run tests command: | From f6ab11e4ee1bf0e90b94af28fb16a74ef10e0ae0 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Sun, 26 Aug 2018 02:20:01 +0200 Subject: [PATCH 18/21] run gofmt --- pkg/app/app.go | 2 +- pkg/commands/git.go | 2 +- pkg/commands/git_test.go | 2 +- pkg/gui/gui.go | 2 +- pkg/i18n/i18n.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/app/app.go b/pkg/app/app.go index 6b3a37ef0..7dccc2748 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -5,11 +5,11 @@ import ( "io/ioutil" "os" - "github.com/sirupsen/logrus" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui" "github.com/jesseduffield/lazygit/pkg/i18n" + "github.com/sirupsen/logrus" ) // App struct diff --git a/pkg/commands/git.go b/pkg/commands/git.go index ec257c441..e5ee5dbfa 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -7,9 +7,9 @@ import ( "os/exec" "strings" - "github.com/sirupsen/logrus" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/sirupsen/logrus" gitconfig "github.com/tcnksm/go-gitconfig" gogit "gopkg.in/src-d/go-git.v4" ) diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 0d076254a..372009641 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - "github.com/sirupsen/logrus" "github.com/jesseduffield/lazygit/pkg/test" + "github.com/sirupsen/logrus" ) func newDummyLog() *logrus.Logger { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 3d9c7b617..ec8eea94d 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -15,12 +15,12 @@ import ( // "strings" - "github.com/sirupsen/logrus" "github.com/golang-collections/collections/stack" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/i18n" + "github.com/sirupsen/logrus" ) // OverlappingEdges determines if panel edges overlap diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go index 898a13906..37de57cc6 100644 --- a/pkg/i18n/i18n.go +++ b/pkg/i18n/i18n.go @@ -1,9 +1,9 @@ package i18n import ( - "github.com/sirupsen/logrus" "github.com/cloudfoundry/jibber_jabber" "github.com/nicksnyder/go-i18n/v2/i18n" + "github.com/sirupsen/logrus" "golang.org/x/text/language" ) From 55c6af258d1ef959b0f6ff29fc3362b8454ed06b Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Sun, 26 Aug 2018 11:30:03 +0200 Subject: [PATCH 19/21] increase parallel build --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eca323aed..d60eadaab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,7 +25,7 @@ jobs: name: Compile project on every platform command: | go get github.com/mitchellh/gox - gox -os "linux freebsd netbsd windows" -osarch "darwin/i386 darwin/amd64" + gox -parallel 10 -os "linux freebsd netbsd windows" -osarch "darwin/i386 darwin/amd64" - run: name: Push on codecov result command: | From b7f6bcb3caa45ecb516670704513110a7d2f6a74 Mon Sep 17 00:00:00 2001 From: Dawid Dziurla Date: Sun, 26 Aug 2018 10:42:25 +0200 Subject: [PATCH 20/21] add config flag --- main.go | 5 +++++ pkg/config/app_config.go | 37 ++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/main.go b/main.go index e8c092da2..758a0ee50 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ var ( version = "unversioned" date string + configFlag = flag.Bool("config", false, "Print the current default config") debuggingFlag = flag.Bool("debug", false, "a boolean") versionFlag = flag.Bool("v", false, "Print the current version") ) @@ -31,6 +32,10 @@ func main() { fmt.Printf("commit=%s, build date=%s, version=%s, os=%s, arch=%s\n", commit, date, version, runtime.GOOS, runtime.GOARCH) os.Exit(0) } + if *configFlag { + fmt.Printf("%s\n", config.GetDefaultConfig()) + os.Exit(0) + } appConfig, err := config.NewAppConfig("lazygit", version, commit, date, debuggingFlag) if err != nil { panic(err) diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index aa56365e3..d49ddd4d5 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -101,7 +101,7 @@ func LoadUserConfig() (*viper.Viper, error) { // LoadDefaultConfig loads in the defaults defined in this file func LoadDefaultConfig(v *viper.Viper) error { - defaults := getDefaultConfig() + defaults := GetDefaultConfig() return v.ReadConfig(bytes.NewBuffer(defaults)) } @@ -139,24 +139,23 @@ func (c *AppConfig) InsertToUserConfig(key, value string) error { return v.WriteConfig() } -func getDefaultConfig() []byte { - return []byte(` - gui: - ## stuff relating to the UI - scrollHeight: 2 - theme: - activeBorderColor: - - white - - bold - inactiveBorderColor: - - white - optionsTextColor: - - blue - git: - # stuff relating to git - os: - # stuff relating to the OS - +func GetDefaultConfig() []byte { + return []byte( +`gui: + # stuff relating to the UI + scrollHeight: 2 + theme: + activeBorderColor: + - white + - bold + inactiveBorderColor: + - white + optionsTextColor: + - blue +git: + # stuff relating to git +os: + # stuff relating to the OS `) } From a2a9e0c478cef1346d63227a8c67171b70814335 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Mon, 27 Aug 2018 10:01:05 +0200 Subject: [PATCH 21/21] fix format issue --- pkg/config/app_config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index d49ddd4d5..d656faa9e 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -141,7 +141,7 @@ func (c *AppConfig) InsertToUserConfig(key, value string) error { func GetDefaultConfig() []byte { return []byte( -`gui: + `gui: # stuff relating to the UI scrollHeight: 2 theme: