diff --git a/util/gitutil/gitutil.go b/util/gitutil/gitutil.go index 22aa72ee..c781311e 100644 --- a/util/gitutil/gitutil.go +++ b/util/gitutil/gitutil.go @@ -78,7 +78,13 @@ func (c *Git) GitDir() (string, error) { } func (c *Git) RemoteURL() (string, error) { - // Try to get the remote URL from the origin remote first + // Try default remote based on remote tracking branch + if remote, err := c.currentRemote(); err == nil && remote != "" { + if ru, err := c.clean(c.run("remote", "get-url", remote)); err == nil && ru != "" { + return stripCredentials(ru), nil + } + } + // Next try to get the remote URL from the origin remote first if ru, err := c.clean(c.run("remote", "get-url", "origin")); err == nil && ru != "" { return stripCredentials(ru), nil } @@ -149,6 +155,22 @@ func (c *Git) clean(out string, err error) (string, error) { return out, err } +func (c *Git) currentRemote() (string, error) { + symref, err := c.clean(c.run("symbolic-ref", "-q", "HEAD")) + if err != nil { + return "", err + } + if symref == "" { + return "", nil + } + // git for-each-ref --format='%(upstream:remotename)' + remote, err := c.clean(c.run("for-each-ref", "--format=%(upstream:remotename)", symref)) + if err != nil { + return "", err + } + return remote, nil +} + func IsUnknownRevision(err error) bool { if err == nil { return false diff --git a/util/gitutil/gitutil_test.go b/util/gitutil/gitutil_test.go index 991cd32e..06c6fa45 100644 --- a/util/gitutil/gitutil_test.go +++ b/util/gitutil/gitutil_test.go @@ -106,8 +106,9 @@ func TestGitDescribeTags(t *testing.T) { func TestGitRemoteURL(t *testing.T) { type remote struct { - name string - url string + name string + url string + tracking string } cases := []struct { @@ -165,6 +166,36 @@ func TestGitRemoteURL(t *testing.T) { }, fail: true, }, + { + name: "single tracking branch", + remotes: []remote{ + { + name: "foo", + url: "https://github.com/tonistiigi/buildx.git", + tracking: "master", + }, + }, + expected: "https://github.com/tonistiigi/buildx.git", + }, + { + name: "fork tracking branch", + remotes: []remote{ + { + name: "origin", + url: "git@github.com:crazy-max/buildx.git", + }, + { + name: "foobranch", + url: "https://github.com/tonistiigi/buildx.git", + tracking: "master", + }, + { + name: "crazymax", + url: "git@github.com:crazy-max/buildx.git", + }, + }, + expected: "https://github.com/tonistiigi/buildx.git", + }, } for _, tt := range cases { tt := tt @@ -177,6 +208,9 @@ func TestGitRemoteURL(t *testing.T) { GitCommit(c, t, "initial commit") for _, r := range tt.remotes { GitSetRemote(c, t, r.name, r.url) + if r.tracking != "" { + GitSetMainUpstream(c, t, r.name, r.tracking) + } } ru, err := c.RemoteURL() diff --git a/util/gitutil/testutil.go b/util/gitutil/testutil.go index ea9dd058..d0de8970 100644 --- a/util/gitutil/testutil.go +++ b/util/gitutil/testutil.go @@ -52,6 +52,15 @@ func GitSetRemote(c *Git, tb testing.TB, name string, url string) { require.NoError(tb, err) } +func GitSetMainUpstream(c *Git, tb testing.TB, remote, target string) { + tb.Helper() + _, err := fakeGit(c, "fetch", "--depth", "1", remote, target) + require.NoError(tb, err) + + _, err = fakeGit(c, "branch", "--set-upstream-to", remote+"/"+target, "main") + require.NoError(tb, err) +} + func Mktmp(tb testing.TB) string { tb.Helper() folder := tb.TempDir()