version

package module
v0.0.0-...-2f4aa95 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: MPL-2.0 Imports: 6 Imported by: 20

README

go-version

Go Reference Go Go Version

A zero-dependency Go library that ports the PHP Composer version and constraint parsing semantics to Go — including caret (^), tilde (~), wildcards (*), hyphen ranges, stability flags, and prerelease comparison.

Forked from hashicorp/go-version and fundamentally extended with full Composer compatibility.

Installation

go get github.com/shyim/go-version

Requires Go 1.23+.

Quick Start

import "github.com/shyim/go-version"

// Check if a version satisfies a constraint
ok, err := version.Satisfies("1.2.3", "^1.0")   // true
ok, err  = version.Satisfies("7.0.0", "^1.0")   // false

// Parse a version
v, err := version.NewVersion("1.2.3-beta1")
fmt.Println(v.Major())            // 1
fmt.Println(v.Minor())            // 2
fmt.Println(v.Patch())            // 3
fmt.Println(v.Prerelease())       // "beta1"
fmt.Println(v.NormalizedString()) // "1.2.3.0-beta1"

// Compare versions
a := version.Must(version.NewVersion("1.2.3-rc2"))
b := version.Must(version.NewVersion("1.2.3-rc1"))
a.GreaterThan(b)  // true — numeric suffixes compared correctly

// Parse a constraint with multiple conditions
c, err := version.NewConstraint(">=1.0,<2.0")
c.Check(v)  // true

// Check constraint intersection (for dependency solvers)
ok, err = version.ConstraintIntersects("^1.0", ">=1.0,<2.0")  // true
ok, err = version.ConstraintIntersects("^1.0", "^2.0")         // false

// Check subset relationship
ok, err = version.ConstraintSubsetOf("^1.2", "^1.0 || ^2.0")   // true

API Reference

Version Parsing & Comparison
Function / Method Description
NewVersion(v string) (*Version, error) Parse a version string (supports Composer formats)
Must(v *Version, err error) *Version Panic-on-error convenience wrapper
v.Compare(other *Version) int Compare two versions: -1, 0, 1
v.Equal(other *Version) bool Exact equality
v.GreaterThan(other *Version) bool Greater-than
v.GreaterThanOrEqual(other *Version) bool Greater-than-or-equal
v.LessThan(other *Version) bool Less-than
v.LessThanOrEqual(other *Version) bool Less-than-or-equal
v.Major() int Major version segment
v.Minor() int Minor version segment
v.Patch() int Patch version segment
v.Segments() []int All numeric segments as []int
v.Segments64() []int64 All numeric segments as []int64
v.Prerelease() string Prerelease identifier (e.g. "beta2")
v.IsPrerelease() bool Whether the version has prerelease info
v.NormalizedString() string Canonical string representation
v.Original() string Original parsed string
v.IncreaseMajor() Bump major, reset minor/patch/build
v.IncreaseMinor() Bump minor, reset patch/build
v.IncreasePatch() Bump patch, reset build
Constraint Parsing & Checking
Function / Method Description
NewConstraint(cs string) (Constraints, error) Parse a constraint string
MustConstraints(c Constraints, err error) Constraints Panic-on-error convenience wrapper
cs.Check(v *Version) bool Test if a version satisfies the constraints
cs.String() string String representation of constraints
c.Check(v *Version) bool Test a single constraint against a version
c.Prerelease() bool Whether the constraint target has a prerelease
c.String() string Original constraint string
Convenience API
Function Description
Satisfies(version, constraint string) (bool, error) One-shot: parse version, parse constraint, check
NormalizeComposerVersion(version string) (string, error) Normalize a Composer version string
Stability(version string) string Returns "dev", "alpha", "beta", "RC", or "stable"
Constraint Intersection (for dependency solvers)
Function Description
ConstraintIntersects(left, right string) (bool, error) Do two constraints share at least one version?
ConstraintSubsetOf(left, right string) (bool, error) Does left's version set fall entirely within right's?
Sorting
Type Description
Collection []*Version Implements sort.Interface for stable version sorting
Stability Constants
const (
    StabilityDev    = "dev"
    StabilityAlpha  = "alpha"
    StabilityBeta   = "beta"
    StabilityRC     = "RC"
    StabilityStable = "stable"
)

Feature Overview

Version Formats

The library parses a wide range of version strings following Composer's conventions:

Format Example Notes
Classic semver 1.2.3, v1.2.3, 1.2.3.4 Padded to 4 segments
Prereleases 1.0.0-alpha1, 1.0.0-beta.2, 1.0.0-RC1 Abbreviations: a1, b2, p1/pl3
Build metadata 1.2.3+build.123 Stripped, does not affect comparison
Date versions 20100102, 2010.01.02, 201903.0 Composer's CalVer support
dev branches dev-main, dev-feature/x Treated as unordered (equality only)
Numeric branches 2.1.x-dev, 1.*-dev Wildcards mapped to 9999999
Stability suffixes 1.0.0@beta, 1.2.3@stable Stripped during normalization
Aliases 1.2.3 as 1.2.3-alias Source version extracted
Constraint Operators
Operator Example Meaning
= / == =1.2.3 Exact version match
!= / <> !=1.2.3 Not equal
> >1.0 Greater than
>= >=1.0 Greater than or equal
< <2.0 Less than
<= <=2.0 Less than or equal
^ ^1.2.3 Caret: compatible updates (Composer-style)
~ ~1.2.3 Tilde: next significant release
* *, 2.*, 1.2.* Wildcard matching
(none) 1.2.3 Bare version = exact match
- 1.0 - 2.0 Hyphen range
Composer-Specific Semantics

Prerelease rank ordering — versions sort in Composer's stability order: dev < alpha < beta < RC < stable

With numeric suffixes compared numerically: 1.0.0-rc1 < 1.0.0-rc2 < 1.0.0-rc10

Caret (^) — allows changes that do not modify the leftmost non-zero digit:

Constraint Equivalent Range Rationale
^1.2.3 >=1.2.3 <2.0.0 Major > 0, lock major
^0.2.3 >=0.2.3 <0.3.0 Major = 0, minor > 0, lock minor
^0.0.3 >=0.0.3 <0.0.4 Both zero, lock patch
^1.2 >=1.2.0 <2.0.0 Equivalent to ^1.2.0

Tilde (~) — allows changes at the last specified segment:

Constraint Equivalent Range Rationale
~1.2.3 >=1.2.3 <1.3.0 3 segments: lock minor
~1.2 >=1.2.0 <2.0.0 2 segments: lock major
~1.2.3.4 >=1.2.3.4 <1.2.4.0 4 segments: lock patch

Hyphen ranges — Composer-style range with intelligent upper bound logic:

Constraint Equivalent
1.0 - 2.0 >=1.0 <2.1
1.2.3 - 2.3.4 >=1.2.3 <=2.3.4
1.0 - 2.0.* >=1.0 <2.1

Stability flags (@stable, @beta, @dev, @alpha, @RC):

c := version.MustConstraints(version.NewConstraint(">=1.0@stable"))
c.Check(version.Must(version.NewVersion("1.0.0")))       // true
c.Check(version.Must(version.NewVersion("1.0.0-beta")))  // false

Stability-appended operators>=1.0@beta expands to >=1.0.0-beta, making the minimum-stable constraint automatically aware of its stability level.

Branch versions (dev-*) — treated as unordered for ordering operators; only equality (=/==) and inequality (!=) give meaningful results. Wildcards (*) and anyBranch domains include all branch versions.

Constraint composition — supports both || and | as OR separators, with , and whitespace as AND:

  • >=1.0,<2.0 — AND: version must satisfy both
  • ^1.0 || ^2.0 — OR: version must satisfy at least one
  • >=1.0 <2.0 — AND (whitespace delimiter)

Differences from hashicorp/go-version

Feature hashicorp/go-version shyim/go-version
Version model Strict semver (MAJOR.MINOR.PATCH) Composer (multi-segment, branches, date versions)
Operators =, !=, >, <, >=, <= + ^, ~, *, hyphen ranges
Prerelease comparison Basic string compare Ranked: dev < alpha < beta < RC < stable, numeric suffixes
Caret / tilde Not supported Full Composer semantics
Stability flags Not supported @stable, @beta, @alpha, @dev, @RC
Branch versions Not supported dev-* with equality-only semantics
Constraint intersection Not supported Full domain algebra
Wildcards * only 1.*, 1.2.*, 2.x, x.x.x
Normalization None Aliases, stability flags, branches, date versions
Dependencies None None (preserved)

Performance

The library includes an optimized fast path for the common case of plain numeric versions (1.2.3, v1.2), avoiding regexp overhead. Benchmarks are available:

go test -bench=. -benchmem ./...

Testing

The library has comprehensive test coverage:

Area Tests
Version parsing 24 test functions, table-driven + property-based
Constraint checking 27 test functions, 900+ operator-matrix combinations
Normalization 2 test functions + fast-path parity verification
Constraint intersection 7 test functions + exhaustive domain algebra tests
API surface 4 test functions
Semver behavior 35 test functions, 100KB+ conformance suite

Fuzz tests are included for all public entry points:

go test -run=Fuzz -fuzz=FuzzNewVersion -fuzztime=30s ./...
go test -run=Fuzz -fuzz=FuzzNewConstraint -fuzztime=30s ./...
go test -run=Fuzz -fuzz=FuzzSatisfies -fuzztime=30s ./...
go test -run=Fuzz -fuzz=FuzzConstraintIntersects -fuzztime=30s ./...

Run all tests:

go test ./...

Architecture

The library follows a clean two-phase pipeline:

normalizer.go → version.go → constraint.go → intersect.go
                         ↕
              version_collection.go
  • normalizer.go — Canonicalizes raw version strings (aliases, stability suffixes, branches, date versions, classical semver modifiers)
  • version.goVersion type, regex parsing, ranked prerelease comparison
  • constraint.go — Disjunctive Normal Form constraint model, all operators, hyphen ranges, stability constraints
  • domain.go / interval.go / snapshot.go / intersect.go — Domain algebra for constraint intersection and subset queries
  • version_collection.gosort.Interface for version slices
  • api.go — Public convenience API (Satisfies, NormalizeComposerVersion, Stability)

Zero external dependencies.

License

MIT — see LICENSE for details. Forked from hashicorp/go-version (also MIT licensed).

Documentation

Index

Constants

View Source
const (
	StabilityDev    = "dev"
	StabilityAlpha  = "alpha"
	StabilityBeta   = "beta"
	StabilityRC     = "RC"
	StabilityStable = "stable"
)
View Source
const (
	VersionRegexpRaw string = `[\^~v]?([0-9]+(\.[0-9]+)*?)` +
		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|([-@]?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
		`?`
)

VersionRegexpRaw The raw regular expression string used for testing the validity of a version.

Variables

This section is empty.

Functions

func ConstraintIntersects

func ConstraintIntersects(left, right string) (bool, error)

ConstraintIntersects reports whether two Composer constraints can match at least one common version.

func ConstraintSubsetOf

func ConstraintSubsetOf(left, right string) (bool, error)

ConstraintSubsetOf reports whether every version matched by left is also matched by right.

func NormalizeComposerVersion

func NormalizeComposerVersion(versionString string) (string, error)

NormalizeComposerVersion normalizes a Composer version string for comparison.

func Satisfies

func Satisfies(versionString, constraintString string) (bool, error)

Satisfies reports whether versionString matches constraintString.

func Stability

func Stability(versionString string) string

Stability returns the Composer stability for a version string.

Types

type Collection

type Collection []*Version

Collection is a type that implements the sort.Interface interface so that versions can be sorted.

func (Collection) Len

func (v Collection) Len() int

func (Collection) Less

func (v Collection) Less(i, j int) bool

func (Collection) Swap

func (v Collection) Swap(i, j int)

type Constraint

type Constraint struct {
	// contains filtered or unexported fields
}

Constraint represents a single constraint for a version, such as ">= 1.0".

func (*Constraint) Check

func (c *Constraint) Check(v *Version) bool

Check tests if a constraint is validated by the given version.

func (*Constraint) Prerelease

func (c *Constraint) Prerelease() bool

Prerelease returns true if the version underlying this constraint contains a prerelease field.

func (*Constraint) String

func (c *Constraint) String() string

type Constraints

type Constraints [][]*Constraint

Constraints is a 2D slice of constraints. We make a custom type so that we can add methods to it.

func MustConstraints

func MustConstraints(c Constraints, err error) Constraints

MustConstraints is a helper that wraps a call to a function returning (Constraints, error) and panics if error is non-nil.

func NewConstraint

func NewConstraint(cs string) (Constraints, error)

NewConstraint will parse one or more constraints from the given constraint string. The string must be a comma or pipe separated list of constraints.

func (Constraints) Check

func (cs Constraints) Check(v *Version) bool

Check tests if a version satisfies all the constraints.

func (Constraints) String

func (cs Constraints) String() string

Returns the string format of the constraints

type Version

type Version struct {
	// contains filtered or unexported fields
}

Version represents a single version.

func Must

func Must(v *Version, err error) *Version

Must is a helper that wraps a call to a function returning (*Version, error) and panics if error is non-nil.

func NewVersion

func NewVersion(v string) (*Version, error)

NewVersion parses the given version and returns a new Version.

func (*Version) Compare

func (v *Version) Compare(other *Version) int

Compare compares this version to another version. This returns -1, 0, or 1 if this version is smaller, equal, or larger than the other version, respectively.

If you want boolean results, use the LessThan, Equal, GreaterThan, GreaterThanOrEqual or LessThanOrEqual methods.

func (*Version) Equal

func (v *Version) Equal(o *Version) bool

Equal tests if two versions are equal.

func (*Version) GreaterThan

func (v *Version) GreaterThan(o *Version) bool

GreaterThan tests if this version is greater than another version.

func (*Version) GreaterThanOrEqual

func (v *Version) GreaterThanOrEqual(o *Version) bool

GreaterThanOrEqual tests if this version is greater than or equal to another version.

func (*Version) IncreaseMajor

func (v *Version) IncreaseMajor()

IncreaseMajor increases the major version number by 1 and resets minor, patch and build to 0.

func (*Version) IncreaseMinor

func (v *Version) IncreaseMinor()

IncreaseMinor increases the minor version number by 1 and resets patch and build to 0.

func (*Version) IncreasePatch

func (v *Version) IncreasePatch()

IncreasePatch increases the patch version number by 1 and resets build to 0.

func (*Version) IsPrerelease

func (v *Version) IsPrerelease() bool

IsPrerelease returns true if the version has prerelease information.

func (*Version) LessThan

func (v *Version) LessThan(o *Version) bool

LessThan tests if this version is less than another version.

func (*Version) LessThanOrEqual

func (v *Version) LessThanOrEqual(o *Version) bool

LessThanOrEqual tests if this version is less than or equal to another version.

func (*Version) Major

func (v *Version) Major() int

Major returns the major version number.

func (*Version) Minor

func (v *Version) Minor() int

Minor returns the minor version number.

func (*Version) NormalizedString

func (v *Version) NormalizedString() string

NormalizedString returns the canonicalized version string including any pre-release information. Build metadata is not retained, matching Composer, which discards everything after "+" during normalization.

This value is rebuilt according to the parsed segments and other information. Therefore, ambiguities in the version string such as prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and missing parts (1.0 => 1.0.0) will be made into a canonicalized form as shown in the parenthesized examples.

func (*Version) Original

func (v *Version) Original() string

Original returns the original parsed version as-is, including any potential space, `v` prefix, etc.

func (*Version) Patch

func (v *Version) Patch() int

Patch returns the patch version number.

func (*Version) Prerelease

func (v *Version) Prerelease() string

Prerelease returns any prerelease data that is part of the version, or blank if there is no prerelease data.

Prerelease information is anything that comes after the "-" in the version (but before any metadata). For example, with "1.2.3-beta", the prerelease information is "beta".

func (*Version) Segments

func (v *Version) Segments() []int

Segments return the numeric segments of the version as a slice of ins.

This excludes any metadata or pre-release information. For example, for a version "1.2.3-beta", segments will return a slice of 1, 2, 3.

func (*Version) Segments64

func (v *Version) Segments64() []int64

Segments64 returns the numeric segments of the version as a slice of int64s.

This excludes any metadata or pre-release information. For example, for a version "1.2.3-beta", segments will return a slice of 1, 2, 3.

func (*Version) String

func (v *Version) String() string

Original returns the original parsed version as-is, including any potential space, `v` prefix, etc.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL