mirror of
https://github.com/Luzifer/worktime.git
synced 2024-12-22 14:01:17 +00:00
Add missing dependencies
This commit is contained in:
parent
5123d14ec8
commit
6e4191f591
6 changed files with 352 additions and 0 deletions
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
|
@ -8,6 +8,10 @@
|
|||
"Comment": "v1.4.0",
|
||||
"Rev": "d76f718bb2d7d043fdf9dfdc01af03f20047432b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/cnf/structhash",
|
||||
"Rev": "f5315d4d2328a72285a323bf0542c3fb182634b7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/fsnotify/fsnotify",
|
||||
"Comment": "v1.3.1-1-gf12c623",
|
||||
|
|
4
vendor/github.com/cnf/structhash/.travis.yml
generated
vendored
Normal file
4
vendor/github.com/cnf/structhash/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.6
|
||||
- tip
|
6
vendor/github.com/cnf/structhash/LICENSE
generated
vendored
Normal file
6
vendor/github.com/cnf/structhash/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
ISC license
|
||||
Copyright (c) 2014, Frank Rosquin
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
94
vendor/github.com/cnf/structhash/README.md
generated
vendored
Normal file
94
vendor/github.com/cnf/structhash/README.md
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
# structhash [![GoDoc](https://godoc.org/github.com/cnf/structhash?status.svg)](https://godoc.org/github.com/cnf/structhash) [![Build Status](https://travis-ci.org/cnf/structhash.svg?branch=master)](https://travis-ci.org/cnf/structhash)
|
||||
|
||||
structhash is a Go library for generating hash strings of arbitrary data structures.
|
||||
|
||||
## Features
|
||||
|
||||
* fields may be ignored or renamed (like in `json.Marshal`, but using different struct tag)
|
||||
* fields may be versioned
|
||||
* fields order in struct doesn't matter (unlike `json.Marshal`)
|
||||
* nil values are treated equally to zero values
|
||||
|
||||
## Installation
|
||||
|
||||
Standard `go get`:
|
||||
|
||||
```
|
||||
$ go get github.com/cnf/structhash
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For usage and examples see the [Godoc](http://godoc.org/github.com/cnf/structhash).
|
||||
|
||||
## Quick start
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"github.com/cnf/structhash"
|
||||
)
|
||||
|
||||
type S struct {
|
||||
Str string
|
||||
Num int
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := S{"hello", 123}
|
||||
|
||||
hash, err := structhash.Hash(s, 1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(hash)
|
||||
// Prints: v1_41011bfa1a996db6d0b1075981f5aa8f
|
||||
|
||||
fmt.Println(structhash.Version(hash))
|
||||
// Prints: 1
|
||||
|
||||
fmt.Printf("%x\n", structhash.Md5(s, 1))
|
||||
// Prints: 41011bfa1a996db6d0b1075981f5aa8f
|
||||
|
||||
fmt.Printf("%x\n", structhash.Sha1(s, 1))
|
||||
// Prints: 5ff72df7212ce8c55838fb3ec6ad0c019881a772
|
||||
|
||||
fmt.Printf("%x\n", md5.Sum(structhash.Dump(s, 1)))
|
||||
// Prints: 41011bfa1a996db6d0b1075981f5aa8f
|
||||
|
||||
fmt.Printf("%x\n", sha1.Sum(structhash.Dump(s, 1)))
|
||||
// Prints: 5ff72df7212ce8c55838fb3ec6ad0c019881a772
|
||||
}
|
||||
```
|
||||
|
||||
## Struct tags
|
||||
|
||||
structhash supports struct tags in the following forms:
|
||||
|
||||
* `hash:"-"`, or
|
||||
* `hash:"name:{string} version:{number} lastversion:{number}"`
|
||||
|
||||
All fields are optional and may be ommitted. Their semantics is:
|
||||
|
||||
* `-` - ignore field
|
||||
* `name:{string}` - rename field (may be useful when you want to rename field but keep hashes unchanged for backward compatibility)
|
||||
* `version:{number}` - ignore field if version passed to structhash is smaller than given number
|
||||
* `lastversion:{number}` - ignore field if version passed to structhash is greater than given number
|
||||
|
||||
Example:
|
||||
|
||||
```go
|
||||
type MyStruct struct {
|
||||
Ignored string `hash:"-"`
|
||||
Renamed string `hash:"name:OldName version:1"`
|
||||
Legacy string `hash:"version:1 lastversion:2"`
|
||||
}
|
||||
```
|
||||
|
||||
## Nil values
|
||||
|
||||
When hash is calculated, nil pointers, nil slices, and nil maps are treated equally to zero values of corresponding type. E.g., nil pointer to string is equivalent to empty string, and nil slice is equivalent to empty slice.
|
4
vendor/github.com/cnf/structhash/doc.go
generated
vendored
Normal file
4
vendor/github.com/cnf/structhash/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
Package structhash creates hash strings from arbitrary go data structures.
|
||||
*/
|
||||
package structhash
|
240
vendor/github.com/cnf/structhash/structhash.go
generated
vendored
Normal file
240
vendor/github.com/cnf/structhash/structhash.go
generated
vendored
Normal file
|
@ -0,0 +1,240 @@
|
|||
package structhash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Version returns the version of the supplied hash as an integer
|
||||
// or -1 on failure
|
||||
func Version(h string) int {
|
||||
if h == "" {
|
||||
return -1
|
||||
}
|
||||
if h[0] != 'v' {
|
||||
return -1
|
||||
}
|
||||
if spos := strings.IndexRune(h[1:], '_'); spos >= 0 {
|
||||
n, e := strconv.Atoi(h[1 : spos+1])
|
||||
if e != nil {
|
||||
return -1
|
||||
}
|
||||
return n
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Hash takes a data structure and returns a hash string of that data structure
|
||||
// at the version asked.
|
||||
//
|
||||
// This function uses md5 hashing function and default formatter. See also Dump()
|
||||
// function.
|
||||
func Hash(c interface{}, version int) (string, error) {
|
||||
return fmt.Sprintf("v%d_%x", version, Md5(c, version)), nil
|
||||
}
|
||||
|
||||
// Dump takes a data structure and returns its byte representation. This can be
|
||||
// useful if you need to use your own hashing function or formatter.
|
||||
func Dump(c interface{}, version int) []byte {
|
||||
return serialize(c, version)
|
||||
}
|
||||
|
||||
// Md5 takes a data structure and returns its md5 hash.
|
||||
// This is a shorthand for md5.Sum(Dump(c, version)).
|
||||
func Md5(c interface{}, version int) []byte {
|
||||
sum := md5.Sum(Dump(c, version))
|
||||
return sum[:]
|
||||
}
|
||||
|
||||
// Sha1 takes a data structure and returns its sha1 hash.
|
||||
// This is a shorthand for sha1.Sum(Dump(c, version)).
|
||||
func Sha1(c interface{}, version int) []byte {
|
||||
sum := sha1.Sum(Dump(c, version))
|
||||
return sum[:]
|
||||
}
|
||||
|
||||
type item struct {
|
||||
name string
|
||||
value reflect.Value
|
||||
}
|
||||
|
||||
type itemSorter []item
|
||||
|
||||
func (s itemSorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s itemSorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s itemSorter) Less(i, j int) bool {
|
||||
return s[i].name < s[j].name
|
||||
}
|
||||
|
||||
type structFieldFilter func(reflect.StructField) (string, bool)
|
||||
|
||||
func writeValue(buf *bytes.Buffer, val reflect.Value, fltr structFieldFilter) {
|
||||
switch val.Kind() {
|
||||
case reflect.String:
|
||||
buf.WriteByte('"')
|
||||
buf.WriteString(val.String())
|
||||
buf.WriteByte('"')
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
buf.WriteString(strconv.FormatInt(val.Int(), 10))
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
buf.WriteString(strconv.FormatUint(val.Uint(), 10))
|
||||
case reflect.Bool:
|
||||
if val.Bool() {
|
||||
buf.WriteByte('t')
|
||||
} else {
|
||||
buf.WriteByte('f')
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if !val.IsNil() || val.Type().Elem().Kind() == reflect.Struct {
|
||||
writeValue(buf, reflect.Indirect(val), fltr)
|
||||
} else {
|
||||
writeValue(buf, reflect.Zero(val.Type().Elem()), fltr)
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
buf.WriteByte('[')
|
||||
len := val.Len()
|
||||
for i := 0; i < len; i++ {
|
||||
if i != 0 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
writeValue(buf, val.Index(i), fltr)
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
case reflect.Map:
|
||||
mk := val.MapKeys()
|
||||
items := make([]item, len(mk), len(mk))
|
||||
// Get all values
|
||||
for i, _ := range items {
|
||||
items[i].name = formatValue(mk[i], fltr)
|
||||
items[i].value = val.MapIndex(mk[i])
|
||||
}
|
||||
|
||||
// Sort values by key
|
||||
sort.Sort(itemSorter(items))
|
||||
|
||||
buf.WriteByte('[')
|
||||
for i, _ := range items {
|
||||
if i != 0 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
buf.WriteString(items[i].name)
|
||||
buf.WriteByte(':')
|
||||
writeValue(buf, items[i].value, fltr)
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
case reflect.Struct:
|
||||
vtype := val.Type()
|
||||
flen := vtype.NumField()
|
||||
items := make([]item, 0, flen)
|
||||
// Get all fields
|
||||
for i := 0; i < flen; i++ {
|
||||
field := vtype.Field(i)
|
||||
it := item{field.Name, val.Field(i)}
|
||||
if fltr != nil {
|
||||
if name, ok := fltr(field); ok {
|
||||
it.name = name
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
items = append(items, it)
|
||||
}
|
||||
// Sort fields by name
|
||||
sort.Sort(itemSorter(items))
|
||||
|
||||
buf.WriteByte('{')
|
||||
for i, _ := range items {
|
||||
if i != 0 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
buf.WriteString(items[i].name)
|
||||
buf.WriteByte(':')
|
||||
writeValue(buf, items[i].value, fltr)
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
default:
|
||||
buf.WriteString(val.String())
|
||||
}
|
||||
}
|
||||
|
||||
func formatValue(val reflect.Value, fltr structFieldFilter) string {
|
||||
if val.Kind() == reflect.String {
|
||||
return "\"" + val.Interface().(string) + "\""
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
writeValue(&buf, val, fltr)
|
||||
|
||||
return string(buf.Bytes())
|
||||
}
|
||||
|
||||
func filterField(f reflect.StructField, version int) (string, bool) {
|
||||
var err error
|
||||
name := f.Name
|
||||
ver := 0
|
||||
lastver := -1
|
||||
if str := f.Tag.Get("hash"); str != "" {
|
||||
if str == "-" {
|
||||
return "", false
|
||||
}
|
||||
for _, tag := range strings.Split(str, " ") {
|
||||
args := strings.Split(strings.TrimSpace(tag), ":")
|
||||
if len(args) != 2 {
|
||||
return "", false
|
||||
}
|
||||
switch args[0] {
|
||||
case "name":
|
||||
name = args[1]
|
||||
case "version":
|
||||
if ver, err = strconv.Atoi(args[1]); err != nil {
|
||||
return "", false
|
||||
}
|
||||
case "lastversion":
|
||||
if lastver, err = strconv.Atoi(args[1]); err != nil {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if str := f.Tag.Get("lastversion"); str != "" {
|
||||
if lastver, err = strconv.Atoi(str); err != nil {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
if str := f.Tag.Get("version"); str != "" {
|
||||
if ver, err = strconv.Atoi(str); err != nil {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
}
|
||||
if lastver != -1 && lastver < version {
|
||||
return "", false
|
||||
}
|
||||
if ver > version {
|
||||
return "", false
|
||||
}
|
||||
return name, true
|
||||
}
|
||||
|
||||
func serialize(object interface{}, version int) []byte {
|
||||
var buf bytes.Buffer
|
||||
|
||||
writeValue(&buf, reflect.ValueOf(object),
|
||||
func(f reflect.StructField) (string, bool) {
|
||||
return filterField(f, version)
|
||||
})
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
Loading…
Reference in a new issue