Skip to content

Commit 48c8a10

Browse files
committed
Modify ExecCommand to always cache stdout/stderr
By adding a new Stream type we can address programs like uploaders which show a progress bar or other long running tools
1 parent 27dd585 commit 48c8a10

File tree

1 file changed

+23
-43
lines changed

1 file changed

+23
-43
lines changed

utils/utils.go

+23-43
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
package utils
3131

3232
import (
33-
"bufio"
3433
"bytes"
3534
"crypto/md5"
3635
"encoding/hex"
@@ -282,72 +281,53 @@ func PrintableCommand(parts []string) string {
282281

283282
const (
284283
Ignore = 0 // Redirect to null
285-
Show = 1 // Show on stdout/stderr as normal
286-
ShowIfVerbose = 2 // Show if verbose is set, Ignore otherwise
287-
Capture = 3 // Capture into buffer
284+
Show = 1 // Print the stream
285+
ShowIfVerbose = 2 // Print the stream only if verbose
286+
Capture = 3 // Capture into buffer and don't print
287+
Stream = 4 // Stream data as it comes in, no capture
288288
)
289289

290290
func ExecCommand(ctx *types.Context, command *exec.Cmd, stdout int, stderr int) ([]byte, []byte, error) {
291291
if ctx.Verbose {
292292
ctx.GetLogger().UnformattedFprintln(os.Stdout, PrintableCommand(command.Args))
293293
}
294294

295-
var stdoutCopy io.ReadCloser
296-
var stderrCopy io.ReadCloser
297-
298-
if stdout == Capture {
295+
if stdout != Stream {
299296
buffer := &bytes.Buffer{}
300297
command.Stdout = buffer
301-
} else if stdout == Show || stdout == ShowIfVerbose && ctx.Verbose {
302-
stdoutCopy, _ = command.StdoutPipe()
298+
} else {
299+
command.Stdout = os.Stdout
303300
}
304301

305-
if stderr == Capture {
302+
if stderr != Stream {
306303
buffer := &bytes.Buffer{}
307304
command.Stderr = buffer
308-
} else if stderr == Show || stderr == ShowIfVerbose && ctx.Verbose {
309-
stderrCopy, _ = command.StderrPipe()
305+
} else {
306+
command.Stderr = os.Stderr
310307
}
311308

312309
err := command.Start()
313310
if err != nil {
314311
return nil, nil, i18n.WrapError(err)
315312
}
316313

317-
var outbytes, errbytes []byte
318-
319-
if stdoutCopy != nil && stderrCopy != nil {
320-
stdOut := bufio.NewScanner(stdoutCopy)
321-
stdErr := bufio.NewScanner(stderrCopy)
322-
stdOut.Split(bufio.ScanLines)
323-
stdErr.Split(bufio.ScanLines)
324-
325-
go func() {
326-
for stdOut.Scan() {
327-
txt := stdOut.Text() + "\n"
328-
fmt.Fprint(os.Stderr, txt)
329-
outbytes = append(outbytes, txt...)
330-
}
331-
}()
314+
err = command.Wait()
332315

333-
go func() {
334-
for stdErr.Scan() {
335-
txt := stdErr.Text() + "\n"
336-
fmt.Fprint(os.Stderr, txt)
337-
errbytes = append(errbytes, txt...)
338-
}
339-
}()
316+
var outbytes, errbytes []byte
317+
// this operation is a no-op in case of streaming
318+
if buf, ok := command.Stdout.(*bytes.Buffer); ok {
319+
outbytes = buf.Bytes()
320+
}
321+
if buf, ok := command.Stderr.(*bytes.Buffer); ok {
322+
errbytes = buf.Bytes()
340323
}
341324

342-
err = command.Wait()
325+
if stdout == Show || (stdout == ShowIfVerbose && ctx.Verbose) {
326+
ctx.GetLogger().UnformattedWrite(os.Stdout, outbytes)
327+
}
343328

344-
if stdoutCopy == nil || stderrCopy == nil {
345-
if buf, ok := command.Stdout.(*bytes.Buffer); ok {
346-
outbytes = buf.Bytes()
347-
}
348-
if buf, ok := command.Stderr.(*bytes.Buffer); ok {
349-
errbytes = buf.Bytes()
350-
}
329+
if stderr == Show || (stderr == ShowIfVerbose && ctx.Verbose) {
330+
ctx.GetLogger().UnformattedWrite(os.Stderr, errbytes)
351331
}
352332

353333
return outbytes, errbytes, i18n.WrapError(err)

0 commit comments

Comments
 (0)