Add basic skeleton of libpod runtime

Signed-off-by: Matthew Heon <mheon@redhat.com>
This commit is contained in:
Matthew Heon 2017-08-28 17:33:02 -04:00
parent 3473e8afed
commit 2a121111b5
5 changed files with 715 additions and 28 deletions

22
vendor/github.com/ulule/deepcopier/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Ulule
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

129
vendor/github.com/ulule/deepcopier/README.md generated vendored Normal file
View file

@ -0,0 +1,129 @@
# Deepcopier
[![Build Status](https://secure.travis-ci.org/ulule/deepcopier.png?branch=master)](http://travis-ci.org/ulule/deepcopier)
This package is meant to make copying of structs to/from others structs a bit easier.
## Installation
```bash
go get -u github.com/ulule/deepcopier
```
## Usage
```golang
// Deep copy instance1 into instance2
Copy(instance1).To(instance2)
// Deep copy instance1 into instance2 and passes the following context (which
// is basically a map[string]interface{}) as first argument
// to methods of instance2 that defined the struct tag "context".
Copy(instance1).WithContext(map[string]interface{}{"foo": "bar"}).To(instance2)
// Deep copy instance2 into instance1
Copy(instance1).From(instance2)
// Deep copy instance2 into instance1 and passes the following context (which
// is basically a map[string]interface{}) as first argument
// to methods of instance1 that defined the struct tag "context".
Copy(instance1).WithContext(map[string]interface{}{"foo": "bar"}).From(instance2)
```
Available options for `deepcopier` struct tag:
| Option | Description |
| --------- | -------------------------------------------------------------------- |
| `field` | Field or method name in source instance |
| `skip` | Ignores the field |
| `context` | Takes a `map[string]interface{}` as first argument (for methods) |
| `force` | Set the value of a `sql.Null*` field (instead of copying the struct) |
**Options example:**
```golang
type Source struct {
Name string
SkipMe string
SQLNullStringToSQLNullString sql.NullString
SQLNullStringToString sql.NullString
}
func (Source) MethodThatTakesContext(c map[string]interface{}) string {
return "whatever"
}
type Destination struct {
FieldWithAnotherNameInSource string `deepcopier:"field:Name"`
SkipMe string `deepcopier:"skip"`
MethodThatTakesContext string `deepcopier:"context"`
SQLNullStringToSQLNullString sql.NullString
SQLNullStringToString string `deepcopier:"force"`
}
```
Example:
```golang
package main
import (
"fmt"
"github.com/ulule/deepcopier"
)
// Model
type User struct {
// Basic string field
Name string
// Deepcopier supports https://golang.org/pkg/database/sql/driver/#Valuer
Email sql.NullString
}
func (u *User) MethodThatTakesContext(ctx map[string]interface{}) string {
// do whatever you want
return "hello from this method"
}
// Resource
type UserResource struct {
DisplayName string `deepcopier:"field:Name"`
SkipMe string `deepcopier:"skip"`
MethodThatTakesContext string `deepcopier:"context"`
Email string `deepcopier:"force"`
}
func main() {
user := &User{
Name: "gilles",
Email: sql.NullString{
Valid: true,
String: "gilles@example.com",
},
}
resource := &UserResource{}
deepcopier.Copy(user).To(resource)
fmt.Println(resource.DisplayName)
fmt.Println(resource.Email)
}
```
Looking for more information about the usage?
We wrote [an introduction article](https://github.com/ulule/deepcopier/blob/master/examples/rest-usage/README.rst).
Have a look and feel free to give us your feedback.
## Contributing
* Ping us on twitter [@oibafsellig](https://twitter.com/oibafsellig), [@thoas](https://twitter.com/thoas)
* Fork the [project](https://github.com/ulule/deepcopier)
* Help us improving and fixing [issues](https://github.com/ulule/deepcopier/issues)
Don't hesitate ;)

350
vendor/github.com/ulule/deepcopier/deepcopier.go generated vendored Normal file
View file

@ -0,0 +1,350 @@
package deepcopier
import (
"database/sql/driver"
"fmt"
"reflect"
"strings"
)
const (
// TagName is the deepcopier struct tag name.
TagName = "deepcopier"
// FieldOptionName is the from field option name for struct tag.
FieldOptionName = "field"
// ContextOptionName is the context option name for struct tag.
ContextOptionName = "context"
// SkipOptionName is the skip option name for struct tag.
SkipOptionName = "skip"
// ForceOptionName is the skip option name for struct tag.
ForceOptionName = "force"
)
type (
// TagOptions is a map that contains extracted struct tag options.
TagOptions map[string]string
// Options are copier options.
Options struct {
// Context given to WithContext() method.
Context map[string]interface{}
// Reversed reverses struct tag checkings.
Reversed bool
}
)
// DeepCopier deep copies a struct to/from a struct.
type DeepCopier struct {
dst interface{}
src interface{}
ctx map[string]interface{}
}
// Copy sets source or destination.
func Copy(src interface{}) *DeepCopier {
return &DeepCopier{src: src}
}
// WithContext injects the given context into the builder instance.
func (dc *DeepCopier) WithContext(ctx map[string]interface{}) *DeepCopier {
dc.ctx = ctx
return dc
}
// To sets the destination.
func (dc *DeepCopier) To(dst interface{}) error {
dc.dst = dst
return process(dc.dst, dc.src, Options{Context: dc.ctx})
}
// From sets the given the source as destination and destination as source.
func (dc *DeepCopier) From(src interface{}) error {
dc.dst = dc.src
dc.src = src
return process(dc.dst, dc.src, Options{Context: dc.ctx, Reversed: true})
}
// process handles copy.
func process(dst interface{}, src interface{}, args ...Options) error {
var (
options = Options{}
srcValue = reflect.Indirect(reflect.ValueOf(src))
dstValue = reflect.Indirect(reflect.ValueOf(dst))
srcFieldNames = getFieldNames(src)
srcMethodNames = getMethodNames(src)
)
if len(args) > 0 {
options = args[0]
}
if !dstValue.CanAddr() {
return fmt.Errorf("destination %+v is unaddressable", dstValue.Interface())
}
for _, f := range srcFieldNames {
var (
srcFieldValue = srcValue.FieldByName(f)
srcFieldType, srcFieldFound = srcValue.Type().FieldByName(f)
srcFieldName = srcFieldType.Name
dstFieldName = srcFieldName
tagOptions TagOptions
)
if !srcFieldFound {
continue
}
if options.Reversed {
tagOptions = getTagOptions(srcFieldType.Tag.Get(TagName))
if v, ok := tagOptions[FieldOptionName]; ok && v != "" {
dstFieldName = v
}
} else {
if name, opts := getRelatedField(dst, srcFieldName); name != "" {
dstFieldName, tagOptions = name, opts
}
}
if _, ok := tagOptions[SkipOptionName]; ok {
continue
}
var (
dstFieldType, dstFieldFound = dstValue.Type().FieldByName(dstFieldName)
dstFieldValue = dstValue.FieldByName(dstFieldName)
)
if !dstFieldFound {
continue
}
// Force option for empty interfaces and nullable types
_, force := tagOptions[ForceOptionName]
// Valuer -> ptr
if isNullableType(srcFieldType.Type) && dstFieldValue.Kind() == reflect.Ptr && force {
v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
if v == nil {
continue
}
valueType := reflect.TypeOf(v)
ptr := reflect.New(valueType)
ptr.Elem().Set(reflect.ValueOf(v))
if valueType.AssignableTo(dstFieldType.Type.Elem()) {
dstFieldValue.Set(ptr)
}
continue
}
// Valuer -> value
if isNullableType(srcFieldType.Type) {
if force {
v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
if v == nil {
continue
}
rv := reflect.ValueOf(v)
if rv.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(rv)
}
}
continue
}
if dstFieldValue.Kind() == reflect.Interface {
if force {
dstFieldValue.Set(srcFieldValue)
}
continue
}
// Ptr -> Value
if srcFieldType.Type.Kind() == reflect.Ptr && !srcFieldValue.IsNil() && dstFieldType.Type.Kind() != reflect.Ptr {
indirect := reflect.Indirect(srcFieldValue)
if indirect.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(indirect)
continue
}
}
// Other types
if srcFieldType.Type.AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(srcFieldValue)
}
}
for _, m := range srcMethodNames {
name, opts := getRelatedField(dst, m)
if name == "" {
continue
}
if _, ok := opts[SkipOptionName]; ok {
continue
}
method := reflect.ValueOf(src).MethodByName(m)
if !method.IsValid() {
return fmt.Errorf("method %s is invalid", m)
}
var (
dstFieldType, _ = dstValue.Type().FieldByName(name)
dstFieldValue = dstValue.FieldByName(name)
_, withContext = opts[ContextOptionName]
_, force = opts[ForceOptionName]
)
args := []reflect.Value{}
if withContext {
args = []reflect.Value{reflect.ValueOf(options.Context)}
}
var (
result = method.Call(args)[0]
resultInterface = result.Interface()
resultValue = reflect.ValueOf(resultInterface)
resultType = resultValue.Type()
)
// Value -> Ptr
if dstFieldValue.Kind() == reflect.Ptr && force {
ptr := reflect.New(resultType)
ptr.Elem().Set(resultValue)
if ptr.Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(ptr)
}
continue
}
// Ptr -> value
if resultValue.Kind() == reflect.Ptr && force {
if resultValue.Elem().Type().AssignableTo(dstFieldType.Type) {
dstFieldValue.Set(resultValue.Elem())
}
continue
}
if resultType.AssignableTo(dstFieldType.Type) && result.IsValid() {
dstFieldValue.Set(result)
}
}
return nil
}
// getTagOptions parses deepcopier tag field and returns options.
func getTagOptions(value string) TagOptions {
options := TagOptions{}
for _, opt := range strings.Split(value, ";") {
o := strings.Split(opt, ":")
// deepcopier:"keyword; without; value;"
if len(o) == 1 {
options[o[0]] = ""
}
// deepcopier:"key:value; anotherkey:anothervalue"
if len(o) == 2 {
options[strings.TrimSpace(o[0])] = strings.TrimSpace(o[1])
}
}
return options
}
// getRelatedField returns first matching field.
func getRelatedField(instance interface{}, name string) (string, TagOptions) {
var (
value = reflect.Indirect(reflect.ValueOf(instance))
fieldName string
tagOptions TagOptions
)
for i := 0; i < value.NumField(); i++ {
var (
vField = value.Field(i)
tField = value.Type().Field(i)
tagOptions = getTagOptions(tField.Tag.Get(TagName))
)
if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
if n, o := getRelatedField(vField.Interface(), name); n != "" {
return n, o
}
}
if v, ok := tagOptions[FieldOptionName]; ok && v == name {
return tField.Name, tagOptions
}
if tField.Name == name {
return tField.Name, tagOptions
}
}
return fieldName, tagOptions
}
// getMethodNames returns instance's method names.
func getMethodNames(instance interface{}) []string {
var methods []string
t := reflect.TypeOf(instance)
for i := 0; i < t.NumMethod(); i++ {
methods = append(methods, t.Method(i).Name)
}
return methods
}
// getFieldNames returns instance's field names.
func getFieldNames(instance interface{}) []string {
var (
fields []string
v = reflect.Indirect(reflect.ValueOf(instance))
t = v.Type()
)
if t.Kind() != reflect.Struct {
return nil
}
for i := 0; i < v.NumField(); i++ {
var (
vField = v.Field(i)
tField = v.Type().Field(i)
)
// Is exportable?
if tField.PkgPath != "" {
continue
}
if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
fields = append(fields, getFieldNames(vField.Interface())...)
continue
}
fields = append(fields, tField.Name)
}
return fields
}
// isNullableType returns true if the given type is a nullable one.
func isNullableType(t reflect.Type) bool {
return t.ConvertibleTo(reflect.TypeOf((*driver.Valuer)(nil)).Elem())
}