diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 965bb97..5a491c4 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -36,7 +36,7 @@ jobs: ${{ runner.os }}-go- - name: Lint - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.0 && golangci-lint run ./... --deadline=15m + run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.8.0 && golangci-lint run --timeout=15m ./... - name: Unit run: CGO_ENABLED=1 go test -coverprofile=cov.out -race -test.v ./... | tee out.txt diff --git a/.golangci.yaml b/.golangci.yaml index ccc306f..22c9ef1 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,165 +1,178 @@ +version: "2" +run: + build-tags: + - integration linters: - disable-all: true + default: none # One can't use disable and disable-all. disable-all is preferred to avoid lint failing when golangci gets updated and linters are added. # at the same time but it is nice to explicitly state which linters we do not want. #disable: - #- containedctx # Context.Context within a struct a struct (as opposed to a func parameter) is nasty for many reasons, but actually sometimes useful. - #- contextcheck # Not that useful/false positives. - #- cyclop # Cyclo complexity already calculated by other linters. - #- depguard # We do not restrict imports. - #- dogsled # Could be nice in the future. - #- dupl # Could be nice in the future. - #- exhaustive # Not that useful/false positives. - #- exhaustruct # Not that useful/false positives. - #- forcetypeassert # We want a panic in situations when a type is asserted. - #- funlen # We really like long functions. - #- gci # Conflicts with other linters. - #- gochecknoglobals # We need globals. - #- gochecknoinits # We have a lot of those. - #- gocognit # Not that useful/false positives. - #- godox # Not that useful/false positives. - #- gomnd # The annoy is strong. - #- gomoddirectives # Not that useful/false positives. - #- interfacebloat # WE do bloaty interfaces. - #- inamedparam # Not that useful. - #- ireturn # Not that useful/false positives. - #- lll # Could be nice in the future. - #- musttag # Dislikes our deps. - #- nakedret # Naked return good return. - #- nlreturn # Could be nice in the future. - #- nonamedreturns # Named return good return. - #- rowserrcheck # No SQL here. - #- sqlclosecheck # No SQL here. - #- tagliatelle # Reports issues that are not right for us. - #- testpackage # Could be nice in the future. - #- unparam # Not that useful/false positives. - #- varnamelen # Not that useful/false positives. - #- wrapcheck # Not that useful/false positives. - #- wsl # Not that useful/false positives. - #- zerologlint # No zerolog here. - #- goerr113 + # - containedctx # Context.Context within a struct (as opposed to a func parameter) is nasty for many reasons, but actually sometimes useful. + # - contextcheck # Not that useful/false positives. + # - cyclop # Cyclo complexity already calculated by other linters. + # - dogsled # Could be nice in the future. + # - dupl # Could be nice in the future. + # - err113 # Could be nice in the future. + # - exhaustive # Not that useful/false positives. + # - exhaustruct # Not that useful/false positives. + # - forcetypeassert # We want a panic in situations when a type is asserted. + # - funcorder # Not that useful. + # - funlen # We really like long functions. + # - gochecknoglobals # We need globals. + # - gochecknoinits # We have a lot of those. + # - gocognit # Not that useful/false positives. + # - godox # Not that useful/false positives. + # - gomoddirectives # Not that useful/false positives. + # - inamedparam # Not that useful. + # - interfacebloat # We do bloaty interfaces. + # - ireturn # Not that useful/false positives. + # - mnd # The annoy is strong. + # - nakedret # Naked return good return. + # - nlreturn # Could be nice in the future. + # - nonamedreturns # Named return good return. + # - recvcheck # Could be nice in the future. + # - tagliatelle # Reports issues that are not right for us. + # - testpackage # Whitebox testing is fine too. + # - usetesting # Would be nice to have. + # - varnamelen # Not that useful/false positives. + # - wrapcheck # Not that useful/false positives. + # - wsl # Not that useful/false positives. enable: - - asasalint - - asciicheck - - bidichk - - bodyclose - - decorder - - dupword - - durationcheck - - errcheck - - errchkjson - - errname - - errorlint - - execinquery - - exportloopref - - forbidigo - - ginkgolinter - - gocheckcompilerdirectives - - gochecksumtype - - goconst - - gocritic - - gocyclo - - godot - - gofmt - - gofumpt - - goheader - - goimports - - gosmopolitan - - govet - - grouper - - importas - - ineffassign - - loggercheck - - maintidx - - makezero - - mirror - - misspell - - musttag - - nestif - - nilerr - - nilnil - - noctx - - nolintlint - - nosprintfhostport - - paralleltest - - perfsprint - - prealloc - - predeclared - - promlinter - - protogetter - - reassign - - revive - - rowserrcheck - - sloglint - - staticcheck - - stylecheck - - tagalign - - tenv - - testableexamples - - testifylint - - thelper - - tparallel - - typecheck - - unconvert - - unused - - usestdlibvars - - wastedassign - - whitespace + - asasalint + - asciicheck + - bidichk + - bodyclose + - canonicalheader + - copyloopvar + - decorder + - depguard + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - exptostd + - fatcontext + - forbidigo + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - goconst + - gocritic + - gocyclo + - godot + - goheader + - gomodguard + - goprintffuncname + - gosec + - gosmopolitan + - govet + - grouper + - iface + - importas + - ineffassign + - intrange + - lll + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - musttag + - nestif + - nilerr + - nilnesserr + - nilnil + - noctx + - nolintlint + - nosprintfhostport + - paralleltest + - perfsprint + - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - revive + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck + - staticcheck + - tagalign + - testableexamples + - testifylint + - thelper + - tparallel + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign + - whitespace + - zerologlint + settings: + depguard: + rules: + xcontext: + deny: + - pkg: golang.org/x/net/context + desc: use context package + gosec: + excludes: + - G115 + - G204 + - G301 + - G302 + - G304 + - G306 + - G601 + - G602 + exclusions: + generated: lax + rules: + - linters: + - lll + source: ^//( ?)[+]kubebuilder + - linters: + - lll + source: "^\t*//( ?)http(s?)://" + - linters: + - paralleltest + path: integration\/.+\.go + - path: internal/ + text: ((comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)|exported (.+) should have comment( \(or a comment on this block\))? or be unexported|package comment should be of the form "(.+)...|comment on exported (.+) should be of the form "(.+)..."|should have a package comment) + - path: cmd/ + text: ((comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)|exported (.+) should have comment( \(or a comment on this block\))? or be unexported|package comment should be of the form "(.+)...|comment on exported (.+) should be of the form "(.+)..."|should have a package comment) + - path: integration/ + text: ((comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)|exported (.+) should have comment( \(or a comment on this block\))? or be unexported|package comment should be of the form "(.+)...|comment on exported (.+) should be of the form "(.+)..."|should have a package comment) + paths: + - internal/packages/internal/packagekickstart/rukpak + - third_party$ + - builtin$ + - examples$ issues: - max-same-issues: 0 max-issues-per-linter: 0 - exclude-rules: - # Integration tests MUST NOT run in parallel. - - path: 'integration\/.+\.go' - linters: - - paralleltest -run: - skip-files: [ "zz_generated.deepcopy.go$" ] -linters-settings: - goimports: - local-prefixes: package-operator.run - gosec: - excludes: - - G301 # Poor file permissions used when creating a directory. - - G302 # Poor file permissions used with chmod. - - G306 # Poor file permissions used when writing to a new file. - - G601 # Taking address of loop variable - not relevant anymore. - - G602 # Should reports out of bound access but is broken. - importas: - no-unaliased: false - no-extra-aliases: true - alias: - - pkg: k8s\.io\/api\/([^\/]+)\/([^\/]+) - alias: $1$2 - - pkg: k8s\.io\/apimachinery\/pkg\/([^\/]+) - alias: $1 - - pkg: k8s\.io\/apimachinery\/pkg\/apis\/([^\/]+)\/([^\/]+) - alias: $1$2 - - pkg: package-operator\.run\/apis - alias: apis - - pkg: package-operator\.run\/apis\/([^\/]+)\/([^\/]+) - alias: $1$2 - - pkg: k8s\.io\/apiextensions-apiserver\/pkg\/apis\/([^\/]+)\/([^\/]+) - alias: $1$2 - - pkg: github\.com\/openshift\/api\/([^\/]+)\/([^\/]+) - alias: $1$2 - - pkg: package-operator.run/internal/controllers/hostedclusters/([^\/]+)\/([^\/]+) - alias: $1$2 - - pkg: k8s\.io\/apimachinery\/pkg\/api\/([^\/]+) - alias: apimachinery$1 - - pkg: sigs\.k8s\.io\/controller-runtime - alias: ctrl - - pkg: package-operator\.run\/internal\/cmd - alias: internalcmd - - pkg: package-operator\.run\/internal\/probing - alias: internalprobing - - pkg: package-operator\.run\/internal\/controllers\/packages - alias: controllerspackages - - pkg: github\.com\/google\/go-containerregistry\/pkg\/v1 - alias: containerregistrypkgv1 - - pkg: k8s\.io\/utils\/clock\/testing - alias: clocktesting - - pkg: k8s\.io\/apiserver\/pkg\/cel - alias: apiservercel - - pkg: k8s\.io\/apiserver\/pkg\/apis\/cel - alias: apiserverapiscel + max-same-issues: 0 +formatters: + enable: + - gofmt + - gofumpt + - goimports + settings: + goimports: + local-prefixes: + - package-operator.run + gofmt: + simplify: true + rewrite-rules: + - pattern: interface{} + replacement: any + exclusions: + generated: lax + paths: + - internal/packages/internal/packagekickstart/rukpak + - third_party$ + - builtin$ + - examples$ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9247557..00e046d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: hooks: - id: lint name: lint - entry: golangci-lint run ./... --deadline=15m + entry: golangci-lint run --timeout=3m --fix ./... language: system exclude: ".*" always_run: true diff --git a/README.md b/README.md index 17bf95e..9a58d5c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Semver -The `semver` package implements logic to work with [Sementic Versioning 2.0.0](http://semver.org/) in Go. +The `semver` package implements logic to work with [Sementic Versioning 2.0.0](http://semver.org/) in Go. It provides: - Parser for semantic versions - Validation of semantic versions @@ -10,15 +10,15 @@ It provides: - whether version contained in range - whether a range is contained in another range -This library is loosely based on the awesome: +This library is loosely based on the awesome: https://github.com/Masterminds/semver ## Parsing Semantic Versions This library implements strict parsing of semantic versions as outlined in the [Sementic Versioning](http://semver.org/) spec. Shorthand forms or a `v` prefix e.g. 2.0, 1, v2.1.2 are not considered valid semantic versions following the 2.0.0 spec. -> **Parsing Huge Versions** -> Semver does not limit the amount of Major, Minor or Patch version numbers. +> **Parsing Huge Versions** +> Semver does not limit the amount of Major, Minor or Patch version numbers. Making `99999999999999999999999.999999999999999999.99999999999999999` a valid semver. > For simplicity this library uses `uint64` as underlying datatype for Major, Minor and Patch, limiting the maximum number to `9999999999999999999`. @@ -39,7 +39,7 @@ e.g. `1 - 2` => `1.0.0 - 2.0.0` Pre release versions that fall within a range will match. If pre release versions should be excluded, they have to be filtered before checking against constraints. -Specifying pre-release ranges is NOT supported. +Specifying pre-release ranges is NOT supported. e.g. `1.0.0-rc.0 - 1.0.0.rc.10` In the following examples `` is used to denote the max number possible to put into the Major, Minor or Patch section of a semantic version. @@ -93,4 +93,4 @@ The caret (^) comparison operator is for major level changes once a stable (`1.0 **unstable versions** - `^0.2.3` is expanded to `0.2.3 - 0.2.` - `^0.2` is expanded to `0.2.0 - 0.2.` -- `^0` is expanded to `0.0.0 - 0.0.` \ No newline at end of file +- `^0` is expanded to `0.0.0 - 0.0.` diff --git a/constraintparser.go b/constraintparser.go index 381b212..476e9d3 100644 --- a/constraintparser.go +++ b/constraintparser.go @@ -1,3 +1,12 @@ +// Package semver implements logic to work with Sementic Versioning 2.0.0 in Go. +// It provides: +// - Parser for semantic versions +// - Validation of semantic versions +// - Sorting of semantic versions +// - Parser for semantic version range constraints +// - Range constraint matching +// - whether version contained in range +// - whether a range is contained in another range package semver import ( @@ -9,7 +18,7 @@ import ( const maxUint64 = ^uint64(0) -// Parses the given string into a Version Constraint or panics. +// MustNewConstraint parses the given string into a Version Constraint or panics. func MustNewConstraint(data string) Constraint { c, err := NewConstraint(data) if err != nil { @@ -18,7 +27,7 @@ func MustNewConstraint(data string) Constraint { return c } -// Parses the given string into a Version Constraint. +// NewConstraint parses the given string into a Version Constraint. func NewConstraint(data string) (Constraint, error) { c, err := parseConstraint([]byte(data)) if err != nil { @@ -250,7 +259,7 @@ parse: for { pos, tok, lit := p.scanner.Scan() if len(p.errors) > 0 { - return nil, fmt.Errorf(p.errors[0]) + return nil, fmt.Errorf("%s", p.errors[0]) } switch tok { @@ -352,44 +361,53 @@ func compactAndValidateLogicalAND(pos internal.Position, and and) (and, error) { // find min version and max version var ( - max *Version - min *Version + maxVersion *Version + minVersion *Version ) for _, c := range and { r, ok := c.(*Range) switch { case ok && isMinUnconstraint(*r): - if max != nil { - return nil, fmt.Errorf("%s: <=%s overlaps with <=%s in logical AND", pos, r.Max.String(), max) + if maxVersion != nil { + return nil, fmt.Errorf( + "%s: <=%s overlaps with <=%s in logical AND", + pos, r.Max.String(), maxVersion, + ) } - max = &r.Max + maxVersion = &r.Max case ok && isMaxUnconstraint(*r): - if min != nil { - return nil, fmt.Errorf("%s: >=%s overlaps with >=%s in logical AND", pos, r.Min.String(), min) + if minVersion != nil { + return nil, fmt.Errorf( + "%s: >=%s overlaps with >=%s in logical AND", + pos, r.Min.String(), minVersion, + ) } - min = &r.Min + minVersion = &r.Min case ok: - if min != nil && max != nil { - existingRange := Range{Min: *min, Max: *max} + if minVersion != nil && maxVersion != nil { + existingRange := Range{Min: *minVersion, Max: *maxVersion} if !existingRange.Contains(r) { - return nil, fmt.Errorf("%s: non overlapping ranges %q and %q in logical AND", pos, r.String(), existingRange.String()) + return nil, fmt.Errorf( + "%s: non overlapping ranges %q and %q in logical AND", + pos, r.String(), existingRange.String(), + ) } fullyDefinedConstraints = append(fullyDefinedConstraints, c) } else { - min = &r.Min - max = &r.Max + minVersion = &r.Min + maxVersion = &r.Max } default: fullyDefinedConstraints = append(fullyDefinedConstraints, c) } } - if min != nil && max != nil { + if minVersion != nil && maxVersion != nil { fullyDefinedConstraints = append(fullyDefinedConstraints, &Range{ - Min: *min, - Max: *max, + Min: *minVersion, + Max: *maxVersion, }) } return fullyDefinedConstraints, nil diff --git a/constraintparser_test.go b/constraintparser_test.go index f4671ac..e0bb24a 100644 --- a/constraintparser_test.go +++ b/constraintparser_test.go @@ -399,7 +399,6 @@ func TestConstraintParser_success(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() c, err := NewConstraint(test.input) @@ -492,7 +491,6 @@ func TestConstraintParser_error(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.input, func(t *testing.T) { t.Parallel() _, err := NewConstraint(test.input) @@ -517,7 +515,6 @@ func TestConstraintParser_invalidBytes(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(string(test.version), func(t *testing.T) { t.Parallel() _, err := parseConstraint(test.version) diff --git a/go.mod b/go.mod index 9be1910..45fdb0f 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module pkg.package-operator.run/semver -go 1.21.1 +go 1.25.3 -require github.com/stretchr/testify v1.8.4 +require github.com/stretchr/testify v1.11.1 require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index fa4b6e6..f7a8426 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/ranges/scanner_test.go b/internal/ranges/scanner_test.go index 32d96e7..ddc59aa 100644 --- a/internal/ranges/scanner_test.go +++ b/internal/ranges/scanner_test.go @@ -155,7 +155,6 @@ func TestScanner(t *testing.T) { } for _, test := range tests { - test := test t.Run(test.Input, func(t *testing.T) { t.Parallel() // Init diff --git a/range.go b/range.go index 49b3206..e70d2bb 100644 --- a/range.go +++ b/range.go @@ -30,7 +30,7 @@ func (r *Range) Check(v Version) bool { return true } -// Checks if the given constraint fits into this range. +// Contains checks if the given constraint fits into this range. func (r *Range) Contains(other Constraint) bool { return rangeContains(*r, other) } diff --git a/range_test.go b/range_test.go index 58c9188..d11c8da 100644 --- a/range_test.go +++ b/range_test.go @@ -40,7 +40,6 @@ func TestRange_Test(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() r := test.r.Check(test.v) @@ -185,7 +184,6 @@ func TestRange_Contains(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() r := test.rA.Contains(test.rB) diff --git a/sort.go b/sort.go index 2d198f7..965ed96 100644 --- a/sort.go +++ b/sort.go @@ -2,7 +2,7 @@ package semver import "sort" -// Sorts versions Ascending via the sorts standard lib package. +// Ascending sorts versions Ascending via the sorts standard lib package. // resulting order: 1.0.0, 1.1.0, 2.0.0. type Ascending []Version @@ -26,7 +26,7 @@ func (l Ascending) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -// Sorts versions Descending via the sorts standard lib package. +// Descending sorts versions Descending via the sorts standard lib package. // resulting order: 2.0.0, 1.1.0, 1.0.0. type Descending []Version diff --git a/sort_test.go b/sort_test.go index 4df362d..13390cf 100644 --- a/sort_test.go +++ b/sort_test.go @@ -85,10 +85,9 @@ func TestAscendingDescendingSort(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() - var list []Version + list := make([]Version, 0, len(test.input)) for _, vs := range test.input { v, err := NewVersion(vs) require.NoError(t, err) diff --git a/version.go b/version.go index af42d4b..6b38060 100644 --- a/version.go +++ b/version.go @@ -10,7 +10,7 @@ import ( // VersionList keeps a list of versions and provides helper functions on them. type VersionList []Version -// Converts all Versions into strings and returns them. +// StringList converts all Versions into strings and returns them. func (l VersionList) StringList() []string { vs := make([]string, len(l)) for i := range l { @@ -24,14 +24,14 @@ func (l VersionList) String() string { return strings.Join(l.StringList(), ", ") } -// Represents a Semantic Versioning 2.0.0 Version. +// Version represents a Semantic Versioning 2.0.0 Version. type Version struct { Major, Minor, Patch uint64 PreRelease PreReleaseIdentifierList BuildMetadata []string } -// Returns true if both Versions are the same. +// Same returns true if both Versions are the same. func (v *Version) Same(o Version) bool { return v.Major == o.Major && v.Minor == o.Minor && @@ -40,7 +40,7 @@ func (v *Version) Same(o Version) bool { slices.Equal(v.BuildMetadata, o.BuildMetadata) } -// Returns a string representation of the Version. +// String returns a string representation of the Version. func (v *Version) String() string { s := fmt.Sprintf("%s.%s.%s", printXonMaxInt(v.Major), @@ -92,8 +92,13 @@ func (v *Version) Compare(o Version) int { return o.PreRelease.Compare(v.PreRelease) } +// PreReleaseIdentifierList is a list of PreReleaseIdentifiers. +// A pre-release version MAY be denoted by appending a hyphen and +// a series of dot separated identifiers immediately following the patch version. +// Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--. type PreReleaseIdentifierList []PreReleaseIdentifier +// String returns the pre-release identifier list as a single string joined by '.'. func (l PreReleaseIdentifierList) String() string { pre := make([]string, len(l)) for i := range l { @@ -122,7 +127,7 @@ func (l PreReleaseIdentifierList) Compare(o []PreReleaseIdentifier) int { prel = otherLen } - for i := 0; i < prel; i++ { + for i := range prel { var ( pre PreReleaseIdentifier other PreReleaseIdentifier @@ -179,21 +184,25 @@ func (s *PreReleaseIdentifier) Compare(o PreReleaseIdentifier) int { return 1 } -func (s *PreReleaseIdentifier) Interface() interface{} { +// Interface returns either a string or uint64 depending on the underlying type. +func (s *PreReleaseIdentifier) Interface() any { if len(s.str) > 0 { return s.str } return s.num } +// GetString returns a string and whether the underlying type is a string. func (s *PreReleaseIdentifier) GetString() (string, bool) { return s.str, len(s.str) > 0 } +// GetNumber returns a uint64 and whether the underlying type is a uint64. func (s *PreReleaseIdentifier) GetNumber() (uint64, bool) { return s.num, len(s.str) == 0 } +// String always returns a string representation. func (s *PreReleaseIdentifier) String() string { if len(s.str) > 0 { return s.str @@ -201,7 +210,7 @@ func (s *PreReleaseIdentifier) String() string { return strconv.FormatUint(s.num, 10) } -// Converts the given string into a PreReleaseIdentifier. +// ToPreReleaseIdentifier converts the given string into a PreReleaseIdentifier. func ToPreReleaseIdentifier(s string) PreReleaseIdentifier { num, err := strconv.ParseUint(s, 10, 0) if err != nil { diff --git a/version_test.go b/version_test.go index 6a82db2..262de75 100644 --- a/version_test.go +++ b/version_test.go @@ -17,7 +17,6 @@ func TestVersion_String(t *testing.T) { "1.2.3----RC-SNAPSHOT.12.9.1--.12+788", } for _, test := range tests { - test := test t.Run(test, func(t *testing.T) { t.Parallel() v, err := NewVersion(test) @@ -73,7 +72,6 @@ func TestPreReleaseIdentifier_Compare(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() d := test.pre.Compare(test.other) @@ -144,7 +142,6 @@ func TestPreReleaseIdentifierList_Compare(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { t.Parallel() pre := PreReleaseIdentifierList(test.pre) diff --git a/versionparser.go b/versionparser.go index 96b274f..9ee228e 100644 --- a/versionparser.go +++ b/versionparser.go @@ -1,6 +1,7 @@ package semver import ( + "errors" "fmt" "strconv" "unicode/utf8" @@ -8,7 +9,7 @@ import ( "pkg.package-operator.run/semver/internal" ) -// Parses the given string into a Version object and panics on error. +// MustNewVersion parses the given string into a Version object and panics on error. func MustNewVersion(src string) Version { v, err := NewVersion(src) if err != nil { @@ -17,7 +18,7 @@ func MustNewVersion(src string) Version { return v } -// Parses the given string into a Version object. +// NewVersion parses the given string into a Version object. func NewVersion(src string) (Version, error) { return parseVersion([]byte(src)) } @@ -221,7 +222,7 @@ func (p *parser) scanBuildMeta() ([]string, error) { func (p *parser) scanPreRelease() ([]PreReleaseIdentifier, error) { if p.logicalPosition != 3 { - return nil, fmt.Errorf("pre release not after patch") + return nil, errors.New("pre release not after patch") } var prParts []PreReleaseIdentifier diff --git a/versionparser_test.go b/versionparser_test.go index 962ddbe..e2c6bc1 100644 --- a/versionparser_test.go +++ b/versionparser_test.go @@ -145,7 +145,6 @@ func TestParser_success(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.version, func(t *testing.T) { t.Parallel() v, err := NewVersion(test.version) @@ -247,7 +246,6 @@ func TestParser_error(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.version, func(t *testing.T) { t.Parallel() _, err := NewVersion(test.version)