Skip to content

Commit d0560e5

Browse files
committed
Use same SemVer logic in both Git implementations
Signed-off-by: Hidde Beydals <hello@hidde.co>
1 parent 77d1c9c commit d0560e5

File tree

4 files changed

+57
-23
lines changed

4 files changed

+57
-23
lines changed

go.mod

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ replace github.com/fluxcd/source-controller/api => ./api
66

77
require (
88
github.com/Masterminds/semver/v3 v3.1.1
9-
github.com/blang/semver/v4 v4.0.0
109
github.com/cyphar/filepath-securejoin v0.2.2
1110
github.com/fluxcd/pkg/apis/meta v0.10.0
1211
github.com/fluxcd/pkg/gittestserver v0.3.0

go.sum

-3
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
113113
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
114114
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
115115
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
116-
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
117116
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
118-
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
119-
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
120117
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
121118
github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA=
122119
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=

pkg/git/gogit/checkout.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g
193193

194194
tags := make(map[string]string)
195195
tagTimestamps := make(map[string]time.Time)
196-
_ = repoTags.ForEach(func(t *plumbing.Reference) error {
196+
if err = repoTags.ForEach(func(t *plumbing.Reference) error {
197197
revision := plumbing.Revision(t.Name().String())
198198
hash, err := repo.ResolveRevision(revision)
199199
if err != nil {
@@ -207,7 +207,9 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g
207207

208208
tags[t.Name().Short()] = t.Strings()[1]
209209
return nil
210-
})
210+
}); err != nil {
211+
return nil, "", err
212+
}
211213

212214
var matchedVersions semver.Collection
213215
for tag, _ := range tags {

pkg/git/libgit2/checkout.go

+53-17
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ package libgit2
1919
import (
2020
"context"
2121
"fmt"
22+
"sort"
23+
"time"
2224

23-
"github.com/blang/semver/v4"
25+
"github.com/Masterminds/semver/v3"
26+
"github.com/fluxcd/pkg/version"
2427
git2go "github.com/libgit2/git2go/v31"
2528

2629
"github.com/fluxcd/pkg/gitutil"
@@ -168,7 +171,7 @@ type CheckoutSemVer struct {
168171
}
169172

170173
func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *git.Auth) (git.Commit, string, error) {
171-
rng, err := semver.ParseRange(c.semVer)
174+
verConstraint, err := semver.NewConstraint(c.semVer)
172175
if err != nil {
173176
return nil, "", fmt.Errorf("semver parse range error: %w", err)
174177
}
@@ -186,28 +189,61 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g
186189
return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, err)
187190
}
188191

189-
repoTags, err := repo.Tags.List()
190-
if err != nil {
191-
return nil, "", fmt.Errorf("git list tags error: %w", err)
192-
}
192+
tags := make(map[string]string)
193+
tagTimestamps := make(map[string]time.Time)
194+
if err := repo.Tags.Foreach(func(name string, id *git2go.Oid) error {
195+
tag, err := repo.LookupTag(id)
196+
if err != nil {
197+
return nil
198+
}
193199

194-
svTags := make(map[string]string)
195-
var svers []semver.Version
196-
for _, tag := range repoTags {
197-
v, _ := semver.ParseTolerant(tag)
198-
if rng(v) {
199-
svers = append(svers, v)
200-
svTags[v.String()] = tag
200+
commit, err := tag.Peel(git2go.ObjectCommit)
201+
if err != nil {
202+
return fmt.Errorf("can't get commit for tag %s: %w", name, err)
201203
}
204+
c, err := commit.AsCommit()
205+
if err != nil {
206+
return err
207+
}
208+
tagTimestamps[tag.Name()] = c.Committer().When
209+
tags[tag.Name()] = name
210+
return nil
211+
}); err != nil {
212+
return nil, "", err
202213
}
203214

204-
if len(svers) == 0 {
215+
var matchedVersions semver.Collection
216+
for tag, _ := range tags {
217+
v, err := version.ParseVersion(tag)
218+
if err != nil {
219+
continue
220+
}
221+
if !verConstraint.Check(v) {
222+
continue
223+
}
224+
matchedVersions = append(matchedVersions, v)
225+
}
226+
if len(matchedVersions) == 0 {
205227
return nil, "", fmt.Errorf("no match found for semver: %s", c.semVer)
206228
}
207229

208-
semver.Sort(svers)
209-
v := svers[len(svers)-1]
210-
t := svTags[v.String()]
230+
// Sort versions
231+
sort.SliceStable(matchedVersions, func(i, j int) bool {
232+
left := matchedVersions[i]
233+
right := matchedVersions[j]
234+
235+
if !left.Equal(right) {
236+
return left.LessThan(right)
237+
}
238+
239+
// Having tag target timestamps at our disposal, we further try to sort
240+
// versions into a chronological order. This is especially important for
241+
// versions that differ only by build metadata, because it is not considered
242+
// a part of the comparable version in Semver
243+
return tagTimestamps[left.String()].Before(tagTimestamps[right.String()])
244+
})
245+
v := matchedVersions[len(matchedVersions)-1]
246+
t := v.Original()
211247

212248
ref, err := repo.References.Dwim(t)
213249
if err != nil {

0 commit comments

Comments
 (0)