resolve the default remote branch dynamically

Rather than hardcode or fall over between branches, look up the
default the remote repo is using, and go with that locally too.

BUG=chromium:1126855, b:173131586
TEST=`./run_tests.sh` passes

Change-Id: I2b6b4aeb6ea404e68d32673c807187c8061d9f16
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/infra/go/+/2693059
Reviewed-by: Julio Hurtado <juahurta@google.com>
Commit-Queue: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/internal/git/git.go b/internal/git/git.go
index 6b10dfb..68ec058 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -336,3 +336,24 @@
 	}
 	return output.Stdout != "", nil
 }
+
+// ResolveRemoteSymbolicRef resolves the target of a symbolic ref.
+func ResolveRemoteSymbolicRef(gitRepo, remote string, ref string) (string, error) {
+	output, err := RunGit(gitRepo, []string{"ls-remote", "-q", "--symref", "--exit-code", remote, ref})
+	if err != nil {
+		if strings.Contains(output.Stderr, "not appear to be a git repository") {
+			return "", fmt.Errorf("%s is not a valid remote", remote)
+		}
+		return "", fmt.Errorf(output.Stderr)
+	}
+	// The output will look like (NB: tabs are separators):
+	// ref: refs/heads/main	HEAD
+	// 5f6803b100bb3cd0f534e96e88c91373e8ed1c44	HEAD
+	for _, line := range strings.Split(output.Stdout, "\n") {
+		parts := strings.SplitN(line, "\t", 2)
+		if strings.HasPrefix(parts[0], "ref:") && parts[1] == ref {
+			return strings.TrimSpace(parts[0][4:]), nil
+		}
+	}
+	return "", fmt.Errorf("unable to resolve %s", ref)
+}