gogit: add CheckoutStrategy tests
Signed-off-by: Hidde Beydals <hello@hidde.co>
This commit is contained in:
parent
0cf0d4e756
commit
80b9807550
|
@ -74,7 +74,7 @@ func (c *CheckoutBranch) Checkout(ctx context.Context, path, url string, opts *g
|
|||
RecurseSubmodules: recurseSubmodules(c.recurseSubmodules),
|
||||
Progress: nil,
|
||||
Tags: extgogit.NoTags,
|
||||
CABundle: opts.CAFile,
|
||||
CABundle: caBundle(opts),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, gitutil.GoGitError(err))
|
||||
|
@ -111,7 +111,7 @@ func (c *CheckoutTag) Checkout(ctx context.Context, path, url string, opts *git.
|
|||
RecurseSubmodules: recurseSubmodules(c.recurseSubmodules),
|
||||
Progress: nil,
|
||||
Tags: extgogit.NoTags,
|
||||
CABundle: opts.CAFile,
|
||||
CABundle: caBundle(opts),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, err)
|
||||
|
@ -148,7 +148,7 @@ func (c *CheckoutCommit) Checkout(ctx context.Context, path, url string, opts *g
|
|||
RecurseSubmodules: recurseSubmodules(c.recurseSubmodules),
|
||||
Progress: nil,
|
||||
Tags: extgogit.NoTags,
|
||||
CABundle: opts.CAFile,
|
||||
CABundle: caBundle(opts),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, err)
|
||||
|
@ -194,7 +194,7 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, opts *g
|
|||
RecurseSubmodules: recurseSubmodules(c.recurseSubmodules),
|
||||
Progress: nil,
|
||||
Tags: extgogit.AllTags,
|
||||
CABundle: opts.CAFile,
|
||||
CABundle: caBundle(opts),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, err)
|
||||
|
|
|
@ -18,37 +18,379 @@ package gogit
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fluxcd/source-controller/pkg/git"
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
extgogit "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/cache"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/storage/filesystem"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestCheckoutTagSemVer_Checkout(t *testing.T) {
|
||||
auth := &git.AuthOptions{}
|
||||
tag := CheckoutTag{
|
||||
tag: "v1.7.0",
|
||||
}
|
||||
tmpDir, _ := os.MkdirTemp("", "test")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
cTag, _, err := tag.Checkout(context.TODO(), tmpDir, "https://github.com/projectcontour/contour", auth)
|
||||
func TestCheckoutBranch_Checkout(t *testing.T) {
|
||||
repo, path, err := initRepo()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
|
||||
semVer := CheckoutSemVer{
|
||||
semVer: ">=1.0.0 <=1.7.0",
|
||||
}
|
||||
tmpDir2, _ := os.MkdirTemp("", "test")
|
||||
defer os.RemoveAll(tmpDir2)
|
||||
|
||||
cSemVer, _, err := semVer.Checkout(context.TODO(), tmpDir2, "https://github.com/projectcontour/contour", auth)
|
||||
firstCommit, err := commitFile(repo, "branch", "init", time.Now())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if cTag.Hash() != cSemVer.Hash() {
|
||||
t.Errorf("expected semver hash %s, got %s", cTag.Hash(), cSemVer.Hash())
|
||||
if err = createBranch(repo, "test"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
secondCommit, err := commitFile(repo, "branch", "second", time.Now())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
branch string
|
||||
expectedCommit string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "Default branch",
|
||||
branch: "master",
|
||||
expectedCommit: firstCommit.String(),
|
||||
},
|
||||
{
|
||||
name: "Other branch",
|
||||
branch: "test",
|
||||
expectedCommit: secondCommit.String(),
|
||||
},
|
||||
{
|
||||
name: "Non existing branch",
|
||||
branch: "invalid",
|
||||
expectedErr: "couldn't find remote ref \"refs/heads/invalid\"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
branch := CheckoutBranch{
|
||||
branch: tt.branch,
|
||||
}
|
||||
tmpDir, _ := os.MkdirTemp("", "test")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err := branch.Checkout(context.TODO(), tmpDir, path, nil)
|
||||
if tt.expectedErr != "" {
|
||||
g.Expect(err.Error()).To(ContainSubstring(tt.expectedErr))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
return
|
||||
}
|
||||
g.Expect(err).To(BeNil())
|
||||
g.Expect(ref).To(Equal(tt.branch + "/" + tt.expectedCommit))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckoutTag_Checkout(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
tag string
|
||||
annotated bool
|
||||
checkoutTag string
|
||||
expectTag string
|
||||
expectErr string
|
||||
}{
|
||||
{
|
||||
name: "Tag",
|
||||
tag: "tag-1",
|
||||
checkoutTag: "tag-1",
|
||||
expectTag: "tag-1",
|
||||
},
|
||||
{
|
||||
name: "Annotated",
|
||||
tag: "annotated",
|
||||
annotated: true,
|
||||
checkoutTag: "annotated",
|
||||
expectTag: "annotated",
|
||||
},
|
||||
{
|
||||
name: "Non existing tag",
|
||||
tag: "tag-1",
|
||||
checkoutTag: "invalid",
|
||||
expectErr: "error: couldn't find remote ref \"refs/tags/invalid\"",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
repo, path, err := initRepo()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
|
||||
var h plumbing.Hash
|
||||
if tt.tag != "" {
|
||||
h, err = commitFile(repo, "tag", tt.tag, time.Now())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = tag(repo, h, !tt.annotated, tt.tag, time.Now())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
tag := CheckoutTag{
|
||||
tag: tt.checkoutTag,
|
||||
}
|
||||
tmpDir, _ := os.MkdirTemp("", "test")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err := tag.Checkout(context.TODO(), tmpDir, path, nil)
|
||||
if tt.expectErr != "" {
|
||||
g.Expect(err.Error()).To(ContainSubstring(tt.expectErr))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
return
|
||||
}
|
||||
if tt.expectTag != "" {
|
||||
g.Expect(ref).To(Equal(tt.expectTag + "/" + h.String()))
|
||||
g.Expect(filepath.Join(tmpDir, "tag")).To(BeARegularFile())
|
||||
g.Expect(os.ReadFile(filepath.Join(tmpDir, "tag"))).To(BeEquivalentTo(tt.tag))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckoutCommit_Checkout(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
repo, path, err := initRepo()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
|
||||
c, err := commitFile(repo, "commit", "init", time.Now())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = commitFile(repo, "commit", "second", time.Now()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
commit := CheckoutCommit{
|
||||
commit: c.String(),
|
||||
branch: "master",
|
||||
}
|
||||
tmpDir, _ := os.MkdirTemp("", "git2go")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err := commit.Checkout(context.TODO(), tmpDir, path, nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(ref).To(Equal("master/" + c.String()))
|
||||
g.Expect(filepath.Join(tmpDir, "commit")).To(BeARegularFile())
|
||||
g.Expect(os.ReadFile(filepath.Join(tmpDir, "commit"))).To(BeEquivalentTo("init"))
|
||||
|
||||
commit = CheckoutCommit{
|
||||
commit: "4dc3185c5fc94eb75048376edeb44571cece25f4",
|
||||
branch: "master",
|
||||
}
|
||||
tmpDir2, _ := os.MkdirTemp("", "git2go")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err = commit.Checkout(context.TODO(), tmpDir2, path, nil)
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err.Error()).To(HavePrefix("git commit '4dc3185c5fc94eb75048376edeb44571cece25f4' not found:"))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
}
|
||||
|
||||
func TestCheckoutTagSemVer_Checkout(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tags := []struct {
|
||||
tag string
|
||||
annotated bool
|
||||
commitTime time.Time
|
||||
tagTime time.Time
|
||||
}{
|
||||
{
|
||||
tag: "v0.0.1",
|
||||
annotated: false,
|
||||
commitTime: now,
|
||||
},
|
||||
{
|
||||
tag: "v0.1.0+build-1",
|
||||
annotated: true,
|
||||
commitTime: now.Add(10 * time.Minute),
|
||||
tagTime: now.Add(2 * time.Hour), // This should be ignored during TS comparisons
|
||||
},
|
||||
{
|
||||
tag: "v0.1.0+build-2",
|
||||
annotated: false,
|
||||
commitTime: now.Add(30 * time.Minute),
|
||||
},
|
||||
{
|
||||
tag: "v0.1.0+build-3",
|
||||
annotated: true,
|
||||
commitTime: now.Add(1 * time.Hour),
|
||||
tagTime: now.Add(1 * time.Hour), // This should be ignored during TS comparisons
|
||||
},
|
||||
{
|
||||
tag: "0.2.0",
|
||||
annotated: true,
|
||||
commitTime: now,
|
||||
tagTime: now,
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
constraint string
|
||||
expectErr error
|
||||
expectTag string
|
||||
}{
|
||||
{
|
||||
name: "Orders by SemVer",
|
||||
constraint: ">0.1.0",
|
||||
expectTag: "0.2.0",
|
||||
},
|
||||
{
|
||||
name: "Orders by SemVer and timestamp",
|
||||
constraint: "<0.2.0",
|
||||
expectTag: "v0.1.0+build-3",
|
||||
},
|
||||
{
|
||||
name: "Errors without match",
|
||||
constraint: ">=1.0.0",
|
||||
expectErr: errors.New("no match found for semver: >=1.0.0"),
|
||||
},
|
||||
}
|
||||
|
||||
repo, path, err := initRepo()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
|
||||
refs := make(map[string]string, len(tags))
|
||||
for _, tt := range tags {
|
||||
ref, err := commitFile(repo, "tag", tt.tag, tt.commitTime)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = tag(repo, ref, tt.annotated, tt.tag, tt.tagTime)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
refs[tt.tag] = ref.String()
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
semVer := CheckoutSemVer{
|
||||
semVer: tt.constraint,
|
||||
}
|
||||
tmpDir, _ := os.MkdirTemp("", "test")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err := semVer.Checkout(context.TODO(), tmpDir, path, nil)
|
||||
if tt.expectErr != nil {
|
||||
g.Expect(err).To(Equal(tt.expectErr))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
return
|
||||
}
|
||||
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(ref).To(Equal(tt.expectTag + "/" + refs[tt.expectTag]))
|
||||
g.Expect(filepath.Join(tmpDir, "tag")).To(BeARegularFile())
|
||||
g.Expect(os.ReadFile(filepath.Join(tmpDir, "tag"))).To(BeEquivalentTo(tt.expectTag))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func initRepo() (*extgogit.Repository, string, error) {
|
||||
tmpDir, err := os.MkdirTemp("", "gogit")
|
||||
if err != nil {
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, "", err
|
||||
}
|
||||
sto := filesystem.NewStorage(osfs.New(tmpDir), cache.NewObjectLRUDefault())
|
||||
repo, err := extgogit.Init(sto, memfs.New())
|
||||
if err != nil {
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, "", err
|
||||
}
|
||||
return repo, tmpDir, err
|
||||
}
|
||||
|
||||
func createBranch(repo *extgogit.Repository, branch string) error {
|
||||
wt, err := repo.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h, err := repo.Head()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return wt.Checkout(&extgogit.CheckoutOptions{
|
||||
Hash: h.Hash(),
|
||||
Branch: plumbing.ReferenceName("refs/heads/" + branch),
|
||||
Create: true,
|
||||
})
|
||||
}
|
||||
|
||||
func commitFile(repo *extgogit.Repository, path, content string, time time.Time) (plumbing.Hash, error) {
|
||||
wt, err := repo.Worktree()
|
||||
if err != nil {
|
||||
return plumbing.Hash{}, err
|
||||
}
|
||||
f, err := wt.Filesystem.Create(path)
|
||||
if err != nil {
|
||||
return plumbing.Hash{}, err
|
||||
}
|
||||
if _, err = f.Write([]byte(content)); err != nil {
|
||||
f.Close()
|
||||
return plumbing.Hash{}, err
|
||||
}
|
||||
if err = f.Close(); err != nil {
|
||||
return plumbing.Hash{}, err
|
||||
}
|
||||
if _, err = wt.Add(path); err != nil {
|
||||
return plumbing.Hash{}, err
|
||||
}
|
||||
return wt.Commit("Adding: "+path, &extgogit.CommitOptions{
|
||||
Author: signature(time),
|
||||
Committer: signature(time),
|
||||
})
|
||||
}
|
||||
|
||||
func tag(repo *extgogit.Repository, commit plumbing.Hash, annotated bool, tag string, time time.Time) (*plumbing.Reference, error) {
|
||||
var opts *extgogit.CreateTagOptions
|
||||
if annotated {
|
||||
opts = &extgogit.CreateTagOptions{
|
||||
Tagger: signature(time),
|
||||
Message: "Annotated tag for: " + tag,
|
||||
}
|
||||
}
|
||||
return repo.CreateTag(tag, commit, opts)
|
||||
}
|
||||
|
||||
func signature(time time.Time) *object.Signature {
|
||||
return &object.Signature{
|
||||
Name: "Jane Doe",
|
||||
Email: "jane@example.com",
|
||||
When: time,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ import (
|
|||
// transportAuth constructs the transport.AuthMethod for the git.Transport of
|
||||
// the given git.AuthOptions. It returns the result, or an error.
|
||||
func transportAuth(opts *git.AuthOptions) (transport.AuthMethod, error) {
|
||||
if opts == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch opts.Transport {
|
||||
case git.HTTPS, git.HTTP:
|
||||
return &http.BasicAuth{
|
||||
|
@ -53,3 +56,11 @@ func transportAuth(opts *git.AuthOptions) (transport.AuthMethod, error) {
|
|||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// caBundle returns the CA bundle from the given git.AuthOptions.
|
||||
func caBundle(opts *git.AuthOptions) []byte {
|
||||
if opts == nil {
|
||||
return nil
|
||||
}
|
||||
return opts.CAFile
|
||||
}
|
||||
|
|
|
@ -193,3 +193,10 @@ func Test_transportAuth(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_caBundle(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
g.Expect(caBundle(&git.AuthOptions{CAFile: []byte("foo")})).To(BeEquivalentTo("foo"))
|
||||
g.Expect(caBundle(nil)).To(BeNil())
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ func TestCheckoutBranch_Checkout(t *testing.T) {
|
|||
|
||||
_, ref, err := branch.Checkout(context.TODO(), tmpDir, repo.Path(), nil)
|
||||
if tt.expectedErr != "" {
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err.Error()).To(ContainSubstring(tt.expectedErr))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
return
|
||||
|
@ -154,7 +155,8 @@ func TestCheckoutTag_Checkout(t *testing.T) {
|
|||
|
||||
_, ref, err := tag.Checkout(context.TODO(), tmpDir, repo.Path(), nil)
|
||||
if tt.expectErr != "" {
|
||||
g.Expect(err.Error()).To(Equal(tt.expectErr))
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err.Error()).To(ContainSubstring(tt.expectErr))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
return
|
||||
}
|
||||
|
@ -193,7 +195,7 @@ func TestCheckoutCommit_Checkout(t *testing.T) {
|
|||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err := commit.Checkout(context.TODO(), tmpDir, repo.Path(), nil)
|
||||
g.Expect(err).To(BeNil())
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(ref).To(Equal("main/" + c.String()))
|
||||
g.Expect(filepath.Join(tmpDir, "commit")).To(BeARegularFile())
|
||||
g.Expect(os.ReadFile(filepath.Join(tmpDir, "commit"))).To(BeEquivalentTo("init"))
|
||||
|
@ -205,6 +207,7 @@ func TestCheckoutCommit_Checkout(t *testing.T) {
|
|||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
_, ref, err = commit.Checkout(context.TODO(), tmpDir2, repo.Path(), nil)
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err.Error()).To(HavePrefix("git checkout error: git commit '4dc3185c5fc94eb75048376edeb44571cece25f4' not found:"))
|
||||
g.Expect(ref).To(BeEmpty())
|
||||
}
|
||||
|
@ -316,6 +319,7 @@ func TestCheckoutTagSemVer_Checkout(t *testing.T) {
|
|||
g.Expect(ref).To(BeEmpty())
|
||||
return
|
||||
}
|
||||
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(ref).To(Equal(tt.expectTag + "/" + refs[tt.expectTag]))
|
||||
g.Expect(filepath.Join(tmpDir, "tag")).To(BeARegularFile())
|
||||
|
|
Loading…
Reference in New Issue