diff --git a/source/gitidentifier.go b/source/gitidentifier.go index 1547c713..c6167475 100644 --- a/source/gitidentifier.go +++ b/source/gitidentifier.go @@ -2,10 +2,13 @@ package source import ( "net/url" + "os/exec" "path" + "regexp" "strings" "github.com/moby/buildkit/util/sshutil" + "github.com/pkg/errors" ) type GitIdentifier struct { @@ -19,6 +22,8 @@ type GitIdentifier struct { KnownSSHHosts string } +var defaultBranch = regexp.MustCompile(`refs/heads/(\S+)`) + func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) { repo := GitIdentifier{} @@ -35,6 +40,7 @@ func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) { if len(parts) == 2 { fragment = parts[1] } + repo.Ref, repo.Subdir = getRefAndSubdir(fragment) } else { u, err := url.Parse(remoteURL) @@ -49,6 +55,15 @@ func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) { if sd := path.Clean(repo.Subdir); sd == "/" || sd == "." { repo.Subdir = "" } + + if repo.Ref == "" { + var err error + repo.Ref, err = getDefaultBranch(repo.Remote) + if err != nil { + return nil, err + } + } + return &repo, nil } @@ -64,7 +79,7 @@ func isGitTransport(str string) bool { func getRefAndSubdir(fragment string) (ref string, subdir string) { refAndDir := strings.SplitN(fragment, ":", 2) - ref = "master" + ref = "" if len(refAndDir[0]) != 0 { ref = refAndDir[0] } @@ -73,3 +88,17 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) { } return } + +// getDefaultBranch gets the default branch of a repository using ls-remote +func getDefaultBranch(remoteURL string) (string, error) { + out, err := exec.Command("git", "ls-remote", "--symref", remoteURL, "HEAD").CombinedOutput() + if err != nil { + return "", errors.Errorf("error fetching default branch for repository %s: %v", remoteURL, err) + } + + ss := defaultBranch.FindAllStringSubmatch(string(out), -1) + if len(ss) == 0 || len(ss[0]) != 2 { + return "", errors.Errorf("could not find default branch for repository: %s", remoteURL) + } + return ss[0][1], nil +} diff --git a/source/gitidentifier_test.go b/source/gitidentifier_test.go index 20395945..9ba2e414 100644 --- a/source/gitidentifier_test.go +++ b/source/gitidentifier_test.go @@ -7,19 +7,13 @@ import ( ) func TestNewGitIdentifier(t *testing.T) { - gi, err := NewGitIdentifier("ssh://root@subdomain.example.hostname:2222/root/my/really/weird/path/foo.git") - require.Nil(t, err) - require.Equal(t, "ssh://root@subdomain.example.hostname:2222/root/my/really/weird/path/foo.git", gi.Remote) - require.Equal(t, "master", gi.Ref) - require.Equal(t, "", gi.Subdir) - - gi, err = NewGitIdentifier("ssh://root@subdomain.example.hostname:2222/root/my/really/weird/path/foo.git#main") + gi, err := NewGitIdentifier("ssh://root@subdomain.example.hostname:2222/root/my/really/weird/path/foo.git#main") require.Nil(t, err) require.Equal(t, "ssh://root@subdomain.example.hostname:2222/root/my/really/weird/path/foo.git", gi.Remote) require.Equal(t, "main", gi.Ref) require.Equal(t, "", gi.Subdir) - gi, err = NewGitIdentifier("git@github.com:moby/buildkit.git") + gi, err = NewGitIdentifier("git@github.com:moby/buildkit.git#master") require.Nil(t, err) require.Equal(t, "git@github.com:moby/buildkit.git", gi.Remote) require.Equal(t, "master", gi.Ref)