diff --git a/pkg/commands/oscommands/cmd_obj_runner.go b/pkg/commands/oscommands/cmd_obj_runner.go index 2a1e52884..01d07a7ee 100644 --- a/pkg/commands/oscommands/cmd_obj_runner.go +++ b/pkg/commands/oscommands/cmd_obj_runner.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "io" + "os/exec" "regexp" "strings" "time" @@ -11,6 +12,7 @@ import ( "github.com/go-errors/errors" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/sasha-s/go-deadlock" "github.com/sirupsen/logrus" ) @@ -236,7 +238,7 @@ func (self *cmdObjRunner) runAndStreamAux( var stderr bytes.Buffer cmd.Stderr = io.MultiWriter(cmdWriter, &stderr) - handler, err := self.getCmdHandler(cmd) + handler, err := self.getCmdHandlerPty(cmd) if err != nil { return err } @@ -410,3 +412,38 @@ func (self *cmdObjRunner) getCheckForCredentialRequestFunc() func([]byte) (Crede return 0, false } } + +type Buffer struct { + b bytes.Buffer + m deadlock.Mutex +} + +func (b *Buffer) Read(p []byte) (n int, err error) { + b.m.Lock() + defer b.m.Unlock() + return b.b.Read(p) +} + +func (b *Buffer) Write(p []byte) (n int, err error) { + b.m.Lock() + defer b.m.Unlock() + return b.b.Write(p) +} + +func (self *cmdObjRunner) getCmdHandlerNonPty(cmd *exec.Cmd) (*cmdHandler, error) { + stdoutReader, stdoutWriter := io.Pipe() + cmd.Stdout = stdoutWriter + + buf := &Buffer{} + cmd.Stdin = buf + + if err := cmd.Start(); err != nil { + return nil, err + } + + return &cmdHandler{ + stdoutPipe: stdoutReader, + stdinPipe: buf, + close: func() error { return nil }, + }, nil +} diff --git a/pkg/commands/oscommands/cmd_obj_runner_default.go b/pkg/commands/oscommands/cmd_obj_runner_default.go index 567dcf970..891b4c4ee 100644 --- a/pkg/commands/oscommands/cmd_obj_runner_default.go +++ b/pkg/commands/oscommands/cmd_obj_runner_default.go @@ -11,7 +11,7 @@ import ( // we define this separately for windows and non-windows given that windows does // not have great PTY support and we need a PTY to handle a credential request -func (self *cmdObjRunner) getCmdHandler(cmd *exec.Cmd) (*cmdHandler, error) { +func (self *cmdObjRunner) getCmdHandlerPty(cmd *exec.Cmd) (*cmdHandler, error) { ptmx, err := pty.Start(cmd) if err != nil { return nil, err diff --git a/pkg/commands/oscommands/cmd_obj_runner_win.go b/pkg/commands/oscommands/cmd_obj_runner_win.go index 6893a2535..2189da2e6 100644 --- a/pkg/commands/oscommands/cmd_obj_runner_win.go +++ b/pkg/commands/oscommands/cmd_obj_runner_win.go @@ -4,48 +4,10 @@ package oscommands import ( - "bytes" - "io" "os/exec" - - "github.com/sasha-s/go-deadlock" ) -type Buffer struct { - b bytes.Buffer - m deadlock.Mutex -} - -func (b *Buffer) Read(p []byte) (n int, err error) { - b.m.Lock() - defer b.m.Unlock() - return b.b.Read(p) -} - -func (b *Buffer) Write(p []byte) (n int, err error) { - b.m.Lock() - defer b.m.Unlock() - return b.b.Write(p) -} - -// TODO: Remove this hack and replace it with a proper way to run commands live on windows. We still have an issue where if a password is requested, the request for a password is written straight to stdout because we can't control the stdout of a subprocess of a subprocess. Keep an eye on https://github.com/creack/pty/pull/109 -func (self *cmdObjRunner) getCmdHandler(cmd *exec.Cmd) (*cmdHandler, error) { - stdoutReader, stdoutWriter := io.Pipe() - cmd.Stdout = stdoutWriter - - buf := &Buffer{} - cmd.Stdin = buf - - if err := cmd.Start(); err != nil { - return nil, err - } - - // because we don't yet have windows support for a pty, we instead just - // pass our standard stream handlers and because there's no pty to close - // we pass a no-op function for that. - return &cmdHandler{ - stdoutPipe: stdoutReader, - stdinPipe: buf, - close: func() error { return nil }, - }, nil +func (self *cmdObjRunner) getCmdHandlerPty(cmd *exec.Cmd) (*cmdHandler, error) { + // We don't have PTY support on Windows yet, so we just return a non-PTY handler. + return self.getCmdHandlerNonPty(cmd) }