summaryrefslogtreecommitdiff
path: root/data/datasource_git.go
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2021-09-24 12:32:18 -0400
committerGitHub <noreply@github.com>2021-09-24 16:32:18 +0000
commit67697bba2ba926954508a05628a838457b25fa0e (patch)
tree97d3e976b24ed23f79a4da5fa34bf7f3e609890f /data/datasource_git.go
parentdc1c992939579b15c7d0ba7498065185eb2f6655 (diff)
Attempt to find the correct default git branch (#1217)
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'data/datasource_git.go')
-rw-r--r--data/datasource_git.go52
1 files changed, 52 insertions, 0 deletions
diff --git a/data/datasource_git.go b/data/datasource_git.go
index 6c2491de..bd1811b4 100644
--- a/data/datasource_git.go
+++ b/data/datasource_git.go
@@ -14,12 +14,14 @@ import (
"github.com/hairyhenderson/gomplate/v3/base64"
"github.com/hairyhenderson/gomplate/v3/env"
+ "github.com/rs/zerolog"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/transport"
+ "github.com/go-git/go-git/v5/plumbing/transport/client"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/go-git/go-git/v5/storage/memory"
@@ -141,6 +143,7 @@ func cloneURL(u *url.URL) *url.URL {
return out
}
+// refFromURL - extract the ref from the URL fragment if present
func (g gitsource) refFromURL(u *url.URL) plumbing.ReferenceName {
switch {
case strings.HasPrefix(u.Fragment, "refs/"):
@@ -152,6 +155,44 @@ func (g gitsource) refFromURL(u *url.URL) plumbing.ReferenceName {
}
}
+// refFromRemoteHead - extract the ref from the remote HEAD, to work around
+// hard-coded 'master' default branch in go-git.
+// Should be unnecessary once https://github.com/go-git/go-git/issues/249 is
+// fixed.
+func (g gitsource) refFromRemoteHead(ctx context.Context, u *url.URL, auth transport.AuthMethod) (plumbing.ReferenceName, error) {
+ e, err := transport.NewEndpoint(u.String())
+ if err != nil {
+ return "", err
+ }
+
+ cli, err := client.NewClient(e)
+ if err != nil {
+ return "", err
+ }
+
+ s, err := cli.NewUploadPackSession(e, auth)
+ if err != nil {
+ return "", err
+ }
+
+ info, err := s.AdvertisedReferencesContext(ctx)
+ if err != nil {
+ return "", err
+ }
+
+ refs, err := info.AllReferences()
+ if err != nil {
+ return "", err
+ }
+
+ headRef, ok := refs["HEAD"]
+ if !ok {
+ return "", fmt.Errorf("no HEAD ref found")
+ }
+
+ return headRef.Target(), nil
+}
+
// clone a repo for later reading through http(s), git, or ssh. u must be the URL to the repo
// itself, and must have any file path stripped
func (g gitsource) clone(ctx context.Context, repoURL *url.URL, depth int) (billy.Filesystem, *git.Repository, error) {
@@ -175,6 +216,17 @@ func (g gitsource) clone(ctx context.Context, repoURL *url.URL, depth int) (bill
u.Fragment = ""
u.RawQuery = ""
+ // attempt to get the ref from the remote so we don't default to master
+ if ref == "" {
+ ref, err = g.refFromRemoteHead(ctx, u, auth)
+ if err != nil {
+ zerolog.Ctx(ctx).Warn().
+ Stringer("repoURL", u).
+ Err(err).
+ Msg("failed to get ref from remote, using default")
+ }
+ }
+
opts := &git.CloneOptions{
URL: u.String(),
Auth: auth,