infra/go: misc TODOs

Updated git.PushRef to take a force parameter. Also wrote a small unit test for something.

BUG=None
TEST=run_tests.sh

Change-Id: I8dbd8d79b47380ecc15be5d5de1a1b345db8ba78
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/infra/go/+/1758856
Reviewed-by: Benjamin Gordon <bmgordon@chromium.org>
Reviewed-by: Evan Hernandez <evanhernandez@chromium.org>
Commit-Queue: Jack Neus <jackneus@google.com>
Tested-by: Jack Neus <jackneus@google.com>
diff --git a/internal/git/git.go b/internal/git/git.go
index 9793f00..6b10dfb 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -30,6 +30,11 @@
 	Ref    string
 }
 
+type GitOpts struct {
+	DryRun bool
+	Force  bool
+}
+
 // RunGit the specified git command in the specified repo. It returns
 // stdout and stderr.
 func RunGit(gitRepo string, cmd []string) (CommandOutput, error) {
@@ -221,18 +226,21 @@
 	}
 	output, err := RunGit(gitRepo, []string{"rev-parse", "HEAD"})
 	if err != nil {
-		return "", nil
+		return "", err
 	}
 	return strings.TrimSpace(output.Stdout), nil
 }
 
 // PushRef pushes the specified local ref to the specified remote ref.
-func PushRef(gitRepo, localRef string, dryRun bool, pushTo RemoteRef) error {
+func PushRef(gitRepo, localRef string, pushTo RemoteRef, opts GitOpts) error {
 	ref := fmt.Sprintf("%s:%s", localRef, pushTo.Ref)
 	cmd := []string{"push", pushTo.Remote, ref}
-	if dryRun {
+	if opts.DryRun {
 		cmd = append(cmd, "--dry-run")
 	}
+	if opts.Force {
+		cmd = append(cmd, "--force")
+	}
 	_, err := RunGit(gitRepo, cmd)
 	return err
 }
diff --git a/internal/git/git_test.go b/internal/git/git_test.go
index 17f7a98..c87c53b 100644
--- a/internal/git/git_test.go
+++ b/internal/git/git_test.go
@@ -288,10 +288,14 @@
 	pushStr := fmt.Sprintf("%s:%s", localRef, remoteRef.Ref)
 	CommandRunnerImpl = cmd.FakeCommandRunner{
 		ExpectedDir: fakeGitRepo,
-		ExpectedCmd: []string{"git", "push", remoteRef.Remote, pushStr, "--dry-run"},
+		ExpectedCmd: []string{"git", "push", remoteRef.Remote, pushStr, "--dry-run", "--force"},
 	}
 
-	err := PushRef(fakeGitRepo, localRef, true, remoteRef)
+	opts := GitOpts{
+		DryRun: true,
+		Force:  true,
+	}
+	err := PushRef(fakeGitRepo, localRef, remoteRef, opts)
 	assert.NilError(t, err)
 }
 
@@ -459,9 +463,13 @@
 		Remote: "remote",
 		Ref:    "foo",
 	}
-	assert.NilError(t, PushRef(local, "HEAD", false, remoteRef))
+	opts := GitOpts{
+		DryRun: false,
+		Force:  true,
+	}
+	assert.NilError(t, PushRef(local, "HEAD", remoteRef, opts))
 	remoteRef.Ref = "bar"
-	assert.NilError(t, PushRef(local, "HEAD", false, remoteRef))
+	assert.NilError(t, PushRef(local, "HEAD", remoteRef, opts))
 
 	branches, err := RemoteBranches(local, "remote")
 	assert.NilError(t, err)