buildr/internal/semver/parsing.go
Peter 1261932bdc
All checks were successful
continuous-integration/drone/push Build is passing
refactor: apply golangci-lint findings
2023-06-22 19:16:00 +02:00

59 lines
1.5 KiB
Go

package semver
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
//nolint:lll // regex is as it is
var (
ErrNotASemver = errors.New("the given version does not match the semantic versioning scheme")
semVerRegex = regexp.MustCompile(`^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
)
func IsValid(version string) bool {
return semVerRegex.MatchString(strings.TrimPrefix(version, "v"))
}
func ParseVersion(version string) (v Version, err error) {
if !IsValid(version) {
return Version{}, fmt.Errorf("%w: %s", ErrNotASemver, version)
}
submatches := semVerRegex.FindStringSubmatch(strings.TrimPrefix(version, "v"))
for i, name := range semVerRegex.SubexpNames() {
switch name {
case "major":
if v.Major, err = strconv.Atoi(submatches[i]); err != nil {
return Version{}, err
}
case "minor":
if v.Minor, err = strconv.Atoi(submatches[i]); err != nil {
return Version{}, err
}
case "patch":
if v.Patch, err = strconv.Atoi(submatches[i]); err != nil {
return Version{}, err
}
case "prerelease":
v.Prerelease = submatches[i]
case "buildmetadata":
v.BuildMetadata = submatches[i]
}
}
return v, nil
}
type Version struct {
Prerelease string `cty:"prerelease"`
BuildMetadata string `cty:"build_metadata"`
Major int `cty:"major"`
Minor int `cty:"minor"`
Patch int `cty:"patch"`
}