Merge pull request #9184 from hashicorp/jbardin/vendor

Update reflectwalk and copystructure
This commit is contained in:
James Bardin 2016-10-03 12:59:43 -04:00 committed by GitHub
commit 4c2a33748c
3 changed files with 77 additions and 36 deletions

View File

@ -28,6 +28,18 @@ type CopierFunc func(interface{}) (interface{}, error)
// this map as well as to Copy in a mutex. // this map as well as to Copy in a mutex.
var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc) var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
// Must is a helper that wraps a call to a function returning
// (interface{}, error) and panics if the error is non-nil. It is intended
// for use in variable initializations and should only be used when a copy
// error should be a crashing case.
func Must(v interface{}, err error) interface{} {
if err != nil {
panic("copy error: " + err.Error())
}
return v
}
var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true") var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true")
type Config struct { type Config struct {
@ -77,7 +89,7 @@ type walker struct {
ignoreDepth int ignoreDepth int
vals []reflect.Value vals []reflect.Value
cs []reflect.Value cs []reflect.Value
ps []bool ps []int
// any locks we've taken, indexed by depth // any locks we've taken, indexed by depth
locks []sync.Locker locks []sync.Locker
@ -93,6 +105,10 @@ func (w *walker) Enter(l reflectwalk.Location) error {
w.locks = append(w.locks, nil) w.locks = append(w.locks, nil)
} }
for len(w.ps) < w.depth+1 {
w.ps = append(w.ps, 0)
}
return nil return nil
} }
@ -103,6 +119,7 @@ func (w *walker) Exit(l reflectwalk.Location) error {
defer locker.Unlock() defer locker.Unlock()
} }
w.ps[w.depth] = 0
w.depth-- w.depth--
if w.ignoreDepth > w.depth { if w.ignoreDepth > w.depth {
w.ignoreDepth = 0 w.ignoreDepth = 0
@ -154,6 +171,7 @@ func (w *walker) Exit(l reflectwalk.Location) error {
if v.IsValid() { if v.IsValid() {
s := w.cs[len(w.cs)-1] s := w.cs[len(w.cs)-1]
sf := reflect.Indirect(s).FieldByName(f.Name) sf := reflect.Indirect(s).FieldByName(f.Name)
if sf.CanSet() { if sf.CanSet() {
sf.Set(v) sf.Set(v)
} }
@ -191,20 +209,16 @@ func (w *walker) MapElem(m, k, v reflect.Value) error {
} }
func (w *walker) PointerEnter(v bool) error { func (w *walker) PointerEnter(v bool) error {
if w.ignoring() { if v {
return nil w.ps[w.depth]++
} }
w.ps = append(w.ps, v)
return nil return nil
} }
func (w *walker) PointerExit(bool) error { func (w *walker) PointerExit(v bool) error {
if w.ignoring() { if v {
return nil w.ps[w.depth]--
} }
w.ps = w.ps[:len(w.ps)-1]
return nil return nil
} }
@ -219,7 +233,7 @@ func (w *walker) Primitive(v reflect.Value) error {
var newV reflect.Value var newV reflect.Value
if v.IsValid() && v.CanInterface() { if v.IsValid() && v.CanInterface() {
newV = reflect.New(v.Type()) newV = reflect.New(v.Type())
reflect.Indirect(newV).Set(v) newV.Elem().Set(v)
} }
w.valPush(newV) w.valPush(newV)
@ -318,7 +332,7 @@ func (w *walker) ignoring() bool {
} }
func (w *walker) pointerPeek() bool { func (w *walker) pointerPeek() bool {
return w.ps[len(w.ps)-1] return w.ps[w.depth] > 0
} }
func (w *walker) valPop() reflect.Value { func (w *walker) valPop() reflect.Value {
@ -350,7 +364,17 @@ func (w *walker) replacePointerMaybe() {
// we need to push that onto the stack. // we need to push that onto the stack.
if !w.pointerPeek() { if !w.pointerPeek() {
w.valPush(reflect.Indirect(w.valPop())) w.valPush(reflect.Indirect(w.valPop()))
return
} }
v := w.valPop()
for i := 1; i < w.ps[w.depth]; i++ {
p := reflect.New(v.Type())
p.Elem().Set(v)
v = p
}
w.valPush(v)
} }
// if this value is a Locker, lock it and add it to the locks slice // if this value is a Locker, lock it and add it to the locks slice

View File

@ -81,35 +81,52 @@ func walk(v reflect.Value, w interface{}) (err error) {
// almost any part is changed). I will try to explain here. // almost any part is changed). I will try to explain here.
// //
// First, we check if the value is an interface, if so, we really need // First, we check if the value is an interface, if so, we really need
// to check the interface's VALUE to see whether it is a pointer (pointers // to check the interface's VALUE to see whether it is a pointer.
// to interfaces are not allowed).
// //
// Check whether the value is then an interface. If so, then set pointer // Check whether the value is then a pointer. If so, then set pointer
// to true to notify the user. // to true to notify the user.
// //
// If we still have a pointer or an interface after the indirections, then
// we unwrap another level
//
// At this time, we also set "v" to be the dereferenced value. This is // At this time, we also set "v" to be the dereferenced value. This is
// because once we've unwrapped the pointer we want to use that value. // because once we've unwrapped the pointer we want to use that value.
pointer := false pointer := false
pointerV := v pointerV := v
if pointerV.Kind() == reflect.Interface {
pointerV = pointerV.Elem()
}
if pointerV.Kind() == reflect.Ptr {
pointer = true
v = reflect.Indirect(pointerV)
}
if pw, ok := w.(PointerWalker); ok {
if err = pw.PointerEnter(pointer); err != nil {
return
}
defer func() { for {
if err != nil { if pointerV.Kind() == reflect.Interface {
pointerV = pointerV.Elem()
}
if pointerV.Kind() == reflect.Ptr {
pointer = true
v = reflect.Indirect(pointerV)
}
if pw, ok := w.(PointerWalker); ok {
if err = pw.PointerEnter(pointer); err != nil {
return return
} }
err = pw.PointerExit(pointer) defer func(pointer bool) {
}() if err != nil {
return
}
err = pw.PointerExit(pointer)
}(pointer)
}
if pointer {
pointerV = v
}
pointer = false
// If we still have a pointer or interface we have to indirect another level.
switch pointerV.Kind() {
case reflect.Ptr, reflect.Interface:
continue
}
break
} }
// We preserve the original value here because if it is an interface // We preserve the original value here because if it is an interface

12
vendor/vendor.json vendored
View File

@ -1464,10 +1464,10 @@
"revision": "8631ce90f28644f54aeedcb3e389a85174e067d1" "revision": "8631ce90f28644f54aeedcb3e389a85174e067d1"
}, },
{ {
"checksumSHA1": "EDAtec3XSbTjw6gWG+NNScows9M=", "checksumSHA1": "gsIaLhXE/YZahSg33edGHvzVQ1o=",
"path": "github.com/mitchellh/copystructure", "path": "github.com/mitchellh/copystructure",
"revision": "49a4444999946bce1882f9db0eb3ba0a44ed1fbb", "revision": "c740739b7b69de009385f52933769c1c037705df",
"revisionTime": "2016-09-28T02:49:35Z" "revisionTime": "2016-10-03T06:35:14Z"
}, },
{ {
"path": "github.com/mitchellh/go-homedir", "path": "github.com/mitchellh/go-homedir",
@ -1499,10 +1499,10 @@
"revision": "6e6954073784f7ee67b28f2d22749d6479151ed7" "revision": "6e6954073784f7ee67b28f2d22749d6479151ed7"
}, },
{ {
"checksumSHA1": "kXh6sdGViiRK0REpIWydJvpsyY0=", "checksumSHA1": "u+sHUhd/XXvjiVPAJ/h8yvLbSj4=",
"path": "github.com/mitchellh/reflectwalk", "path": "github.com/mitchellh/reflectwalk",
"revision": "0c9480f65513be815a88d6076a3d8d95d4274236", "revision": "4a18c295388e8482403483c88469392f9e6556d7",
"revisionTime": "2016-09-28T02:49:03Z" "revisionTime": "2016-10-02T04:32:56Z"
}, },
{ {
"checksumSHA1": "/iig5lYSPCL3C8J7e4nTAevYNDE=", "checksumSHA1": "/iig5lYSPCL3C8J7e4nTAevYNDE=",