Skip to content

Commit 17f2fa5

Browse files
committed
ensure that new types minimize internal access and maximize safeness
Signed-off-by: grokspawn <jordan@nimblewidget.com>
1 parent 6ea0f39 commit 17f2fa5

1 file changed

Lines changed: 49 additions & 21 deletions

File tree

alpha/declcfg/declcfg.go

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"strings"
89

910
"github.com/blang/semver/v4"
1011
"golang.org/x/text/cases"
@@ -208,24 +209,55 @@ func (destination *DeclarativeConfig) Merge(src *DeclarativeConfig) {
208209
destination.Deprecations = append(destination.Deprecations, src.Deprecations...)
209210
}
210211

211-
type CompositeVersion struct {
212-
Version semver.Version
213-
Release semver.Version
214-
}
212+
type Release []semver.PRVersion
215213

216-
func (cv *CompositeVersion) Compare(other *CompositeVersion) int {
217-
if cv.Version.NE(other.Version) {
218-
return cv.Version.Compare(other.Version)
214+
func (r Release) Compare(other Release) int {
215+
if len(r) == 0 && len(other) > 0 {
216+
return -1
219217
}
220-
hasrelease := len(cv.Release.Pre) > 0
221-
otherhasrelease := len(other.Release.Pre) > 0
222-
if hasrelease && !otherhasrelease {
218+
if len(other) == 0 && len(r) > 0 {
223219
return 1
224220
}
225-
if !hasrelease && otherhasrelease {
226-
return -1
221+
a := semver.Version{Pre: r}
222+
b := semver.Version{Pre: other}
223+
return a.Compare(b)
224+
}
225+
226+
func NewRelease(relStr string) (Release, error) {
227+
// empty input is not an error, but results in an empty release slice
228+
if relStr == "" {
229+
return nil, nil
227230
}
228-
return cv.Release.Compare(other.Release)
231+
232+
var (
233+
segments = strings.Split(relStr, ".")
234+
r = make(Release, 0, len(segments))
235+
errs []error
236+
)
237+
for i, segment := range segments {
238+
prVer, err := semver.NewPRVersion(segment)
239+
if err != nil {
240+
errs = append(errs, fmt.Errorf("segment %d: %v", i, err))
241+
continue
242+
}
243+
r = append(r, prVer)
244+
}
245+
if err := errors.Join(errs...); err != nil {
246+
return nil, fmt.Errorf("invalid release %q: %v", relStr, err)
247+
}
248+
return r, nil
249+
}
250+
251+
type CompositeVersion struct {
252+
version semver.Version
253+
release Release
254+
}
255+
256+
func (cv *CompositeVersion) Compare(other *CompositeVersion) int {
257+
if cmp := cv.version.Compare(other.version); cmp != 0 {
258+
return cmp
259+
}
260+
return cv.release.Compare(other.release)
229261
}
230262

231263
// order by version, then
@@ -258,20 +290,16 @@ func (b *Bundle) CompositeVersion() (*CompositeVersion, error) {
258290
return nil, fmt.Errorf("bundle %q has invalid version %q: %v", b.Name, props.Packages[0].Version, err)
259291
}
260292

261-
var r semver.Version
293+
var r Release
262294
if props.Packages[0].Release != "" {
263-
r, err = semver.Parse(fmt.Sprintf("0.0.0-%s", props.Packages[0].Release))
295+
r, err = NewRelease(props.Packages[0].Release)
264296
if err != nil {
265297
return nil, fmt.Errorf("error parsing bundle %q release version %q: %v", b.Name, props.Packages[0].Release, err)
266298
}
267-
// only need to check for build metadata since we are using explicit zero major, minor, and patch versions above
268-
if len(r.Build) != 0 {
269-
return nil, fmt.Errorf("bundle %q release version %q cannot contain build metadata", b.Name, props.Packages[0].Release)
270-
}
271299
}
272300

273301
return &CompositeVersion{
274-
Version: v,
275-
Release: r,
302+
version: v,
303+
release: r,
276304
}, nil
277305
}

0 commit comments

Comments
 (0)