diff --git a/README.md b/README.md index 4519a8b..b20881a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![GoDoc](https://godoc.org/github.com/romnnn/flatbson?status.svg)](https://godoc.org/github.com/romnnn/flatbson) [![Test Coverage](https://codecov.io/gh/romnnn/flatbson/branch/master/graph/badge.svg)](https://codecov.io/gh/romnnn/flatbson) [![Release](https://img.shields.io/github/release/romnnn/flatbson)](https://github.com/romnnn/flatbson/releases/latest) -Your description goes here... +Go package for flattening bson documents. @@ -15,6 +15,28 @@ Your description goes here... import "github.com/romnnn/flatbson" ``` +Example: +```golang +import ( + "fmt" + "github.com/romnnn/flatbson" + "go.mongodb.org/mongo-driver/bson" +) + +func main() { + input := bson.D{ + {"user", bson.D{{"email", "test"}}}, + {"metadata", bson.D{{"city", bson.D{{"name", "Berlin"}}}}}, + } + // Flatten the document + flattened, err := flatbson.Flattened(input, ".") + if err != nil { + panic(err) + } + fmt.Println(flattened) +} +``` + For more examples, see `examples/`. diff --git a/examples/example1/example1.go b/examples/example1/example1.go index 5514f4e..a9d4282 100644 --- a/examples/example1/example1.go +++ b/examples/example1/example1.go @@ -1,15 +1,34 @@ package main import ( - "fmt" + "log" + "sort" "github.com/romnnn/flatbson" + "go.mongodb.org/mongo-driver/bson" ) -func run() string { - return flatbson.Shout("This is an example") +func getLongestKey() string { + input := bson.D{ + {Key: "user", Value: bson.D{{Key: "email", Value: "test"}}}, + {Key: "metadata", Value: bson.D{{Key: "city", Value: bson.D{{Key: "name", Value: "Berlin"}}}}}, + } + // Flatten the document + flattened, err := flatbson.Flattened(input, ".") + if err != nil { + log.Fatalf("Failed to flatten: %v", err) + } + log.Printf("Flattened: %v\n", flattened) + + // Get the longest key + keys := make([]string, 0, len(flattened)) + for k := range flattened.Map() { + keys = append(keys, k) + } + sort.Sort(sort.StringSlice(keys)) + return keys[0] } func main() { - fmt.Println(run()) + log.Println(getLongestKey()) } diff --git a/examples/example1/example1_test.go b/examples/example1/example1_test.go index 504e383..2ff7075 100644 --- a/examples/example1/example1_test.go +++ b/examples/example1/example1_test.go @@ -5,8 +5,8 @@ import ( ) func TestCli(t *testing.T) { - out := run() - expected := "This is an example!" + out := getLongestKey() + expected := "metadata.city.name" if out != expected { t.Errorf("Got %s but expected %s", out, expected) } diff --git a/flatbson.go b/flatbson.go index a112671..d98377d 100644 --- a/flatbson.go +++ b/flatbson.go @@ -1,9 +1,94 @@ package flatbson +import ( + "fmt" + "reflect" + "strconv" + + "go.mongodb.org/mongo-driver/bson" +) + // Version is incremented using bump2version const Version = "0.0.1" -// Shout returns the input message with an exclamation mark -func Shout(s string) string { - return s + "!" +var defaultSeparator = "." + +// Flattener represents flattening options +type Flattener struct { + FlattenSlices bool + Separator *string + flattened *bson.D +} + +func (f *Flattener) flatten(input interface{}, lkey string) error { + var err error + var inputMap bson.D + switch input.(type) { + case bson.D: + inputMap = input.(bson.D) + case bson.E: + inputMap = bson.D{input.(bson.E)} + case bson.M: + for k, v := range input.(bson.M) { + inputMap = append(inputMap, bson.E{Key: k, Value: v}) + } + default: + return fmt.Errorf("Cannot flatten %v of type %v", input, reflect.TypeOf(input)) + } + for i := 0; i < len(inputMap); i++ { + // for rkey, value := range inputMap { + rkey := inputMap[i].Key + value := inputMap[i].Value + key := lkey + rkey + // Check for nested document + if nested, ok := value.(bson.D); ok { + err = f.flatten(nested, key+*f.Separator) + } else if nested, ok := value.(bson.M); ok { + err = f.flatten(nested, key+*f.Separator) + } else if nested, ok := value.(bson.E); ok { + err = f.flatten(nested, key+*f.Separator) + } else if nested, ok := value.(bson.A); ok && f.FlattenSlices { + // Convert slice to map using indices as keys + mapped := bson.D{} + for i, v := range nested { + mapped = append(mapped, bson.E{Key: strconv.Itoa(i), Value: v}) + } + err = f.flatten(mapped, key+*f.Separator) + } else { + // Add the value + *f.flattened = append(*f.flattened, bson.E{Key: key, Value: value}) + } + } + return err +} + +// Flatten flattens a bson D or M document +func (f *Flattener) Flatten(input interface{}, flattened *bson.D) error { + f.flattened = flattened + if f.Separator == nil { + f.Separator = &defaultSeparator + } + return f.flatten(input, "") +} + +// Flattened returns a new, flattened bson.D from a bson D or M document +func (f *Flattener) Flattened(input interface{}) (bson.D, error) { + var flattened bson.D + err := f.Flatten(input, &flattened) + return flattened, err +} + +// Flatten flattens a bson D or M document +func Flatten(input interface{}, flattened *bson.D, separator string) error { + f := &Flattener{ + Separator: &separator, + } + return f.Flatten(input, flattened) +} + +// Flattened returns a new, flattened bson.D from a bson D or M document +func Flattened(input interface{}, separator string) (bson.D, error) { + var flattened bson.D + err := Flatten(input, &flattened, separator) + return flattened, err } diff --git a/flatbson_test.go b/flatbson_test.go index f7149f7..f3a5ad9 100644 --- a/flatbson_test.go +++ b/flatbson_test.go @@ -1,12 +1,70 @@ package flatbson -import "testing" +import ( + "testing" -func TestShout(t *testing.T) { - if Shout("Test") != "Test!" { - t.Errorf("Got %s but want \"Test!\"", Shout("Test")) + "github.com/romnnn/deepequal" + "go.mongodb.org/mongo-driver/bson" +) + +func TestFlatten(t *testing.T) { + input := bson.D{ + {Key: "user", Value: bson.D{ + {Key: "email", Value: "test"}, + {Key: "list", Value: bson.A{"a0", bson.M{"a1": bson.E{Key: "will be", Value: "flattened"}}, "a2"}}, + }}, + } + expected := bson.D{ + {Key: "user.email", Value: "test"}, + {Key: "user.list", Value: bson.A{"a0", bson.M{"a1": bson.E{Key: "will be", Value: "flattened"}}, "a2"}}, + } + flattened, err := Flattened(input, ".") + if err != nil { + t.Errorf("Failed to flatten: %v", err) + } + if equal, err := deepequal.DeepEqual(flattened, expected); err != nil || !equal { + t.Errorf("\nGot: %v\nWant %v\nError: %v", flattened, expected, err) + } +} + +func TestFlattenWithSlices(t *testing.T) { + input := bson.D{ + {Key: "user", Value: bson.D{ + {Key: "email", Value: "test"}, + {Key: "list", Value: bson.A{"a0", bson.D{{Key: "a1", Value: bson.E{Key: "will be", Value: "flattened"}}}, "a2"}}, + }}, + } + expected := bson.D{ + {Key: "user.email", Value: "test"}, + {Key: "user.list.0", Value: "a0"}, + {Key: "user.list.1.a1.will be", Value: "flattened"}, + {Key: "user.list.2", Value: "a2"}, + } + f := &Flattener{FlattenSlices: true} + flattened, err := f.Flattened(input) + if err != nil { + t.Errorf("Failed to flatten: %v", err) + } + if equal, err := deepequal.DeepEqual(flattened, expected); err != nil || !equal { + t.Errorf("\nGot: %v\nWant %v\nError: %v", flattened, expected, err) + } +} + +func TestSeparators(t *testing.T) { + input := bson.D{ + {Key: "user", Value: bson.D{{Key: "email", Value: "test"}}}, + } + tests := map[string]bson.D{ + ".": bson.D{{Key: "user.email", Value: "test"}}, + " ": bson.D{{Key: "user email", Value: "test"}}, } - if Shout("") != "!" { - t.Errorf("Got %s but want \"!\"", Shout("")) + for sep, expected := range tests { + flattened, err := Flattened(input, sep) + if err != nil { + t.Errorf("Failed to flatten: %v", err) + } + if equal, err := deepequal.DeepEqual(flattened, expected); err != nil || !equal { + t.Errorf("\nGot: %v\nWant %v\nError: %v", flattened, expected, err) + } } } diff --git a/go.mod b/go.mod index c29fb7b..aa8338f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,9 @@ module github.com/romnnn/flatbson go 1.13 + +require ( + github.com/romnnn/deepequal v0.0.0-20200304153056-ea9233e420e6 + go.mongodb.org/mongo-driver v1.3.2 + gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e46b884 --- /dev/null +++ b/go.sum @@ -0,0 +1,98 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/romnnn/deepequal v0.0.0-20200304153056-ea9233e420e6 h1:7v41wDR0Ntr347K9vYzBRf5T6wLUPcGdHxWoO2rPRQA= +github.com/romnnn/deepequal v0.0.0-20200304153056-ea9233e420e6/go.mod h1:FaE/gNsr9h7pEy9uz/vcPJ2Qp/fdQYNk8ZOJdax/TwE= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +go.mongodb.org/mongo-driver v1.3.2 h1:IYppNjEV/C+/3VPbhHVxQ4t04eVW0cLp0/pNdW++6Ug= +go.mongodb.org/mongo-driver v1.3.2/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=