fs storage
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SemVer stores a numeric semantic version as major, minor, patch, and build
|
||||
// components. Components that are not provided are represented as zero values.
|
||||
type SemVer struct {
|
||||
Major uint
|
||||
Minor uint
|
||||
Patch uint
|
||||
Build uint
|
||||
}
|
||||
|
||||
// NewSemver constructs a SemVer from v.
|
||||
//
|
||||
// NewSemver requires between one and four components ordered as major, minor,
|
||||
// patch, and build. Components that are not provided are set to zero.
|
||||
func NewSemver(v ...uint) (SemVer, error) {
|
||||
s := &SemVer{}
|
||||
switch len(v) {
|
||||
case 4:
|
||||
s.Build = v[3]
|
||||
fallthrough
|
||||
case 3:
|
||||
s.Patch = v[2]
|
||||
fallthrough
|
||||
case 2:
|
||||
s.Minor = v[1]
|
||||
fallthrough
|
||||
case 1:
|
||||
s.Major = v[0]
|
||||
default:
|
||||
return *s, fmt.Errorf("new semver: incorrect args count: %d", len(v))
|
||||
}
|
||||
return *s, nil
|
||||
}
|
||||
|
||||
// MustSemver returns the SemVer produced by NewSemver(v...).
|
||||
//
|
||||
// MustSemver panics if NewSemver returns an error.
|
||||
func MustSemver(v ...uint) SemVer {
|
||||
if v, err := NewSemver(v...); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// ParseSemver parses input into a SemVer.
|
||||
//
|
||||
// ParseSemver accepts versions with one to four numeric components separated by
|
||||
// dots, for example "1", "1.2", "1.2.3", or "1.2.3.4". The input may also use
|
||||
// the optional "v" or "v." prefix. Missing minor, patch, and build components
|
||||
// are set to zero.
|
||||
func ParseSemver(input string) (SemVer, error) {
|
||||
source := input
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(input, "v."):
|
||||
input = strings.TrimPrefix(input, "v.")
|
||||
case strings.HasPrefix(input, "v"):
|
||||
input = strings.TrimPrefix(input, "v")
|
||||
}
|
||||
|
||||
if input == "" {
|
||||
return SemVer{}, fmt.Errorf("parse semver %q: missing major version", source)
|
||||
}
|
||||
|
||||
parts := strings.Split(input, ".")
|
||||
if len(parts) > 4 {
|
||||
return SemVer{}, fmt.Errorf("parse semver %q: too many version parts: %d", source, len(parts))
|
||||
}
|
||||
|
||||
values := make([]uint, 0, len(parts))
|
||||
for idx, part := range parts {
|
||||
if part == "" {
|
||||
return SemVer{}, fmt.Errorf("parse semver %q: empty version part at position %d", source, idx+1)
|
||||
}
|
||||
|
||||
value, err := strconv.ParseUint(part, 10, 0)
|
||||
if err != nil {
|
||||
return SemVer{}, fmt.Errorf("parse semver %q: parse part %q at position %d: %w", source, part, idx+1, err)
|
||||
}
|
||||
|
||||
values = append(values, uint(value))
|
||||
}
|
||||
|
||||
version, err := NewSemver(values...)
|
||||
if err != nil {
|
||||
return SemVer{}, fmt.Errorf("parse semver %q: %w", source, err)
|
||||
}
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// ParserSemver calls ParseSemver.
|
||||
//
|
||||
// Deprecated: use ParseSemver.
|
||||
func ParserSemver(input string) (SemVer, error) {
|
||||
return ParseSemver(input)
|
||||
}
|
||||
|
||||
// CompareSemver compares two semantic versions and returns:
|
||||
//
|
||||
// +1 if x is less than y,
|
||||
// 0 if x equals y,
|
||||
// -1 if x is greater than y.
|
||||
func CompareSemver(x, y SemVer) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(y.Major, x.Major),
|
||||
cmp.Compare(y.Minor, x.Minor),
|
||||
cmp.Compare(y.Patch, x.Patch),
|
||||
cmp.Compare(y.Build, x.Build),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user