mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Use ConPTY on Windows for pty-backed command execution
The per-platform getCmdHandlerPty split existed because the Unix side had creack/pty and the Windows side had nothing — so it fell back to a non-pty handler. Now that oscommands.StartPty provides a pty on both platforms, the two files collapse into one cross-platform implementation and the stub is gone. cmdHandler grows a 'wait' field because the pty path on Windows spawns via CreateProcess and never runs exec.Cmd.Start — so cmd.Wait wouldn't work there. Non-pty handlers set wait = cmd.Wait; pty handlers set it to the wait closure StartPty returns. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1935117141
commit
8c035ebe60
|
|
@ -157,7 +157,7 @@ func (self *CmdObj) ShouldStreamOutput() bool {
|
|||
}
|
||||
|
||||
// when you call this, then call Run(), we'll use a PTY to run the command. Only
|
||||
// has an effect if StreamOutput() was also called. Ignored on Windows.
|
||||
// has an effect if StreamOutput() was also called.
|
||||
func (self *CmdObj) UsePty() *CmdObj {
|
||||
self.usePty = true
|
||||
|
||||
|
|
|
|||
|
|
@ -219,6 +219,10 @@ type cmdHandler struct {
|
|||
stdoutPipe io.Reader
|
||||
stdinPipe io.Writer
|
||||
close func() error
|
||||
// wait blocks until the child process exits. Needed as a separate
|
||||
// field because the pty path on Windows spawns via CreateProcess and
|
||||
// never runs *exec.Cmd.Start — so cmd.Wait wouldn't work there.
|
||||
wait func() error
|
||||
}
|
||||
|
||||
func (self *cmdObjRunner) runAndStream(cmdObj *CmdObj) error {
|
||||
|
|
@ -274,7 +278,7 @@ func (self *cmdObjRunner) runAndStreamAux(
|
|||
|
||||
onRun(handler, cmdWriter)
|
||||
|
||||
err = cmd.Wait()
|
||||
err = handler.wait()
|
||||
|
||||
self.log.Infof("%s (%s)", cmdObj.ToString(), time.Since(t))
|
||||
|
||||
|
|
@ -376,9 +380,7 @@ func (self *cmdObjRunner) processOutput(
|
|||
responseChan := promptUserForCredential(askFor)
|
||||
if responseChan == nil {
|
||||
// Returning a nil channel means we should terminate the process.
|
||||
// We achieve this by closing the pty that it's running in. Note that this won't
|
||||
// work for the case where we're not running in a pty (i.e. on Windows), but
|
||||
// in that case we'll never be prompted for credentials, so it's not a concern.
|
||||
// We achieve this by closing the pty that it's running in.
|
||||
if err := closeFunc(); err != nil {
|
||||
self.log.Error(err)
|
||||
}
|
||||
|
|
@ -481,5 +483,21 @@ func (self *cmdObjRunner) getCmdHandlerNonPty(cmd *exec.Cmd) (*cmdHandler, error
|
|||
stdoutPipe: stdoutReader,
|
||||
stdinPipe: buf,
|
||||
close: func() error { return nil },
|
||||
wait: cmd.Wait,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *cmdObjRunner) getCmdHandlerPty(cmd *exec.Cmd) (*cmdHandler, error) {
|
||||
// Size will be adjusted by the caller if it cares; this just avoids a
|
||||
// zero-size pty.
|
||||
sp, err := StartPty(cmd, 80, 24)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cmdHandler{
|
||||
stdoutPipe: sp.Pty,
|
||||
stdinPipe: sp.Pty,
|
||||
close: sp.Pty.Close,
|
||||
wait: sp.Wait,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
//go:build !windows
|
||||
|
||||
package oscommands
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
// 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) getCmdHandlerPty(cmd *exec.Cmd) (*cmdHandler, error) {
|
||||
ptmx, err := pty.Start(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cmdHandler{
|
||||
stdoutPipe: ptmx,
|
||||
stdinPipe: ptmx,
|
||||
close: ptmx.Close,
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
package oscommands
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
Loading…
Reference in a new issue