command: Require callers to explicitly set up stdout
When not providing an stdout writer to command.New(), we implicitly
set up the command such that it writes into a pipe. This has multiple
downsides:
- It is not easy to see whether a specific command needs it stdout
at all.
- Commands whose stdout is never read are wasting CPU time to write
data that nobody is going to read.
- Commands whose stdout is never read may deadlock when they write a
sufficient amount of data that fills the pipe's buffer. This is a
bug waiting to happen.
- We need to discard stdout when calling `command.Wait()` in order
to discard any potential output in order to unblock commands. This
is not only a waste of CPU time, but also causes bugs because
context cancellation may cause any concurrent readers to race with
this drain.
The only upside of the current code is that it's less verbose given that a lot of callsites actually do want to read stdout.
Refactor the code to require explicit setup of standard output via a new
WithSetupStdout() option in both the command and git package that
mirrors the preexisting WithSetupStdin() option. This addresses the
first three shortcomings while also paving a way to fix the last one,
where we should instead be able to just close the stdout pipe instead of
draining it.
Part of #5021 (closed).