checkout.RunGit function and some new test support code

I added a checkout.RunGit function which wraps the git.RunGit function
with some retry logic. Testing this was a PITA so I factored out &
improved some of our existing test support code for mocking cmd line calls.

BUG=chromium:980346
TEST=run_tests.sh

Change-Id: I707759e86bc09b4fbb0c3a23c9f0d66ba3413b01
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/infra/go/+/1700522
Commit-Queue: Jack Neus <jackneus@google.com>
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Evan Hernandez <evanhernandez@chromium.org>
Reviewed-by: Sean Abraham <seanabraham@chromium.org>
diff --git a/internal/git/git.go b/internal/git/git.go
index 640bd3e..f4a7ee4 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -7,29 +7,16 @@
 	"bytes"
 	"context"
 	"fmt"
-	"os/exec"
 	"regexp"
 	"strings"
+
+	"go.chromium.org/chromiumos/infra/go/internal/cmd"
 )
 
 var (
-	commandRunnerImpl commandRunner = realCommandRunner{}
+	CommandRunnerImpl cmd.CommandRunner = cmd.RealCommandRunner{}
 )
 
-type commandRunner interface {
-	runCommand(ctx context.Context, stdoutBuf, stderrBuf *bytes.Buffer, dir, name string, args ...string) error
-}
-
-type realCommandRunner struct{}
-
-func (c realCommandRunner) runCommand(ctx context.Context, stdoutBuf, stderrBuf *bytes.Buffer, dir, name string, args ...string) error {
-	cmd := exec.CommandContext(ctx, name, args...)
-	cmd.Stdout = stdoutBuf
-	cmd.Stderr = stderrBuf
-	cmd.Dir = dir
-	return cmd.Run()
-}
-
 type CommandOutput struct {
 	Stdout string
 	Stderr string
@@ -46,7 +33,7 @@
 func RunGit(gitRepo string, cmd []string) (CommandOutput, error) {
 	ctx := context.Background()
 	var stdoutBuf, stderrBuf bytes.Buffer
-	err := commandRunnerImpl.runCommand(ctx, &stdoutBuf, &stderrBuf, gitRepo, "git", cmd...)
+	err := CommandRunnerImpl.RunCommand(ctx, &stdoutBuf, &stderrBuf, gitRepo, "git", cmd...)
 	cmdOutput := CommandOutput{stdoutBuf.String(), stderrBuf.String()}
 	return cmdOutput, err
 }