in cmd/hub/lifecycle/exec.go [32:115]
func execImplementation(impl *exec.Cmd, passStdin, paginate bool) ([]byte, []byte, error) {
stderrImpl, err := impl.StderrPipe()
if err != nil {
return nil, nil, fmt.Errorf("Unable to obtain sub-process stderr pipe: %v", err)
}
stdoutImpl, err := impl.StdoutPipe()
if err != nil {
return nil, nil, fmt.Errorf("Unable to obtain sub-process stdout pipe: %v", err)
}
logOutput := log.Writer()
var stdout io.Writer = os.Stdout
var stderr io.Writer = os.Stderr
if paginate && config.Tty && !config.Debug {
stdoutTerminal := isatty.IsTerminal(os.Stdout.Fd())
stderrTerminal := isatty.IsTerminal(os.Stderr.Fd())
to := os.Stdout
if !stdoutTerminal && stderrTerminal {
to = os.Stderr
}
tail := newTail(to)
defer tail.Close()
if stdoutTerminal || config.TtyForced {
stdout = tail
}
if stderrTerminal || config.TtyForced {
stderr = tail
}
// send CLI messages to common stream so that output is formatted correctly
log.SetOutput(tail)
}
var stdoutBuffer bytes.Buffer
var stderrBuffer bytes.Buffer
stdoutWritter := io.MultiWriter(&stdoutBuffer, stdout)
stderrWritter := io.MultiWriter(&stderrBuffer, stderr)
if impl.Path != "" {
dir := impl.Dir
fmt.Printf(" Working dir: %s\n", dir)
fmt.Printf(" File: %s\n", impl.Path)
args := ""
if len(impl.Args) > 1 {
args = fmt.Sprintf("Args: %v", impl.Args[1:])
}
if args != "" {
fmt.Printf("--- %s\n", args)
}
}
os.Stdout.Sync()
os.Stderr.Sync()
if passStdin {
impl.Stdin = os.Stdin
}
stdoutComplete := goWait(func() { io.Copy(stdoutWritter, stdoutImpl) })
stderrComplete := goWait(func() { io.Copy(stderrWritter, stderrImpl) })
// Wait will close the pipe after seeing the command exit, so most callers
// need not close the pipe themselves; however, an implication is that it is
// incorrect to call Wait before all reads from the pipe have completed.
// For the same reason, it is incorrect to call Run when using StdoutPipe.
err = impl.Start()
<-stdoutComplete
<-stderrComplete
if impl.Path != "" {
fmt.Printf("--- \n")
}
os.Stdout.Sync()
os.Stderr.Sync()
log.SetOutput(logOutput)
if err == nil {
err = impl.Wait()
}
if err != nil {
err = fmt.Errorf("%v", err)
}
return stdoutBuffer.Bytes(), stderrBuffer.Bytes(), err
}