зеркало из https://github.com/golang/dep.git
Update go-toml for nested custom Marshaler support
This commit is contained in:
Родитель
b30a25cd66
Коммит
0afa554494
10
fs.go
10
fs.go
|
@ -12,16 +12,10 @@ import (
|
|||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// tomlMarshaler is the interface implemented by types that
|
||||
// can marshal themselves into valid TOML.
|
||||
// TODO(carolynvs) Add this (and an unmarshaler) to go-toml, implemented using the same patterns in encoding/json
|
||||
type tomlMarshaler interface {
|
||||
MarshalTOML() ([]byte, error)
|
||||
}
|
||||
|
||||
func IsRegular(name string) (bool, error) {
|
||||
// TODO: lstat?
|
||||
fi, err := os.Stat(name)
|
||||
|
@ -65,7 +59,7 @@ func IsNonEmptyDir(name string) (bool, error) {
|
|||
return len(files) != 0, nil
|
||||
}
|
||||
|
||||
func writeFile(path string, in tomlMarshaler) error {
|
||||
func writeFile(path string, in toml.Marshaler) error {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
memo = "31a7162c06758e4619ed89b91e1f48bf94ad14f394bbee79299ed0bb5150e409"
|
||||
memo = "2f117dcf1ebe1cff7acbddb851d29b87554d2249f1033f2a4cca3b33dc3fecc2"
|
||||
|
||||
[[projects]]
|
||||
branch = "2.x"
|
||||
|
@ -9,7 +9,7 @@ memo = "31a7162c06758e4619ed89b91e1f48bf94ad14f394bbee79299ed0bb5150e409"
|
|||
[[projects]]
|
||||
name = "github.com/Masterminds/vcs"
|
||||
packages = ["."]
|
||||
revision = "fbe9fb6ad5b5f35b3e82a7c21123cfc526cbf895"
|
||||
revision = "795e20f901c3d561de52811fb3488a2cb2c8588b"
|
||||
version = "v1.11.0"
|
||||
|
||||
[[projects]]
|
||||
|
@ -27,8 +27,8 @@ memo = "31a7162c06758e4619ed89b91e1f48bf94ad14f394bbee79299ed0bb5150e409"
|
|||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/pelletier/go-toml"
|
||||
revision = "e32a2e04744250647a72bf17da1b09befc03b6b1"
|
||||
packages = ["."]
|
||||
revision = "fe206efb84b2bc8e8cfafe6b4c1826622be969e3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
|
|
|
@ -59,6 +59,10 @@ type LockDiff struct {
|
|||
Modify []LockedProjectDiff
|
||||
}
|
||||
|
||||
type rawLockedProjectDiffs struct {
|
||||
Projects []LockedProjectDiff `toml:"projects"`
|
||||
}
|
||||
|
||||
func (diff *LockDiff) Format() (string, error) {
|
||||
if diff == nil {
|
||||
return "", nil
|
||||
|
@ -71,13 +75,12 @@ func (diff *LockDiff) Format() (string, error) {
|
|||
}
|
||||
|
||||
writeDiffs := func(diffs []LockedProjectDiff) error {
|
||||
for i := 0; i < len(diffs); i++ {
|
||||
chunk, err := toml.Marshal(diffs[i])
|
||||
raw := rawLockedProjectDiffs{diffs}
|
||||
chunk, err := toml.Marshal(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf.Write(chunk)
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
return nil
|
||||
}
|
||||
|
@ -114,11 +117,11 @@ func (diff *LockDiff) Format() (string, error) {
|
|||
// TODO(carolynvs) this should be moved to gps
|
||||
type LockedProjectDiff struct {
|
||||
Name gps.ProjectRoot `toml:"name"`
|
||||
Source *StringDiff `toml:"source"`
|
||||
Version *StringDiff `toml:"version"`
|
||||
Branch *StringDiff `toml:"branch"`
|
||||
Revision *StringDiff `toml:"revision"`
|
||||
Packages []StringDiff `toml:"packages"`
|
||||
Source *StringDiff `toml:"source,omitempty"`
|
||||
Version *StringDiff `toml:"version,omitempty"`
|
||||
Branch *StringDiff `toml:"branch,omitempty"`
|
||||
Revision *StringDiff `toml:"revision,omitempty"`
|
||||
Packages []StringDiff `toml:"packages,omitempty"`
|
||||
}
|
||||
|
||||
type StringDiff struct {
|
||||
|
@ -142,6 +145,10 @@ func (diff StringDiff) String() string {
|
|||
return diff.Current
|
||||
}
|
||||
|
||||
func (diff StringDiff) MarshalTOML() ([]byte, error) {
|
||||
return []byte(diff.String()), nil
|
||||
}
|
||||
|
||||
// VendorBehavior defines when the vendor directory should be written.
|
||||
type VendorBehavior int
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ type tomlOpts struct {
|
|||
}
|
||||
|
||||
var timeType = reflect.TypeOf(time.Time{})
|
||||
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
||||
|
||||
// Check if the given marshall type maps to a TomlTree primitive
|
||||
func isPrimitive(mtype reflect.Type) bool {
|
||||
|
@ -50,7 +51,7 @@ func isPrimitive(mtype reflect.Type) bool {
|
|||
case reflect.String:
|
||||
return true
|
||||
case reflect.Struct:
|
||||
return mtype == timeType
|
||||
return mtype == timeType || isCustomMarshaler(mtype)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -90,6 +91,20 @@ func isTree(mtype reflect.Type) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func isCustomMarshaler(mtype reflect.Type) bool {
|
||||
return mtype.Implements(marshalerType)
|
||||
}
|
||||
|
||||
func callCustomMarshaler(mval reflect.Value) ([]byte, error) {
|
||||
return mval.Interface().(Marshaler).MarshalTOML()
|
||||
}
|
||||
|
||||
// Marshaler is the interface implemented by types that
|
||||
// can marshal themselves into valid TOML.
|
||||
type Marshaler interface {
|
||||
MarshalTOML() ([]byte, error)
|
||||
}
|
||||
|
||||
/*
|
||||
Marshal returns the TOML encoding of v. Behavior is similar to the Go json
|
||||
encoder, except that there is no concept of a Marshaler interface or MarshalTOML
|
||||
|
@ -106,6 +121,9 @@ func Marshal(v interface{}) ([]byte, error) {
|
|||
return []byte{}, errors.New("Only a struct can be marshaled to TOML")
|
||||
}
|
||||
sval := reflect.ValueOf(v)
|
||||
if isCustomMarshaler(mtype) {
|
||||
return callCustomMarshaler(sval)
|
||||
}
|
||||
t, err := valueToTree(mtype, sval)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
|
@ -178,6 +196,8 @@ func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
|
|||
return valueToToml(mtype.Elem(), mval.Elem())
|
||||
}
|
||||
switch {
|
||||
case isCustomMarshaler(mtype):
|
||||
return callCustomMarshaler(mval)
|
||||
case isTree(mtype):
|
||||
return valueToTree(mtype, mval)
|
||||
case isTreeSlice(mtype):
|
||||
|
|
|
@ -3,6 +3,7 @@ package toml
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -533,3 +534,50 @@ func TestNestedUnmarshal(t *testing.T) {
|
|||
t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
type customMarshalerParent struct {
|
||||
Self customMarshaler `toml:"me"`
|
||||
Friends []customMarshaler `toml:"friends"`
|
||||
}
|
||||
|
||||
type customMarshaler struct {
|
||||
FirsName string
|
||||
LastName string
|
||||
}
|
||||
|
||||
func (c customMarshaler) MarshalTOML() ([]byte, error) {
|
||||
fullName := fmt.Sprintf("%s %s", c.FirsName, c.LastName)
|
||||
return []byte(fullName), nil
|
||||
}
|
||||
|
||||
var customMarshalerData = customMarshaler{FirsName: "Sally", LastName: "Fields"}
|
||||
var customMarshalerToml = []byte(`Sally Fields`)
|
||||
var nestedCustomMarshalerData = customMarshalerParent{
|
||||
Self: customMarshaler{FirsName: "Maiku", LastName: "Suteda"},
|
||||
Friends: []customMarshaler{customMarshalerData},
|
||||
}
|
||||
var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"]
|
||||
me = "Maiku Suteda"
|
||||
`)
|
||||
|
||||
func TestCustomMarshaler(t *testing.T) {
|
||||
result, err := Marshal(customMarshalerData)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := customMarshalerToml
|
||||
if !bytes.Equal(result, expected) {
|
||||
t.Errorf("Bad custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNestedCustomMarshaler(t *testing.T) {
|
||||
result, err := Marshal(nestedCustomMarshalerData)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := nestedCustomMarshalerToml
|
||||
if !bytes.Equal(result, expected) {
|
||||
t.Errorf("Bad nested custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,9 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
|
|||
return strconv.FormatFloat(value, 'f', -1, 32), nil
|
||||
case string:
|
||||
return "\"" + encodeTomlString(value) + "\"", nil
|
||||
case []byte:
|
||||
b, _ := v.([]byte)
|
||||
return tomlValueStringRepresentation(string(b))
|
||||
case bool:
|
||||
if value {
|
||||
return "true", nil
|
||||
|
|
Загрузка…
Ссылка в новой задаче