controllers: implement checkout strategies
This commit is contained in:
parent
40b1369ace
commit
9c67baa158
|
|
@ -22,9 +22,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/blang/semver"
|
|
||||||
"github.com/go-git/go-git/v5"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/object"
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
|
@ -122,36 +119,18 @@ func (r *GitRepositoryReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.GitRepository) (sourcev1.GitRepository, error) {
|
func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.GitRepository) (sourcev1.GitRepository, error) {
|
||||||
// set defaults: master branch, no tags fetching, max two commits
|
// create tmp dir for the Git clone
|
||||||
branch := "master"
|
tmpGit, err := ioutil.TempDir("", repository.Name)
|
||||||
revision := ""
|
if err != nil {
|
||||||
tagMode := git.NoTags
|
err = fmt.Errorf("tmp dir error: %w", err)
|
||||||
depth := 2
|
return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||||
|
|
||||||
// determine ref
|
|
||||||
refName := plumbing.NewBranchReferenceName(branch)
|
|
||||||
|
|
||||||
if repository.Spec.Reference != nil {
|
|
||||||
if repository.Spec.Reference.Branch != "" {
|
|
||||||
branch = repository.Spec.Reference.Branch
|
|
||||||
refName = plumbing.NewBranchReferenceName(branch)
|
|
||||||
}
|
|
||||||
if repository.Spec.Reference.Commit != "" {
|
|
||||||
depth = 0
|
|
||||||
} else {
|
|
||||||
if repository.Spec.Reference.Tag != "" {
|
|
||||||
refName = plumbing.NewTagReferenceName(repository.Spec.Reference.Tag)
|
|
||||||
}
|
|
||||||
if repository.Spec.Reference.SemVer != "" {
|
|
||||||
tagMode = git.AllTags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
defer os.RemoveAll(tmpGit)
|
||||||
|
|
||||||
// determine auth method
|
// determine auth method
|
||||||
strategy := intgit.AuthSecretStrategyForURL(repository.Spec.URL)
|
|
||||||
var auth transport.AuthMethod
|
var auth transport.AuthMethod
|
||||||
if repository.Spec.SecretRef != nil {
|
authStrategy := intgit.AuthSecretStrategyForURL(repository.Spec.URL)
|
||||||
|
if repository.Spec.SecretRef != nil && authStrategy != nil {
|
||||||
name := types.NamespacedName{
|
name := types.NamespacedName{
|
||||||
Namespace: repository.GetNamespace(),
|
Namespace: repository.GetNamespace(),
|
||||||
Name: repository.Spec.SecretRef.Name,
|
Name: repository.Spec.SecretRef.Name,
|
||||||
|
|
@ -164,124 +143,16 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
}
|
}
|
||||||
|
|
||||||
auth, err = strategy.Method(secret)
|
auth, err = authStrategy.Method(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("auth error: %w", err)
|
err = fmt.Errorf("auth error: %w", err)
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create tmp dir for the Git clone
|
checkoutStrategy := intgit.CheckoutStrategyForRef(repository.Spec.Reference)
|
||||||
tmpGit, err := ioutil.TempDir("", repository.Name)
|
commit, revision, err := checkoutStrategy.Checkout(ctx, tmpGit, repository.Spec.URL, auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("tmp dir error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpGit)
|
|
||||||
|
|
||||||
// clone to tmp
|
|
||||||
gitCtx, cancel := context.WithTimeout(ctx, repository.GetTimeout())
|
|
||||||
repo, err := git.PlainCloneContext(gitCtx, tmpGit, false, &git.CloneOptions{
|
|
||||||
URL: repository.Spec.URL,
|
|
||||||
Auth: auth,
|
|
||||||
RemoteName: "origin",
|
|
||||||
ReferenceName: refName,
|
|
||||||
SingleBranch: true,
|
|
||||||
NoCheckout: false,
|
|
||||||
Depth: depth,
|
|
||||||
RecurseSubmodules: 0,
|
|
||||||
Progress: nil,
|
|
||||||
Tags: tagMode,
|
|
||||||
})
|
|
||||||
cancel()
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git clone error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkout commit or tag
|
|
||||||
if repository.Spec.Reference != nil {
|
|
||||||
if commit := repository.Spec.Reference.Commit; commit != "" {
|
|
||||||
w, err := repo.Worktree()
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git worktree error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = w.Checkout(&git.CheckoutOptions{
|
|
||||||
Hash: plumbing.NewHash(commit),
|
|
||||||
Force: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git checkout '%s' for '%s' error: %w", commit, branch, err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
} else if exp := repository.Spec.Reference.SemVer; exp != "" {
|
|
||||||
rng, err := semver.ParseRange(exp)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("semver parse range error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
repoTags, err := repo.Tags()
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git list tags error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
tags := make(map[string]string)
|
|
||||||
_ = repoTags.ForEach(func(t *plumbing.Reference) error {
|
|
||||||
tags[t.Name().Short()] = t.Strings()[1]
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
svTags := make(map[string]string)
|
|
||||||
var svers []semver.Version
|
|
||||||
for tag, _ := range tags {
|
|
||||||
v, _ := semver.ParseTolerant(tag)
|
|
||||||
if rng(v) {
|
|
||||||
svers = append(svers, v)
|
|
||||||
svTags[v.String()] = tag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(svers) > 0 {
|
|
||||||
semver.Sort(svers)
|
|
||||||
v := svers[len(svers)-1]
|
|
||||||
t := svTags[v.String()]
|
|
||||||
commit := tags[t]
|
|
||||||
revision = fmt.Sprintf("%s/%s", t, commit)
|
|
||||||
|
|
||||||
w, err := repo.Worktree()
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git worktree error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = w.Checkout(&git.CheckoutOptions{
|
|
||||||
Hash: plumbing.NewHash(commit),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git checkout error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = fmt.Errorf("no match found for semver: %s", repository.Spec.Reference.SemVer)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read commit hash
|
|
||||||
ref, err := repo.Head()
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git resolve HEAD error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
commit, err := repo.CommitObject(ref.Hash())
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("git resolve HEAD error: %w", err)
|
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,15 +167,8 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if revision == "" {
|
|
||||||
revision = fmt.Sprintf("%s/%s", branch, ref.Hash().String())
|
|
||||||
if repository.Spec.Reference != nil && repository.Spec.Reference.Tag != "" {
|
|
||||||
revision = fmt.Sprintf("%s/%s", repository.Spec.Reference.Tag, ref.Hash().String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
artifact := r.Storage.ArtifactFor(repository.Kind, repository.ObjectMeta.GetObjectMeta(),
|
artifact := r.Storage.ArtifactFor(repository.Kind, repository.ObjectMeta.GetObjectMeta(),
|
||||||
fmt.Sprintf("%s.tar.gz", ref.Hash().String()), revision)
|
fmt.Sprintf("%s.tar.gz", commit.Hash.String()), revision)
|
||||||
|
|
||||||
// create artifact dir
|
// create artifact dir
|
||||||
err = r.Storage.MkdirAll(artifact)
|
err = r.Storage.MkdirAll(artifact)
|
||||||
|
|
|
||||||
|
|
@ -23,21 +23,47 @@ import (
|
||||||
"github.com/blang/semver"
|
"github.com/blang/semver"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||||
|
|
||||||
|
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultOrigin = "origin"
|
||||||
|
defaultBranch = "master"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckoutStrategyForRef(ref *sourcev1.GitRepositoryRef) CheckoutStrategy {
|
||||||
|
switch {
|
||||||
|
case ref == nil:
|
||||||
|
return &CheckoutBranch{branch: defaultBranch}
|
||||||
|
case ref.SemVer != "":
|
||||||
|
return &CheckoutSemVer{semVer: ref.SemVer}
|
||||||
|
case ref.Tag != "":
|
||||||
|
return &CheckoutTag{tag: ref.Tag}
|
||||||
|
case ref.Commit != "":
|
||||||
|
return &CheckoutCommit{branch: ref.Branch, commit: ref.Commit}
|
||||||
|
case ref.Branch != "":
|
||||||
|
return &CheckoutBranch{branch: ref.Branch}
|
||||||
|
default:
|
||||||
|
return &CheckoutBranch{branch: defaultBranch}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type CheckoutStrategy interface {
|
type CheckoutStrategy interface {
|
||||||
Checkout(ctx context.Context, path string) error
|
Checkout(ctx context.Context, path, url string, auth transport.AuthMethod) (*object.Commit, string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckoutBranch struct {
|
type CheckoutBranch struct {
|
||||||
url string
|
|
||||||
branch string
|
branch string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CheckoutBranch) Checkout(ctx context.Context, path string) (string, error) {
|
func (c *CheckoutBranch) Checkout(ctx context.Context, path, url string, auth transport.AuthMethod) (*object.Commit, string, error) {
|
||||||
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
||||||
URL: c.url,
|
URL: url,
|
||||||
RemoteName: "origin",
|
Auth: auth,
|
||||||
|
RemoteName: defaultOrigin,
|
||||||
ReferenceName: plumbing.NewBranchReferenceName(c.branch),
|
ReferenceName: plumbing.NewBranchReferenceName(c.branch),
|
||||||
SingleBranch: true,
|
SingleBranch: true,
|
||||||
NoCheckout: false,
|
NoCheckout: false,
|
||||||
|
|
@ -47,24 +73,28 @@ func (c *CheckoutBranch) Checkout(ctx context.Context, path string) (string, err
|
||||||
Tags: git.NoTags,
|
Tags: git.NoTags,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git clone error: %w", err)
|
return nil, "", fmt.Errorf("git clone error: %w", err)
|
||||||
}
|
}
|
||||||
head, err := repo.Head()
|
head, err := repo.Head()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf(" git resolve HEAD error: %w", err)
|
return nil, "", fmt.Errorf("git resolve HEAD error: %w", err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/%s", c.branch, head.Hash().String()), nil
|
commit, err := repo.CommitObject(head.Hash())
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("git commit not found: %w", err)
|
||||||
|
}
|
||||||
|
return commit, fmt.Sprintf("%s/%s", c.branch, head.Hash().String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckoutTag struct {
|
type CheckoutTag struct {
|
||||||
url string
|
|
||||||
tag string
|
tag string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CheckoutTag) Checkout(ctx context.Context, path string) (string, error) {
|
func (c *CheckoutTag) Checkout(ctx context.Context, path, url string, auth transport.AuthMethod) (*object.Commit, string, error) {
|
||||||
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
||||||
URL: c.url,
|
URL: url,
|
||||||
RemoteName: "origin",
|
Auth: auth,
|
||||||
|
RemoteName: defaultOrigin,
|
||||||
ReferenceName: plumbing.NewTagReferenceName(c.tag),
|
ReferenceName: plumbing.NewTagReferenceName(c.tag),
|
||||||
SingleBranch: true,
|
SingleBranch: true,
|
||||||
NoCheckout: false,
|
NoCheckout: false,
|
||||||
|
|
@ -74,25 +104,29 @@ func (c *CheckoutTag) Checkout(ctx context.Context, path string) (string, error)
|
||||||
Tags: git.NoTags,
|
Tags: git.NoTags,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git clone error: %w", err)
|
return nil, "", fmt.Errorf("git clone error: %w", err)
|
||||||
}
|
}
|
||||||
head, err := repo.Head()
|
head, err := repo.Head()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf(" git resolve HEAD error: %w", err)
|
return nil, "", fmt.Errorf("git resolve HEAD error: %w", err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/%s", c.tag, head.Hash().String()), nil
|
commit, err := repo.CommitObject(head.Hash())
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("git commit not found: %w", err)
|
||||||
|
}
|
||||||
|
return commit, fmt.Sprintf("%s/%s", c.tag, head.Hash().String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckoutCommit struct {
|
type CheckoutCommit struct {
|
||||||
url string
|
|
||||||
branch string
|
branch string
|
||||||
commit string
|
commit string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CheckoutCommit) Checkout(ctx context.Context, path string) (string, error) {
|
func (c *CheckoutCommit) Checkout(ctx context.Context, path, url string, auth transport.AuthMethod) (*object.Commit, string, error) {
|
||||||
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
||||||
URL: c.url,
|
URL: url,
|
||||||
RemoteName: "origin",
|
Auth: auth,
|
||||||
|
RemoteName: defaultOrigin,
|
||||||
ReferenceName: plumbing.NewBranchReferenceName(c.branch),
|
ReferenceName: plumbing.NewBranchReferenceName(c.branch),
|
||||||
SingleBranch: true,
|
SingleBranch: true,
|
||||||
NoCheckout: false,
|
NoCheckout: false,
|
||||||
|
|
@ -101,40 +135,40 @@ func (c *CheckoutCommit) Checkout(ctx context.Context, path string) (string, err
|
||||||
Tags: git.NoTags,
|
Tags: git.NoTags,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git clone error: %w", err)
|
return nil, "", fmt.Errorf("git clone error: %w", err)
|
||||||
}
|
}
|
||||||
w, err := repo.Worktree()
|
w, err := repo.Worktree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git worktree error: %w", err)
|
return nil, "", fmt.Errorf("git worktree error: %w", err)
|
||||||
}
|
}
|
||||||
commit, err := repo.CommitObject(plumbing.NewHash(c.commit))
|
commit, err := repo.CommitObject(plumbing.NewHash(c.commit))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git commit not found: %w", err)
|
return nil, "", fmt.Errorf("git commit not found: %w", err)
|
||||||
}
|
}
|
||||||
err = w.Checkout(&git.CheckoutOptions{
|
err = w.Checkout(&git.CheckoutOptions{
|
||||||
Hash: commit.Hash,
|
Hash: commit.Hash,
|
||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git checkout error: %w", err)
|
return nil, "", fmt.Errorf("git checkout error: %w", err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/%s", c.branch, commit.Hash.String()), nil
|
return commit, fmt.Sprintf("%s/%s", c.branch, commit.Hash.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckoutSemVer struct {
|
type CheckoutSemVer struct {
|
||||||
url string
|
semVer string
|
||||||
semver string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CheckoutSemVer) Checkout(ctx context.Context, path string) (string, error) {
|
func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth transport.AuthMethod) (*object.Commit, string, error) {
|
||||||
rng, err := semver.ParseRange(c.semver)
|
rng, err := semver.ParseRange(c.semVer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("semver parse range error: %w", err)
|
return nil, "", fmt.Errorf("semver parse range error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
|
||||||
URL: c.url,
|
URL: url,
|
||||||
RemoteName: "origin",
|
Auth: auth,
|
||||||
|
RemoteName: defaultOrigin,
|
||||||
SingleBranch: true,
|
SingleBranch: true,
|
||||||
NoCheckout: false,
|
NoCheckout: false,
|
||||||
Depth: 1,
|
Depth: 1,
|
||||||
|
|
@ -143,12 +177,12 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path string) (string, err
|
||||||
Tags: git.AllTags,
|
Tags: git.AllTags,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git clone error: %w", err)
|
return nil, "", fmt.Errorf("git clone error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repoTags, err := repo.Tags()
|
repoTags, err := repo.Tags()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git list tags error: %w", err)
|
return nil, "", fmt.Errorf("git list tags error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tags := make(map[string]string)
|
tags := make(map[string]string)
|
||||||
|
|
@ -168,25 +202,29 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path string) (string, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(svers) == 0 {
|
if len(svers) == 0 {
|
||||||
return "", fmt.Errorf("no match found for semver: %s", c.semver)
|
return nil, "", fmt.Errorf("no match found for semver: %s", c.semVer)
|
||||||
}
|
}
|
||||||
|
|
||||||
semver.Sort(svers)
|
semver.Sort(svers)
|
||||||
v := svers[len(svers)-1]
|
v := svers[len(svers)-1]
|
||||||
t := svTags[v.String()]
|
t := svTags[v.String()]
|
||||||
commit := tags[t]
|
commitRef := tags[t]
|
||||||
|
|
||||||
w, err := repo.Worktree()
|
w, err := repo.Worktree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git worktree error: %w", err)
|
return nil, "", fmt.Errorf("git worktree error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commit, err := repo.CommitObject(plumbing.NewHash(commitRef))
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("git commit not found: %w", err)
|
||||||
|
}
|
||||||
err = w.Checkout(&git.CheckoutOptions{
|
err = w.Checkout(&git.CheckoutOptions{
|
||||||
Hash: plumbing.NewHash(commit),
|
Hash: commit.Hash,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("git checkout error: %w", err)
|
return nil, "", fmt.Errorf("git checkout error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s/%s", t, commit), nil
|
return commit, fmt.Sprintf("%s/%s", t, commitRef), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue