Package semver
Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go.
Specifically it provides the ability to:
- Parse semantic versions
- Sort semantic versions
- Check if a semantic version fits within a set of constraints
- Optionally work with a `v` prefix
Parsing Semantic Versions
There are two functions that can parse semantic versions. The `StrictNewVersion`
function only parses valid version 2 semantic versions as outlined in the
specification. The `NewVersion` function attempts to coerce a version into a
semantic version and parse it. For example, if there is a leading v or a version
listed without all 3 parts (e.g. 1.2) it will attempt to coerce it into a valid
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
that can be sorted, compared, and used in constraints.
When parsing a version an optional error can be returned if there is an issue
parsing the version. For example,
v, err := semver.NewVersion("1.2.3-beta.1+b345")
The version object has methods to get the parts of the version, compare it to
other versions, convert the version back into a string, and get the original
string. For more details please see the documentation
at https://godoc.org/github.com/Masterminds/semver.
Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
Checking Version Constraints and Comparing Versions
There are two methods for comparing versions. One uses comparison methods on
`Version` instances and the other is using Constraints. There are some important
differences to notes between these two methods of comparison.
- When two versions are compared using functions such as `Compare`, `LessThan`,
and others it will follow the specification and always include prereleases
within the comparison. It will provide an answer valid with the comparison
spec section at https://semver.org/#spec-item-11
- When constraint checking is used for checks or validation it will follow a
different set of rules that are common for ranges with tools like npm/js
and Rust/Cargo. This includes considering prereleases to be invalid if the
ranges does not include on. If you want to have it include pre-releases a
simple solution is to include `-0` in your range.
- Constraint ranges can have some complex rules including the shorthard use of
~ and ^. For more details on those see the options below.
There are differences between the two methods or checking versions because the
comparison methods on `Version` follow the specification while comparison ranges
are not part of the specification. Different packages and tools have taken it
upon themselves to come up with range rules. This has resulted in differences.
For example, npm/js and Cargo/Rust follow similar patterns which PHP has a
different pattern for ^. The comparison features in this package follow the
npm/js and Cargo/Rust lead because applications using it have followed similar
patters with their versions.
Checking a version against version constraints is one of the most featureful
parts of the package.
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parsable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parsable.
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of comma or space separated AND comparisons. These are then separated by || (OR)
comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3. This can also be written as
`">= 1.2, < 3.0.0 || >= 4.2.3"`
The basic comparisons are:
- `=`: equal (aliased to no operator)
- `!=`: not equal
- `>`: greater than
- `<`: less than
- `>=`: greater than or equal to
- `<=`: less than or equal to
Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
- `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
- `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the tilde operation. For example,
- `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
- `>= 1.2.x` is equivalent to `>= 1.2.0`
- `<= 2.x` is equivalent to `<= 3`
- `*` is equivalent to `>= 0.0.0`
Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
- `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0`
- `~1` is equivalent to `>= 1, < 2`
- `~2.3` is equivalent to `>= 2.3 < 2.4`
- `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
- `~1.x` is equivalent to `>= 1 < 2`
Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes once a stable
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,
- `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
- `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
- `^2.3` is equivalent to `>= 2.3, < 3`
- `^2.x` is equivalent to `>= 2.0.0, < 3`
- `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
- `^0.2` is equivalent to `>=0.2.0 <0.3.0`
- `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
- `^0.0` is equivalent to `>=0.0.0 <0.1.0`
- `^0` is equivalent to `>=0.0.0 <1.0.0`
Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
}
v, _ := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Validate a version against a constraint.
a, msgs := c.Validate(v)
// a is false
for _, m := range msgs {
fmt.Println(m)
// Loops over the errors which would read
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
- Variables
- type Collection
- func (c Collection) Len() int
- func (c Collection) Less(i, j int) bool
- func (c Collection) Swap(i, j int)
- type Constraints
- func NewConstraint(c string) (*Constraints, error)
- func (cs Constraints) Check(v *Version) bool
- func (cs Constraints) MarshalText() ([]byte, error)
- func (cs Constraints) String() string
- func (cs *Constraints) UnmarshalText(text []byte) error
- func (cs Constraints) Validate(v *Version) (bool, []error)
- type Version
- func MustParse(v string) *Version
- func New(major, minor, patch uint64, pre, metadata string) *Version
- func NewVersion(v string) (*Version, error)
- func StrictNewVersion(v string) (*Version, error)
- func (v *Version) Compare(o *Version) int
- func (v *Version) Equal(o *Version) bool
- func (v *Version) GreaterThan(o *Version) bool
- func (v Version) IncMajor() Version
- func (v Version) IncMinor() Version
- func (v Version) IncPatch() Version
- func (v *Version) LessThan(o *Version) bool
- func (v Version) Major() uint64
- func (v Version) MarshalJSON() ([]byte, error)
- func (v Version) MarshalText() ([]byte, error)
- func (v Version) Metadata() string
- func (v Version) Minor() uint64
- func (v *Version) Original() string
- func (v Version) Patch() uint64
- func (v Version) Prerelease() string
- func (v *Version) Scan(value interface{}) error
- func (v Version) SetMetadata(metadata string) (Version, error)
- func (v Version) SetPrerelease(prerelease string) (Version, error)
- func (v Version) String() string
- func (v *Version) UnmarshalJSON(b []byte) error
- func (v *Version) UnmarshalText(text []byte) error
- func (v Version) Value() (driver.Value, error)
Package files
collection.go
constraints.go
doc.go
version.go
Variables
var (
ErrInvalidSemVer = errors.New("Invalid Semantic Version")
ErrEmptyString = errors.New("Version string empty")
ErrInvalidCharacters = errors.New("Invalid characters in version")
ErrSegmentStartsZero = errors.New("Version segment starts with 0")
ErrInvalidMetadata = errors.New("Invalid Metadata string")
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
)
Collection is a collection of Version instances and implements the sort
interface. See the sort package for more details.
https://golang.org/pkg/sort/
type Collection []*Version
func (Collection) Len
¶
func (c Collection) Len() int
Len returns the length of a collection. The number of Version instances
on the slice.
func (Collection) Less
¶
func (c Collection) Less(i, j int) bool
Less is needed for the sort interface to compare two Version objects on the
slice. If checks if one is less than the other.
func (Collection) Swap
¶
func (c Collection) Swap(i, j int)
Swap is needed for the sort interface to replace the Version objects
at two different positions in the slice.
Constraints is one or more constraint that a semantic version can be
checked against.
type Constraints struct {
}
func NewConstraint(c string) (*Constraints, error)
NewConstraint returns a Constraints instance that a Version instance can
be checked against. If there is a parse error it will be returned.
func (Constraints) Check
¶
func (cs Constraints) Check(v *Version) bool
Check tests if a version satisfies the constraints.
func (cs Constraints) MarshalText() ([]byte, error)
MarshalText implements the encoding.TextMarshaler interface.
func (Constraints) String
¶
func (cs Constraints) String() string
func (cs *Constraints) UnmarshalText(text []byte) error
UnmarshalText implements the encoding.TextUnmarshaler interface.
func (Constraints) Validate
¶
func (cs Constraints) Validate(v *Version) (bool, []error)
Validate checks if a version satisfies a constraint. If not a slice of
reasons for the failure are returned in addition to a bool.
Version represents a single semantic version.
type Version struct {
}
func MustParse(v string) *Version
MustParse parses a given version and panics on error.
func New(major, minor, patch uint64, pre, metadata string) *Version
New creates a new instance of Version with each of the parts passed in as
arguments instead of parsing a version string.
func NewVersion(v string) (*Version, error)
NewVersion parses a given version and returns an instance of Version or
an error if unable to parse the version. If the version is SemVer-ish it
attempts to convert it to SemVer. If you want to validate it was a strict
semantic version at parse time see StrictNewVersion().
func StrictNewVersion(v string) (*Version, error)
StrictNewVersion parses a given version and returns an instance of Version or
an error if unable to parse the version. Only parses valid semantic versions.
Performs checking that can find errors within the version.
If you want to coerce a version such as 1 or 1.2 and parse it as the 1.x
releases of semver did, use the NewVersion() function.
func (*Version) Compare
¶
func (v *Version) Compare(o *Version) int
Compare compares this version to another one. It returns -1, 0, or 1 if
the version smaller, equal, or larger than the other version.
Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is
lower than the version without a prerelease. Compare always takes into account
prereleases. If you want to work with ranges using typical range syntaxes that
skip prereleases if the range is not looking for them use constraints.
func (*Version) Equal
¶
func (v *Version) Equal(o *Version) bool
Equal tests if two versions are equal to each other.
Note, versions can be equal with different metadata since metadata
is not considered part of the comparable version.
func (v *Version) GreaterThan(o *Version) bool
GreaterThan tests if one version is greater than another one.
func (v Version) IncMajor() Version
IncMajor produces the next major version.
Sets patch to 0.
Sets minor to 0.
Increments major number.
Unsets metadata.
Unsets prerelease status.
func (v Version) IncMinor() Version
IncMinor produces the next minor version.
Sets patch to 0.
Increments minor number.
Unsets metadata.
Unsets prerelease status.
func (v Version) IncPatch() Version
IncPatch produces the next patch version.
If the current version does not have prerelease/metadata information,
it unsets metadata and prerelease values, increments patch number.
If the current version has any of prerelease or metadata information,
it unsets both values and keeps current patch value
func (v *Version) LessThan(o *Version) bool
LessThan tests if one version is less than another one.
func (Version) Major
¶
func (v Version) Major() uint64
Major returns the major version.
func (v Version) MarshalJSON() ([]byte, error)
MarshalJSON implements JSON.Marshaler interface.
func (v Version) MarshalText() ([]byte, error)
MarshalText implements the encoding.TextMarshaler interface.
func (v Version) Metadata() string
Metadata returns the metadata on the version.
func (Version) Minor
¶
func (v Version) Minor() uint64
Minor returns the minor version.
func (v *Version) Original() string
Original returns the original value passed in to be parsed.
func (Version) Patch
¶
func (v Version) Patch() uint64
Patch returns the patch version.
func (v Version) Prerelease() string
Prerelease returns the pre-release version.
func (*Version) Scan
¶
func (v *Version) Scan(value interface{}) error
Scan implements the SQL.Scanner interface.
func (v Version) SetMetadata(metadata string) (Version, error)
SetMetadata defines metadata value.
Value must not include the required 'plus' prefix.
func (v Version) SetPrerelease(prerelease string) (Version, error)
SetPrerelease defines the prerelease value.
Value must not include the required 'hyphen' prefix.
func (Version) String
¶
func (v Version) String() string
String converts a Version object to a string.
Note, if the original version contained a leading v this version will not.
See the Original() method to retrieve the original value. Semantic Versions
don't contain a leading v per the spec. Instead it's optional on
implementation.
func (v *Version) UnmarshalJSON(b []byte) error
UnmarshalJSON implements JSON.Unmarshaler interface.
func (v *Version) UnmarshalText(text []byte) error
UnmarshalText implements the encoding.TextUnmarshaler interface.
func (Version) Value
¶
func (v Version) Value() (driver.Value, error)
Value implements the Driver.Valuer interface.