Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON support and BumpVersion #9

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
49 changes: 49 additions & 0 deletions constraint.go
@@ -1,6 +1,7 @@
package version

import (
"encoding/json"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -156,3 +157,51 @@ func constraintPessimistic(v, c *Version) bool {

return true
}

// MarshalJSON - implement the json-Marshaler interface
func (c *Constraints) MarshalJSON() ([]byte, error) {
return json.Marshal(c.String())
}

// UnmarshalJSON - implement the json-Unmarshaler interface
func (c *Constraints) UnmarshalJSON(data []byte) (err error) {
var constraintStr string
var nc Constraints

err = json.Unmarshal(data, &constraintStr)
if err != nil {
return
}

nc, err = NewConstraint(constraintStr)
if err != nil {
Comment on lines +171 to +177

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
err = json.Unmarshal(data, &constraintStr)
if err != nil {
return
}
nc, err = NewConstraint(constraintStr)
if err != nil {
if err = json.Unmarshal(data, &constraintStr); err != nil {
return
}
if nc, err = NewConstraint(constraintStr); err != nil {

return
}
*c = nc

return
}

// MarshalYAML - implement the YAML-Marshaler interface (gopkg.in/yaml.v2)
func (c *Constraints) MarshalYAML() (str interface{}, err error) {
str = c.String()
return
Comment on lines +186 to +188

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (c *Constraints) MarshalYAML() (str interface{}, err error) {
str = c.String()
return
func (c *Constraints) MarshalYAML() (interface{}, error) {
return c.String(), nil

}

// UnmarshalYAML - implement the yaml-Unmarshaler interface (gopkg.in/yaml.v2)
func (c *Constraints) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
var constraintStr string
var nc Constraints

if err = unmarshal(&constraintStr); err != nil {
return
}

nc, err = NewConstraint(constraintStr)
if err != nil {
Comment on lines +200 to +201

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
nc, err = NewConstraint(constraintStr)
if err != nil {
if nc, err = NewConstraint(constraintStr); err != nil {

return
}
*c = nc

return
}
27 changes: 27 additions & 0 deletions constraint_test.go
@@ -1,6 +1,8 @@
package version

import (
"bytes"
"encoding/json"
"testing"
)

Expand Down Expand Up @@ -98,3 +100,28 @@ func TestConstraintsString(t *testing.T) {
}
}
}

func TestConstraintsJson(t *testing.T) {
type MyStruct struct {
MustVer Constraints
}
var (
vc MyStruct
err error
)
jsBytes := []byte(`{"MustVer":"=1.2, =1.3"}`)
// data -> struct
err = json.Unmarshal(jsBytes, &vc)
if err != nil {
t.Fatalf("expected: json.Unmarshal to succeed\nactual: failed with error %v", err)
}
// struct -> data
data, err := json.Marshal(&vc)
if err != nil {
t.Fatalf("expected: json.Marshal to succeed\nactual: failed with error %v", err)
}

if !bytes.Equal(data, jsBytes) {
t.Fatalf("expected: %s\nactual: %s", jsBytes, data)
}
}
73 changes: 73 additions & 0 deletions version.go
Expand Up @@ -2,6 +2,7 @@ package version

import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"regexp"
Expand All @@ -19,6 +20,20 @@ const VersionRegexpRaw string = `([0-9]+(\.[0-9]+){0,2})` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`?`

type VersionPart int

const (
MajorPart VersionPart = iota
MinorPart
PatchPart
PreReleasePart
MetadataPart
)

var partNames = [...]string{
"major", "minor", "patch", "prerelease", "metadata",
}

// Version represents a single version.
type Version struct {
metadata string
Expand Down Expand Up @@ -249,3 +264,61 @@ func (v *Version) String() string {

return buf.String()
}

// BumpVersion - increment the indicated part by one
// part may be one of: MajorPart, MinorPart or PatchPart
func (v *Version) BumpVersion(part VersionPart) (err error) {
switch part {
case MajorPart, MinorPart, PatchPart:
v.segments[part]++
default:
err = fmt.Errorf("unable to bump version part %s", partNames[part])
}
return
}

// MarshalJSON - implement the json-Marshaler interface
func (v *Version) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, v.String())), nil
}

// UnmarshalJSON - implement the json-Unmarshaler interface
func (v *Version) UnmarshalJSON(data []byte) (err error) {
var verStr string
var nv *Version

err = json.Unmarshal(data, &verStr)
if err != nil {
return
}

nv, err = NewVersion(verStr)
if err != nil {
Comment on lines +290 to +296

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
err = json.Unmarshal(data, &verStr)
if err != nil {
return
}
nv, err = NewVersion(verStr)
if err != nil {
if err = json.Unmarshal(data, &verStr); err != nil {
return
}
if nv, err = NewVersion(verStr); err != nil {

return
}
*v = *nv

return
}

// MarshalYAML - implement the YAML-Marshaler interface (gopkg.in/yaml.v2)
func (v *Version) MarshalYAML() (str interface{}, err error) {
str = v.String()
return
}
Comment on lines +305 to +308

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (v *Version) MarshalYAML() (str interface{}, err error) {
str = v.String()
return
}
func (v *Version) MarshalYAML() (interface{}, error) {
return v.String(), nil
}


// UnmarshalYAML - implement the yaml-Unmarshaler interface (gopkg.in/yaml.v2)
func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
var (
verStr string
nv *Version
)
if err = unmarshal(&verStr); err != nil {
return
}
if nv, err = NewVersion(verStr); err != nil {
return
}
*v = *nv
return
}
63 changes: 63 additions & 0 deletions version_test.go
@@ -1,6 +1,8 @@
package version

import (
"bytes"
"encoding/json"
"reflect"
"testing"
)
Expand Down Expand Up @@ -206,3 +208,64 @@ func TestVersionString(t *testing.T) {
}
}
}

func TestBumpVersion(t *testing.T) {
cases := []struct {
version string
part VersionPart
result string
err bool
}{
{"1.1.1", MajorPart, "2.1.1", false},
{"1.1.1", MinorPart, "1.2.1", false},
{"1.1.1", PatchPart, "1.1.2", false},
{"2", MinorPart, "2.1.0", false},
{"2.2", PatchPart, "2.2.1", false},
{"1.1.0-beta1", MinorPart, "1.2.0-beta1", false},
{"1.1.0-beta1", PreReleasePart, "", true},
{"1.1.0-beta1+foo", MetadataPart, "", true},
}

for _, tc := range cases {
v, err := NewVersion(tc.version)
if err != nil {
t.Fatalf("error parsing version %s", tc.version)
}
err = v.BumpVersion(tc.part)
if tc.err && err == nil {
t.Fatalf("expected error for version: %s", tc.version)
} else if !tc.err && err != nil {
t.Fatalf("error for version %s: %s", tc.version, err)
}
if !tc.err {
if v.String() != tc.result {
t.Fatalf("BumpVersion %d, expecting: %s\nfound %s", tc.part, tc.result, v.String())
}
}
}
}

func TestVersionJSON(t *testing.T) {
type MyStruct struct {
Ver *Version
}
var (
ver MyStruct
err error
)
jsBytes := []byte(`{"Ver":"1.2.3"}`)
// data -> struct
err = json.Unmarshal(jsBytes, &ver)
if err != nil {
t.Fatalf("expected: json.Unmarshal to succeed\nactual: failed with error %v", err)
}
// struct -> data
data, err := json.Marshal(&ver)
if err != nil {
t.Fatalf("expected: json.Marshal to succeed\nactual: failed with error %v", err)
}

if !bytes.Equal(data, jsBytes) {
t.Fatalf("expected: %s\nactual: %s", jsBytes, data)
}
}