Giter Site home page Giter Site logo

semver's Introduction

semver for golang Build Status GoDoc Coverage Status Go Report Card

semver is a Semantic Versioning library written in golang. It fully covers spec version 2.0.0.

Versioning

Old v1-v3 versions exist in the root of the repository for compatiblity reasons and will only receive bug fixes.

The current stable version is v4 and is fully go-mod compatible.

Usage

$ go get github.com/blang/semver/v4
# Or use fixed versions
$ go get github.com/blang/semver/[email protected]

Note: Always vendor your dependencies or fix on a specific version tag.

import github.com/blang/semver/v4
v1, err := semver.Make("1.0.0-beta")
v2, err := semver.Make("2.0.0-beta")
v1.Compare(v2)

Also check the GoDocs.

Why should I use this lib?

  • Fully spec compatible
  • No reflection
  • No regex
  • Fully tested (Coverage >99%)
  • Readable parsing/validation errors
  • Fast (See Benchmarks)
  • Only Stdlib
  • Uses values instead of pointers
  • Many features, see below

Features

  • Parsing and validation at all levels
  • Comparator-like comparisons
  • Compare Helper Methods
  • InPlace manipulation
  • Ranges >=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1
  • Wildcards >=1.x, <=2.5.x
  • Sortable (implements sort.Interface)
  • database/sql compatible (sql.Scanner/Valuer)
  • encoding/json compatible (json.Marshaler/Unmarshaler)

Ranges

A Range is a set of conditions which specify which versions satisfy the range.

A condition is composed of an operator and a version. The supported operators are:

  • <1.0.0 Less than 1.0.0
  • <=1.0.0 Less than or equal to 1.0.0
  • >1.0.0 Greater than 1.0.0
  • >=1.0.0 Greater than or equal to 1.0.0
  • 1.0.0, =1.0.0, ==1.0.0 Equal to 1.0.0
  • !1.0.0, !=1.0.0 Not equal to 1.0.0. Excludes version 1.0.0.

Note that spaces between the operator and the version will be gracefully tolerated.

A Range can link multiple Ranges separated by space:

Ranges can be linked by logical AND:

  • >1.0.0 <2.0.0 would match between both ranges, so 1.1.1 and 1.8.7 but not 1.0.0 or 2.0.0
  • >1.0.0 <3.0.0 !2.0.3-beta.2 would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2

Ranges can also be linked by logical OR:

  • <2.0.0 || >=3.0.0 would match 1.x.x and 3.x.x but not 2.x.x

AND has a higher precedence than OR. It's not possible to use brackets.

Ranges can be combined by both AND and OR

  • >1.0.0 <2.0.0 || >3.0.0 !4.2.1 would match 1.2.3, 1.9.9, 3.1.1, but not 4.2.1, 2.1.1

Range usage:

v, err := semver.Parse("1.2.3")
expectedRange, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
if expectedRange(v) {
    //valid
}

Example

Have a look at full examples in v4/examples/main.go

import github.com/blang/semver/v4

v, err := semver.Make("0.0.1-alpha.preview+123.github")
fmt.Printf("Major: %d\n", v.Major)
fmt.Printf("Minor: %d\n", v.Minor)
fmt.Printf("Patch: %d\n", v.Patch)
fmt.Printf("Pre: %s\n", v.Pre)
fmt.Printf("Build: %s\n", v.Build)

// Prerelease versions array
if len(v.Pre) > 0 {
    fmt.Println("Prerelease versions:")
    for i, pre := range v.Pre {
        fmt.Printf("%d: %q\n", i, pre)
    }
}

// Build meta data array
if len(v.Build) > 0 {
    fmt.Println("Build meta data:")
    for i, build := range v.Build {
        fmt.Printf("%d: %q\n", i, build)
    }
}

v001, err := semver.Make("0.0.1")
// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
v001.GT(v) == true
v.LT(v001) == true
v.GTE(v) == true
v.LTE(v) == true

// Or use v.Compare(v2) for comparisons (-1, 0, 1):
v001.Compare(v) == 1
v.Compare(v001) == -1
v.Compare(v) == 0

// Manipulate Version in place:
v.Pre[0], err = semver.NewPRVersion("beta")
if err != nil {
    fmt.Printf("Error parsing pre release version: %q", err)
}

fmt.Println("\nValidate versions:")
v.Build[0] = "?"

err = v.Validate()
if err != nil {
    fmt.Printf("Validation failed: %s\n", err)
}

Benchmarks

BenchmarkParseSimple-4           5000000    390    ns/op    48 B/op   1 allocs/op
BenchmarkParseComplex-4          1000000   1813    ns/op   256 B/op   7 allocs/op
BenchmarkParseAverage-4          1000000   1171    ns/op   163 B/op   4 allocs/op
BenchmarkStringSimple-4         20000000    119    ns/op    16 B/op   1 allocs/op
BenchmarkStringLarger-4         10000000    206    ns/op    32 B/op   2 allocs/op
BenchmarkStringComplex-4         5000000    324    ns/op    80 B/op   3 allocs/op
BenchmarkStringAverage-4         5000000    273    ns/op    53 B/op   2 allocs/op
BenchmarkValidateSimple-4      200000000      9.33 ns/op     0 B/op   0 allocs/op
BenchmarkValidateComplex-4       3000000    469    ns/op     0 B/op   0 allocs/op
BenchmarkValidateAverage-4       5000000    256    ns/op     0 B/op   0 allocs/op
BenchmarkCompareSimple-4       100000000     11.8  ns/op     0 B/op   0 allocs/op
BenchmarkCompareComplex-4       50000000     30.8  ns/op     0 B/op   0 allocs/op
BenchmarkCompareAverage-4       30000000     41.5  ns/op     0 B/op   0 allocs/op
BenchmarkSort-4                  3000000    419    ns/op   256 B/op   2 allocs/op
BenchmarkRangeParseSimple-4      2000000    850    ns/op   192 B/op   5 allocs/op
BenchmarkRangeParseAverage-4     1000000   1677    ns/op   400 B/op  10 allocs/op
BenchmarkRangeParseComplex-4      300000   5214    ns/op  1440 B/op  30 allocs/op
BenchmarkRangeMatchSimple-4     50000000     25.6  ns/op     0 B/op   0 allocs/op
BenchmarkRangeMatchAverage-4    30000000     56.4  ns/op     0 B/op   0 allocs/op
BenchmarkRangeMatchComplex-4    10000000    153    ns/op     0 B/op   0 allocs/op

See benchmark cases at semver_test.go

Motivation

I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.

Contribution

Feel free to make a pull request. For bigger changes create a issue first to discuss about it.

License

See LICENSE file.

semver's People

Contributors

alexandernst avatar blang avatar cbandy avatar ferhatelmas avatar glaslos avatar hanzei avatar jaffee avatar kubuxu avatar kujenga avatar lfaoro avatar matfax avatar priyankchheda avatar radeksimko avatar rosenhouse avatar saschagrunert avatar songmu avatar tike avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

semver's Issues

Major version constraint circumvented by prerelease versions

I'm trying to implement a range check that allows any major or minor version change, but never a major change. So that anything starting with 1 but never anything starting with 2 or above.

I tried expressing that as >= 1.x, >= 1.x < 2.x, >= 1.x < 2.x.x, and >= 1.x < 2.0.0, but found that it will allow 2.x prereleases, e.g. 2.0.0-v2-5.

package main

import (
	"fmt"
	"github.com/blang/semver/v4"
)

func main() {
	v, _ := semver.Parse("2.0.0-v2-5")
	r, _ := semver.ParseRange(">= 1.x")
	fmt.Println(r(v))
	r, _ = semver.ParseRange(">= 1.x < 2.x")
	fmt.Println(r(v))
	r, _ = semver.ParseRange(">= 1.x < 2.x.x")
	fmt.Println(r(v))
	r, _ = semver.ParseRange(">= 1.x < 2.0.0")
	fmt.Println(r(v))
}

This prints true four times. I know that 2.0.0-v2-5 is "less than" 2.0.0 because it is a prerelease, but this seems to be making it caught by 1.x as well.

Minor point - New and Make

Thanks for reworking this to be value oriented. I revisited my project where I was using this and forgot I had reported the whole pointer thing and wondered "Why did I use pointers everywhere". Then I came here and checked the issues to see that I had raised the issue with you and was pleased to see that v2 was now available. That was perfect since I was rewriting my code to use values anyway.

However, one minor thing I noticed. You still have a function called New. The Golang convention here is to use Make for functions that return values and New for ones that return pointers. So I'd suggest you change New to Make. You could include New as well...but it should return a pointer. But I'm not how useful that would be for someone since the whole API is now value based. But the value versions of the methods should work with the pointers (just not the other way around). So it shouldn't hurt to have both New and Make. I could submit a PR if you want.

Thanks again!

Use of Pointers

I notice that lots of methods in your API (e.g., Validate, Compare) take pointer arguments. But I don't see why they should. None of these operations actually mutate the object. So it should be fine to simply pass a value.

The reason I see this as an issue is twofold. First, it gives the impression (when looking at the API), that these things mutate the objects. But more important for me, it means I need to have pointers available in my code which keeps the door open for inadvertent mutation in my code as well.

Is there a reason to use the pointers in the API like you have?

Coverage is lower than what readme says

Fully tested (Coverage >99%)

But it seems coverage is around 87% according to batch in readme.

Please, don't get me wrong, it's just to increase awareness and we can make it great again. If you wish, I can even give a hand.

Support "1.x" like ranges

It would be great if you could do this:

r := semver.ParseRange("1.x")
v := semver.Parse("1.0.0")

fmt.Println(r.Contains(v) == true) // true

proposal: remove pre-release versions >1.0.0 increment constraint

What is the motivation behind stopping pre-releases from being incremented? I read the SemVer spec and couldn't find this rule, could you point out where you've seen this constraint?

// IncrementMinor increments the minor version
func (v *Version) IncrementMinor() error {
        //-----
	if v.Major == 0 { // why?
		return fmt.Errorf("Minor version can not be incremented for %q", v.String())
	}
        //-----
	v.Minor += 1
	v.Patch = 0
	return nil
}

Would you mind me submitting a PR to remove it?

Constraint check fails for .0 patch prereleases

I think I have found a bug in the constraint check for .0 patch prereleases.

An example for this can be found in the Go Playground https://go.dev/play/p/LShjC5F37TT or in the main.go:

main.go (expand)
package main

import (
  "fmt"

  "github.com/blang/semver/v4"
)

func main() {
  constraint := "0.49.x"
  versionConstraint, err := semver.ParseRange(constraint)
  if err != nil {
  	return
  }

  versions := []string{
  	"0.49.0-alpha",
  	"0.49.1-alpha",
  	"0.49.0",
  	"0.49.1",
  }

  for _, ver := range versions {
  	parsedVersion, err := semver.Parse(ver)
  	if err != nil {
  		return
  	}

  	fmt.Printf("%v becomes:\n %#v \n", ver, parsedVersion)
  	fmt.Printf(" Major: %d\n", parsedVersion.Major)
  	fmt.Printf(" Minor: %d\n", parsedVersion.Minor)
  	fmt.Printf(" Patch: %d\n", parsedVersion.Patch)
  	fmt.Printf(" Pre: %s\n", parsedVersion.Pre)
  	fmt.Printf(" Build: %s\n", parsedVersion.Build)

  	didMatch := "false"
  	if versionConstraint(parsedVersion) {
  		didMatch = "true"
  	}

  	fmt.Printf(" => constraint %v matched for %v: %v \n\n", constraint, ver, didMatch)
  }

}

The output of this is:

0.49.0-alpha becomes:
 semver.Version{Major:0x0, Minor:0x31, Patch:0x0, Pre:[]semver.PRVersion{semver.PRVersion{VersionStr:"alpha", VersionNum:0x0, IsNum:false}}, Build:[]string(nil)} 
 Major: 0
 Minor: 49
 Patch: 0
 Pre: [alpha]
 Build: []
 => constraint 0.49.x matched for 0.49.0-alpha: false // ❌ this seems to be a bug

0.49.1-alpha becomes:
 semver.Version{Major:0x0, Minor:0x31, Patch:0x1, Pre:[]semver.PRVersion{semver.PRVersion{VersionStr:"alpha", VersionNum:0x0, IsNum:false}}, Build:[]string(nil)} 
 Major: 0
 Minor: 49
 Patch: 1
 Pre: [alpha]
 Build: []
 => constraint 0.49.x matched for 0.49.1-alpha: true  // ✅ as expected 

0.49.0 becomes:
 semver.Version{Major:0x0, Minor:0x31, Patch:0x0, Pre:[]semver.PRVersion(nil), Build:[]string(nil)} 
 Major: 0
 Minor: 49
 Patch: 0
 Pre: []
 Build: []
 => constraint 0.49.x matched for 0.49.0: true // ✅ as expected 

0.49.1 becomes:
 semver.Version{Major:0x0, Minor:0x31, Patch:0x1, Pre:[]semver.PRVersion(nil), Build:[]string(nil)} 
 Major: 0
 Minor: 49
 Patch: 1
 Pre: []
 Build: []
 => constraint 0.49.x matched for 0.49.1: true // ✅ as expected 

According to this SemVer check, that's incorrect: https://jubianchi.github.io/semver-check/#/0.49.x/0.49.0-alpha.

Confusing behavior of Range with version with release tag

If I have a range >=4.3.0 and I pass a version with release tag such as 4.3.0-20191231, the result will be False. However, if I use range >4.3.0-0, then the result will be True. This is a bit of confusing behavior because from my perspective 4.3.0-20191231 should be a part of the range >=4.3.0. I wonder if someone can explains this behavior a bit for me.

Here is the code if someone wants to test it out on Playground:

package main

import (
	"fmt"
	"github.com/blang/semver"
)

func main() {
	ra, _ := semver.ParseRange(">=4.3.0")

	if ra(semver.MustParse("4.3.0-201912000000")) {
		fmt.Print("True")
	} else {
		fmt.Print("False")
	}
}

Thanks so much in advance.

Comparison operators

Could you use the next names (in uppercase)?

eq
Returns the boolean truth of arg1 == arg2
ne
Returns the boolean truth of arg1 != arg2
lt
Returns the boolean truth of arg1 < arg2
le
Returns the boolean truth of arg1 <= arg2
gt
Returns the boolean truth of arg1 > arg2
ge
Returns the boolean truth of arg1 >= arg2

Got from http://golang.org/pkg/text/template/

range issue perhaps?

I was trying to figure out what might be causing some unexpected behavior in this package. To be honest, I'm not sure if this is something I'm doing wrong or not.

I added some extra code to range_test.go, which I think shows the issue:

		{">1.2.2 <1.2.4", []tv{
			{"1.2.1", false},
			{"1.2.1-pl1", false},
			{"1.2.2", false},
			{"1.2.2-pl1", false},
			{"1.2.3", true},
			{"1.2.3-pl1", true},
			{"1.2.4", false},
			{"1.2.4-pl1", false},
		}},
		{">=1.2.2 <1.2.4", []tv{
			{"1.2.1", false},
			{"1.2.1-pl1", false},
			{"1.2.2", true},
			{"1.2.2-pl1", true},
			{"1.2.3", true},
			{"1.2.3-pl1", true},
			{"1.2.4", false},
			{"1.2.4-pl1", false},
		}},

The issue is that versions with -pl1 seem to return different results then those without.

The output of the above is:

--- FAIL: TestParseRange (0.00s)
	range_test.go:514: Invalid for case ">1.2.2 <1.2.4" matching "1.2.4-pl1": Expected false, got: true
	range_test.go:514: Invalid for case ">=1.2.2 <1.2.4" matching "1.2.2-pl1": Expected true, got: false
	range_test.go:514: Invalid for case ">=1.2.2 <1.2.4" matching "1.2.4-pl1": Expected false, got: true
FAIL
exit status 1
FAIL	github.com/blang/semver	0.007s

Am I doing something wrong here?

  • Greg

Support ParseRangeTolerant

Passing >=1.6.5 <2.0.0 || >= 2.1.7 (note the space before 2.1.7) to ParseRange will make the library return an error.

Can we have a ParseRangeTolerant function that would be more tolerant to this errors?

Bin Release

I really like your Tool.
Are you planning on releasing it as bin?

Support tildes, carets, hyphens, wildcards, etc

👋 Hi there!

tl;dr - I forked your (very good!) library. Are you interested in upstreaming the changes?

I'm in the unenviable position of needing to migrate a Node server that uses node-semver to golang without breaking any user who is currently relying on the logic in the Node library. Currently there is no equivalent semver library for Go that supports the range of inputs that the Node library does. Some examples:

~>1.2.x
^1.2.0
^10.14.1 || ^8.15.0
8 - 10
~7.x || ~8.x || ~9.x
~10.1.x
1.* || >=2.0.* <2.2.*
etc

To that end, I basically translated the (regex heavy) logic from the Node library directly and added it as a pre-processing step that normalizes the above input into the >=1.2.3 <2.0.0 type ranges that your library expects.

Changes here: master...jmorrell:master

I'm happy to either clean up these changes and upstream them into your library, or fork and support as a separate semver library for those who need these other features and something that is compatible with Node's semver library. Or I can maintain my fork separately if you are not interested.

Downsides:

  • Lots of regex, which your library has avoided
  • Parsing is substantially slower as a result

Benchmark after changes:

$ go test -v -bench .
...
goos: darwin
goarch: amd64
pkg: github.com/jmorrell/semver
BenchmarkRangeParseSimple-8                 1000           1332107 ns/op         1155055 B/op       9163 allocs/op
BenchmarkRangeParseAverage-8                1000           1325482 ns/op         1163610 B/op       9283 allocs/op
BenchmarkRangeParseComplex-8                 300           3933910 ns/op         3485886 B/op      27792 allocs/op
BenchmarkRangeMatchSimple-8             100000000               12.7 ns/op             0 B/op          0 allocs/op
BenchmarkRangeMatchAverage-8            50000000                26.7 ns/op             0 B/op          0 allocs/op
BenchmarkRangeMatchComplex-8            20000000                73.2 ns/op             0 B/op          0 allocs/op
BenchmarkParseSimple-8                  10000000               162 ns/op              48 B/op          1 allocs/op
BenchmarkParseComplex-8                  2000000               826 ns/op             256 B/op          7 allocs/op
BenchmarkParseAverage-8                  3000000               537 ns/op             163 B/op          4 allocs/op
BenchmarkParseTolerantAverage-8          5000000               356 ns/op             101 B/op          3 allocs/op
BenchmarkStringSimple-8                 30000000                38.1 ns/op             5 B/op          1 allocs/op
BenchmarkStringLarger-8                 20000000                83.0 ns/op            32 B/op          2 allocs/op
BenchmarkStringComplex-8                10000000               127 ns/op              80 B/op          3 allocs/op
BenchmarkStringAverage-8                20000000               107 ns/op              47 B/op          2 allocs/op
BenchmarkValidateSimple-8               500000000                3.41 ns/op            0 B/op          0 allocs/op
BenchmarkValidateComplex-8               5000000               259 ns/op               0 B/op          0 allocs/op
BenchmarkValidateAverage-8              10000000               141 ns/op               0 B/op          0 allocs/op
BenchmarkCompareSimple-8                300000000                4.22 ns/op            0 B/op          0 allocs/op
BenchmarkCompareComplex-8               100000000               16.4 ns/op             0 B/op          0 allocs/op
BenchmarkCompareAverage-8               100000000               22.1 ns/op             0 B/op          0 allocs/op
BenchmarkSort-8                         10000000               184 ns/op             256 B/op          2 allocs/op

Your repo on master on the same machine:

$ go test -v -bench .
...
goos: darwin
goarch: amd64
pkg: github.com/blang/semver
BenchmarkRangeParseSimple-8              3000000               553 ns/op             240 B/op          7 allocs/op
BenchmarkRangeParseAverage-8             1000000              1058 ns/op             480 B/op         13 allocs/op
BenchmarkRangeParseComplex-8              500000              3309 ns/op            1792 B/op         39 allocs/op
BenchmarkRangeMatchSimple-8             100000000               12.0 ns/op             0 B/op          0 allocs/op
BenchmarkRangeMatchAverage-8            50000000                26.1 ns/op             0 B/op          0 allocs/op
BenchmarkRangeMatchComplex-8            20000000                75.3 ns/op             0 B/op          0 allocs/op
BenchmarkParseSimple-8                  10000000               172 ns/op              48 B/op          1 allocs/op
BenchmarkParseComplex-8                  2000000               762 ns/op             256 B/op          7 allocs/op
BenchmarkParseAverage-8                  3000000               561 ns/op             163 B/op          4 allocs/op
BenchmarkParseTolerantAverage-8          5000000               359 ns/op             101 B/op          3 allocs/op
BenchmarkStringSimple-8                 50000000                37.7 ns/op             5 B/op          1 allocs/op
BenchmarkStringLarger-8                 20000000                79.3 ns/op            32 B/op          2 allocs/op
BenchmarkStringComplex-8                10000000               120 ns/op              80 B/op          3 allocs/op
BenchmarkStringAverage-8                20000000               103 ns/op              47 B/op          2 allocs/op
BenchmarkValidateSimple-8               500000000                3.38 ns/op            0 B/op          0 allocs/op
BenchmarkValidateComplex-8              10000000               191 ns/op               0 B/op          0 allocs/op
BenchmarkValidateAverage-8              20000000               113 ns/op               0 B/op          0 allocs/op
BenchmarkCompareSimple-8                300000000                4.21 ns/op            0 B/op          0 allocs/op
BenchmarkCompareComplex-8               100000000               17.5 ns/op             0 B/op          0 allocs/op
BenchmarkCompareAverage-8               100000000               21.7 ns/op             0 B/op          0 allocs/op
BenchmarkSort-8                         10000000               175 ns/op             256 B/op          2 allocs/op

How to compare the pre-release version?

Why the result is false? I think 201912060615 < 201912111117. How can I make it return true.?

package main

import (
	"fmt"
	"github.com/blang/semver"
)

func main() {
	inRange, err := semver.ParseRange(">=4.3.0 <4.3.0-201912111117")
	if err != nil {
		panic(err)
	}

	version := semver.MustParse("4.3.0-201912060615")

	// Check if the version meets the constraints. The a variable will be true.
	fmt.Printf("within range: %t", inRange(version))
}

Using x in prerelease causes error

Given the version 0.1.0-x, ParseRange returns the following error:

Could not get version from string: "<"

Replacing the x with another character fixes the problem (e.g. 0.1.0-y).

This appears to be related to x being used to denote wildcards as implemented in #27:

if strings.Contains(ap, "x") {

This can be reproduced with the following test:

func TestExpandWildcardVersion(t *testing.T) {
	tests := []struct {
		i [][]string
		o [][]string
	}{
		{[][]string{{"foox"}}, nil},

                // FAILING TEST
		{[][]string{{"0.1.0-x"}}, [][]string{{"0.1.0-x"}}},


		{[][]string{{">=1.2.x"}}, [][]string{{">=1.2.0"}}},
		{[][]string{{"<=1.2.x"}}, [][]string{{"<1.3.0"}}},
		{[][]string{{">1.2.x"}}, [][]string{{">=1.3.0"}}},
		{[][]string{{"<1.2.x"}}, [][]string{{"<1.2.0"}}},
		{[][]string{{"!=1.2.x"}}, [][]string{{"<1.2.0", ">=1.3.0"}}},
		{[][]string{{">=1.x"}}, [][]string{{">=1.0.0"}}},
		{[][]string{{"<=1.x"}}, [][]string{{"<2.0.0"}}},
		{[][]string{{">1.x"}}, [][]string{{">=2.0.0"}}},
		{[][]string{{"<1.x"}}, [][]string{{"<1.0.0"}}},
		{[][]string{{"!=1.x"}}, [][]string{{"<1.0.0", ">=2.0.0"}}},
		{[][]string{{"1.2.x"}}, [][]string{{">=1.2.0", "<1.3.0"}}},
		{[][]string{{"1.x"}}, [][]string{{">=1.0.0", "<2.0.0"}}},

	}

	for _, tc := range tests {
		o, _ := expandWildcardVersion(tc.i)
		if !reflect.DeepEqual(tc.o, o) {
			t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.o, o)
		}
	}
}

Result of this test is: Invalid for case [["0.1.0-x"]]: Expected [["0.1.0-x"]], got: [[">=0.1.0-x" "<"]]

At the very least, it would be helpful to call out this corner case in the docs if fixing this would be challenging due to breaking changes.

Support `^x.x.x`?

A common (and extremely useful) semver constraint is the ^x.x.x form. While this can also be expressed using a range (eg ^1.2.3 can be expressed as >= 1.2.3 <2.0.0). Similarly (but less useful), ~1.2 can be expressed as >= 1.2.0 <1.3.0.

See https://semver.npmjs.com/.

Are there any plans to add this? If not, do you have any pointers on how to best to approach this?

finalize version feature

return only finalize version i.e. major, minor and patch number and discarding prerelease and build number.

ParseTolerant now fails on a valid semver

After #47 I noticed that the following (which semver.ParseTolerant had previously accepted) now no longer parses:

semver.Parse("4.1.0-0.nightly") is returned as 4.1.0-0.nightly

but after this change

semver.ParseTolerant("4.1.0-0.nightly") errors with strconv.ParseUint: parsing "": invalid syntax

I think the fix is that the "remove leading zeroes" part of that change needs a more accurate check than len(p) >1 - probably needs to be looking to the first dot, not the whole string.

1.0.0-rc1 is greater then 1.0.0-rc11

I does work for

  • 1.0.0-rc1 < 1.0.0-rc2
  • 1.0.0-rc10 < 1.0.0-rc11

but is broken for

  • 1.0.0-rc1 > 1.0.0-rc11
  • 1.0.0-rc1 > 1.0.0-rc12

And so on ( comparing a 2 digit rc vs a 1 digit rc )

Fork with ^1.0.0 (caret), ~1.0.0 (tilda), 2 - 4 (subtraction range?) without any regex

In this fork, I added support for the following:

        {[][]string{{"~1.2.1"}}, [][]string{{"<1.3.0", ">=1.2.1"}}},
		{[][]string{{"^1.2.1"}}, [][]string{{"<2.0.0", ">=1.2.1"}}},
		{[][]string{{"~>1.2.x"}}, [][]string{{">=1.2.0"}}},
		{[][]string{{"~>1.x"}}, [][]string{{">=1.0.0"}}},
		{[][]string{{"1.*"}}, [][]string{{">=1.0.0", "<2.0.0"}}},
		{[][]string{{"1.2.*"}}, [][]string{{">=1.2.0", "<1.3.0"}}},
		{[][]string{{"*"}}, [][]string{{">=0.0.0"}}},
		{[][]string{{"8.0.0 - 10.0.0"}}, [][]string{{"<10.0.0", ">=8.0.0"}}},
		{[][]string{{"8 - 10"}}, [][]string{{"<10.0.0", ">=8.0.0"}}},
		{[][]string{{"8 - 10.1"}}, [][]string{{"<10.1.0", ">=8.0.0"}}},
		{[][]string{{" 8 "}}, [][]string{{"8.0.0"}}},
		{[][]string{{" 800000 "}}, [][]string{{"800000.0.0"}}},
		{[][]string{{" ~7.x "}}, [][]string{{"<8.0.0", ">=7.0.0"}}},
		{[][]string{{" ~7.0.x "}}, [][]string{{"<7.1.0", ">=7.0.0"}}},
		{[][]string{{" ~* "}}, [][]string{{">=0.0.0"}}},

It does not allocate more memory. But, it's about 8% slower. Do you want me submit a PR?

goos: darwin
goarch: amd64
pkg: github.com/Jarred-Sumner/semver/v4
cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
BenchmarkRangeParseSimple-16        	 2402451	       493.4 ns/op	     224 B/op	       7 allocs/op
BenchmarkRangeParseAverage-16       	 1235457	       967.9 ns/op	     456 B/op	      13 allocs/op
BenchmarkRangeParseComplex-16       	  392412	      3129 ns/op	    1736 B/op	      39 allocs/op
BenchmarkRangeMatchSimple-16        	100000000	        11.32 ns/op	       0 B/op	       0 allocs/op
BenchmarkRangeMatchAverage-16       	48316423	        25.28 ns/op	       0 B/op	       0 allocs/op
BenchmarkRangeMatchComplex-16       	17318359	        70.28 ns/op	       0 B/op	       0 allocs/op
BenchmarkRangeMatchNPM-16           	27442455	        43.70 ns/op	       0 B/op	       0 allocs/op
BenchmarkParseSimple-16             	 8453367	       139.5 ns/op	      48 B/op	       1 allocs/op
BenchmarkParseComplex-16            	 1795279	       687.0 ns/op	     256 B/op	       7 allocs/op
BenchmarkParseAverage-16            	 2672629	       466.3 ns/op	     163 B/op	       4 allocs/op
BenchmarkParseTolerantAverage-16    	 3093957	       394.1 ns/op	     132 B/op	       4 allocs/op
BenchmarkStringSimple-16            	40966444	        30.76 ns/op	       5 B/op	       1 allocs/op
BenchmarkStringLarger-16            	17750650	        65.63 ns/op	      32 B/op	       2 allocs/op
BenchmarkStringComplex-16           	12103804	        98.85 ns/op	      80 B/op	       3 allocs/op
BenchmarkStringAverage-16           	13836576	        89.55 ns/op	      45 B/op	       2 allocs/op
BenchmarkValidateSimple-16          	441872518	         2.589 ns/op	       0 B/op	   0 allocs/op
BenchmarkValidateComplex-16         	 7224438	       151.2 ns/op	       0 B/op	       0 allocs/op
BenchmarkValidateAverage-16         	13011160	        88.88 ns/op	       0 B/op	       0 allocs/op
BenchmarkCompareSimple-16           	309173464	         3.999 ns/op	       0 B/op	   0 allocs/op
BenchmarkCompareComplex-16          	82620462	        12.37 ns/op	       0 B/op	       0 allocs/op
BenchmarkCompareAverage-16          	68264864	        17.24 ns/op	       0 B/op	       0 allocs/op
BenchmarkSort-16                    	 7555494	       160.2 ns/op	     248 B/op	       2 allocs/op
PASS
ok  	github.com/Jarred-Sumner/semver/v4	31.099s

Fair warning that this is my ~4th day of writing go.

Convert semver.Range to string?

Thanks for this project, I'm sorry if I missed this in the godocs, but is there a way to get a string representation of a range? For example I have a range that is equal to >=1.0.0 AND <= 3.0.0, would like to get that as a string to show to users. Thanks!

Wrong module name

Hi! Thank you for a great package!

There is a caveat though: the package at its v3 major revision but it doesn't have /v3 suffix in its module name.

IMO you should either to drop all versions history or give it a proper name, i.e. github.com/blang/semver/v3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.