// mustContainKeys checks that a bucket contains a given set of keys. func mustContainKeys(b *bolt.Bucket, m map[string]string) { found := make(map[string]string) b.ForEach(func(k, _ []byte) error { found[string(k)] = "" return nil }) // Check for keys found in bucket that shouldn't be there. var keys []string for k, _ := range found { if _, ok := m[string(k)]; !ok { keys = append(keys, k) } } if len(keys) > 0 { sort.Strings(keys) panic(fmt.Sprintf("keys found(%d): %s", len(keys), strings.Join(keys, ","))) } // Check for keys not found in bucket that should be there. for k, _ := range m { if _, ok := found[string(k)]; !ok { keys = append(keys, k) } } if len(keys) > 0 { sort.Strings(keys) panic(fmt.Sprintf("keys not found(%d): %s", len(keys), strings.Join(keys, ","))) } }
func exportBucket(b *bolt.Bucket) (*rawMessage, error) { // Encode individual key/value pairs into raw messages. var children = make([]*rawMessage, 0) err := b.ForEach(func(k, v []byte) error { var err error // If there is no value then it is a bucket. if v == nil { child, err := exportBucket(b.Bucket(k)) if err != nil { return fmt.Errorf("bucket: %s", err) } child.Key = k children = append(children, child) return nil } // Otherwise it's a regular key. var child = &rawMessage{Key: k} if child.Value, err = json.Marshal(v); err != nil { return fmt.Errorf("value: %s", err) } children = append(children, child) return nil }) if err != nil { return nil, err } // Encode bucket into a raw message. var root = rawMessage{Type: "bucket"} if root.Value, err = json.Marshal(children); err != nil { return nil, fmt.Errorf("children: %s", err) } return &root, nil }
func importBucket(b *bolt.Bucket, children []*rawMessage) error { // Decode each message into a key/value pair. for _, child := range children { // Bucket messages are handled recursively. if child.Type == "bucket" { // Create the bucket if it doesn't exist. subbucket, err := b.CreateBucketIfNotExists(child.Key) if err != nil { return fmt.Errorf("create bucket: %s", err) } // Decode child messages. var subchildren []*rawMessage if err := json.Unmarshal(child.Value, &subchildren); err != nil { return fmt.Errorf("decode children: %s", err) } // Import subbucket. if err := importBucket(subbucket, subchildren); err != nil { return fmt.Errorf("import bucket: %s", err) } continue } // Non-bucket values are decoded from base64. var value []byte if err := json.Unmarshal(child.Value, &value); err != nil { return fmt.Errorf("decode value: %s", err) } // Insert key/value into bucket. if err := b.Put(child.Key, value); err != nil { return fmt.Errorf("put: %s", err) } } return nil }