summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
Diffstat (limited to 'data')
-rw-r--r--data/datasource_git.go52
-rw-r--r--data/datasource_git_test.go14
2 files changed, 63 insertions, 3 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,
diff --git a/data/datasource_git_test.go b/data/datasource_git_test.go
index f48393c3..33771410 100644
--- a/data/datasource_git_test.go
+++ b/data/datasource_git_test.go
@@ -229,10 +229,18 @@ func setupGitRepo(t *testing.T) billy.Filesystem {
r, err := git.Init(s, repo)
assert.NilError(t, err)
+ // default to main
+ h := plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.ReferenceName("refs/heads/main"))
+ err = s.SetReference(h)
+ assert.NilError(t, err)
+
// config needs to be created after setting up a "normal" fs repo
// this is possibly a bug in git-go?
c, err := r.Config()
assert.NilError(t, err)
+
+ c.Init.DefaultBranch = "main"
+
s.SetConfig(c)
assert.NilError(t, err)
@@ -331,12 +339,12 @@ func TestOpenFileRepo(t *testing.T) {
b, _ := ioutil.ReadAll(f)
assert.Equal(t, "hello world", string(b))
- _, repo, err := g.clone(ctx, mustParseURL("git+file:///repo#master"), 0)
+ _, repo, err := g.clone(ctx, mustParseURL("git+file:///repo#main"), 0)
assert.NilError(t, err)
- ref, err := repo.Reference(plumbing.NewBranchReferenceName("master"), true)
+ ref, err := repo.Reference(plumbing.NewBranchReferenceName("main"), true)
assert.NilError(t, err)
- assert.Equal(t, "refs/heads/master", ref.Name().String())
+ assert.Equal(t, "refs/heads/main", ref.Name().String())
_, repo, err = g.clone(ctx, mustParseURL("git+file:///repo#refs/tags/v1"), 0)
assert.NilError(t, err)