diff --git a/dev/sg/internal/run/command.go b/dev/sg/internal/run/command.go index 744f282a6b2..b198de7bccc 100644 --- a/dev/sg/internal/run/command.go +++ b/dev/sg/internal/run/command.go @@ -135,7 +135,7 @@ func startCmd(ctx context.Context, dir string, cmd Command, globalEnv map[string stderrWriter = io.MultiWriter(logger, sc.stderrBuf) } - wg, err := process.PipeOutput(ctx, sc.Cmd, stdoutWriter, stderrWriter) + wg, err := process.PipeOutputUnbuffered(ctx, sc.Cmd, stdoutWriter, stderrWriter) if err != nil { return nil, err } diff --git a/lib/process/pipe.go b/lib/process/pipe.go index 8347ed521ec..2a5e1e1c857 100644 --- a/lib/process/pipe.go +++ b/lib/process/pipe.go @@ -17,6 +17,24 @@ import ( // // See this issue for more details: https://github.com/golang/go/issues/21922 func PipeOutput(ctx context.Context, c *exec.Cmd, stdoutWriter, stderrWriter io.Writer) (*sync.WaitGroup, error) { + return pipeOutputWithCopy(ctx, c, stdoutWriter, stderrWriter, func(w io.Writer, r io.Reader) { + scanner := bufio.NewScanner(r) + for scanner.Scan() { + fmt.Fprintln(w, scanner.Text()) + } + }) +} + +func PipeOutputUnbuffered(ctx context.Context, c *exec.Cmd, stdoutWriter, stderrWriter io.Writer) (*sync.WaitGroup, error) { + return pipeOutputWithCopy(ctx, c, stdoutWriter, stderrWriter, func(w io.Writer, r io.Reader) { + _, err := io.Copy(w, r) + if err != nil { + panic(fmt.Sprintf("failed to pipe output: %s", err)) + } + }) +} + +func pipeOutputWithCopy(ctx context.Context, c *exec.Cmd, stdoutWriter, stderrWriter io.Writer, fn copyFunc) (*sync.WaitGroup, error) { stdoutPipe, err := c.StdoutPipe() if err != nil { return nil, err @@ -42,10 +60,7 @@ func PipeOutput(ctx context.Context, c *exec.Cmd, stdoutWriter, stderrWriter io. readIntoBuf := func(w io.Writer, r io.Reader) { defer wg.Done() - scanner := bufio.NewScanner(r) - for scanner.Scan() { - fmt.Fprintln(w, scanner.Text()) - } + fn(w, r) } wg.Add(2) @@ -54,3 +69,5 @@ func PipeOutput(ctx context.Context, c *exec.Cmd, stdoutWriter, stderrWriter io. return wg, nil } + +type copyFunc func(w io.Writer, r io.Reader)