piplineInternal takes a list of commands and a list of options (one for each). If opts is nil, all commands should be run with the default options.
(cmds [][]string, opts []CmdOpts)
| 53 | // piplineInternal takes a list of commands and a list of options (one for each). |
| 54 | // If opts is nil, all commands should be run with the default options. |
| 55 | func pipelineInternal(cmds [][]string, opts []CmdOpts) (string, error) { |
| 56 | x.AssertTrue(opts == nil || len(cmds) == len(opts)) |
| 57 | |
| 58 | var p io.ReadCloser |
| 59 | var numCmds = len(cmds) |
| 60 | |
| 61 | cmd := make([]*exec.Cmd, numCmds) |
| 62 | var stdout bytes.Buffer |
| 63 | |
| 64 | // Run all commands in parallel, connecting stdin of each to the stdout of the previous. |
| 65 | for i, c := range cmds { |
| 66 | lastCmd := i == numCmds-1 |
| 67 | if ShowCommand { |
| 68 | fmt.Fprintf(os.Stderr, "%+v", c) |
| 69 | } |
| 70 | |
| 71 | cmd[i] = exec.Command(c[0], c[1:]...) |
| 72 | cmd[i].Stdin = p |
| 73 | |
| 74 | if opts != nil { |
| 75 | cmd[i].Dir = opts[i].Dir |
| 76 | } |
| 77 | |
| 78 | if !lastCmd { |
| 79 | p, _ = cmd[i].StdoutPipe() |
| 80 | } else { |
| 81 | cmd[i].Stdout = &stdout |
| 82 | } |
| 83 | |
| 84 | if ShowOutput { |
| 85 | cmd[i].Stderr = os.Stderr |
| 86 | } else if ShowError { |
| 87 | cmd[i].Stderr = os.Stderr |
| 88 | } |
| 89 | |
| 90 | if ShowCommand { |
| 91 | if lastCmd { |
| 92 | fmt.Fprintf(os.Stderr, "\n") |
| 93 | } else { |
| 94 | fmt.Fprintf(os.Stderr, "\n| ") |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | err := cmd[i].Start() |
| 99 | x.Check(err) |
| 100 | } |
| 101 | |
| 102 | // Make sure to properly reap all spawned processes, but only save the error from the |
| 103 | // earliest stage of the pipeline. |
| 104 | var err error |
| 105 | for i := range cmds { |
| 106 | e := cmd[i].Wait() |
| 107 | if e != nil && err == nil { |
| 108 | err = e |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | outStr := stdout.String() |
no test coverage detected