33package rhctag
44
55import (
6+ "errors"
67 "fmt"
78 "math"
89 "strconv"
910 "strings"
1011
11- rpmVersion "github.com/knqyf263/go-rpm-version"
12-
1312 "github.com/quay/claircore"
13+ "github.com/quay/claircore/internal/rpmver"
1414)
1515
16- // Allows extracting the Major and Minor versions so that we don't compare container tags from different minor versions.
16+ // Version allows extracting the "major" and "minor" versions so that we don't compare container tags from different minor versions.
17+ //
1718// This is a workaround for another problem where not all minor releases of containers have a unique CPE.
18- // Take for example ocs4/rook-ceph-rhel8-operator, it shipped at least 2 minor releases into the same container repository.
19- // Both those major versions use the same CPE "cpe:/a:redhat:openshift_container_storage:4"
20- // Here are 2 example tags which fixed CVE-2020-8565
21- // 4.7 minor: 4.7-140.49a6fcf.release_4.7
22- // 4.8 minor: 4.8-167.9a9db5f.release_4.8
23-
24- // This class also handles container tags which have a 'v' prefix, for example openshift4/ose-metering-hive
25- // 4.6 minor: v4.6.0-202112140546.p0.g8b9da97.assembly.stream
26- // 4.7 minor: v4.7.0-202112140553.p0.g091bb99.assembly.stream
19+ //
20+ // For example, take "ocs4/rook-ceph-rhel8-operator": it shipped at least 2 minor releases into the same container repository.
21+ // Both those major versions use the same CPE: "cpe:/a:redhat:openshift_container_storage:4".
22+ // Here are 2 example tags which fixed CVE-2020-8565:
23+ // - 4.7-140.49a6fcf.release_4.7
24+ // - 4.8-167.9a9db5f.release_4.8
25+ //
26+ // This type also handles container tags which have a 'v' prefix (e.g. "openshift4/ose-metering-hive").
27+ // - v4.6.0-202112140546.p0.g8b9da97.assembly.stream
28+ // - v4.7.0-202112140553.p0.g091bb99.assembly.stream
2729type Version struct {
2830 Original string
2931 Major int
3032 Minor int
3133}
3234
35+ // Version turns the reciever into a [claircore.Version].
36+ //
37+ // "Min" controls whether the returned version is the minimum within the minor
38+ // series or the maximum.
3339func (v * Version ) Version (min bool ) (c claircore.Version ) {
3440 const (
3541 major = 0
@@ -64,7 +70,7 @@ func upToDot(s string) (value int, remainder string, err error) {
6470 if err == nil {
6571 return value , remainder , nil
6672 }
67- return value , remainder , fmt .Errorf ("Could not parse %s as an int" , s )
73+ return value , remainder , fmt .Errorf ("could not parse %q as int" , s )
6874}
6975
7076// Parse attempts to extract a Red Hat container registry tag version string
@@ -75,7 +81,7 @@ func Parse(s string) (v Version, err error) {
7581 // remove the leading "v" prefix
7682 canonical = s [1 :]
7783 }
78- //strip revision
84+ // strip revision
7985 dashIndex := strings .Index (canonical , "-" )
8086 if dashIndex > 0 {
8187 canonical = canonical [:dashIndex ]
@@ -105,13 +111,26 @@ func (v *Version) MinorStart() (start Version) {
105111 return start
106112}
107113
114+ // Compare is a comparison for the provided [Version]s.
108115func (v * Version ) Compare (x * Version ) int {
109- thisRpmVersion := rpmVersion .NewVersion (v .Original )
110- otherRpmVersion := rpmVersion .NewVersion (x .Original )
111- return thisRpmVersion .Compare (otherRpmVersion )
116+ a , aErr := rpmver .Parse (v .toEVR ())
117+ b , bErr := rpmver .Parse (x .toEVR ())
118+ if err := errors .Join (aErr , bErr ); err != nil {
119+ panic (fmt .Errorf ("unable to compare versions: %w" , err ))
120+ }
121+ return rpmver .Compare (& a , & b )
122+ }
123+
124+ func (v * Version ) toEVR () string {
125+ s := v .Original
126+ s = strings .TrimPrefix (s , "v" )
127+ if ! strings .Contains (s , "-" ) {
128+ s = s + "-0"
129+ }
130+ return s
112131}
113132
114- // Versions implements sort.Interface.
133+ // Versions implements [ sort.Interface] .
115134type Versions []Version
116135
117136func (vs Versions ) Len () int {
0 commit comments