Start of matching rule changes
This commit is contained in:
11
document.go
11
document.go
@@ -1,6 +1,7 @@
|
||||
package bkl
|
||||
|
||||
import (
|
||||
"github.com/gopatchy/bkl/polyfill"
|
||||
"go.jetpack.io/typeid"
|
||||
)
|
||||
|
||||
@@ -27,13 +28,17 @@ func (d *Document) AddParents(parents ...*Document) {
|
||||
}
|
||||
|
||||
func (d *Document) AllParents() []*Document {
|
||||
ret := append([]*Document{}, d.Parents...)
|
||||
parents := map[typeid.TypeID]*Document{}
|
||||
|
||||
for _, parent := range d.Parents {
|
||||
ret = append(ret, parent.AllParents()...)
|
||||
parents[parent.ID] = parent
|
||||
|
||||
for _, doc := range parent.AllParents() {
|
||||
parents[doc.ID] = doc
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
return polyfill.MapsValues(parents)
|
||||
}
|
||||
|
||||
func (d *Document) DataAsMap() map[string]any {
|
||||
|
||||
2
justfile
2
justfile
@@ -9,7 +9,7 @@ tidy:
|
||||
test:
|
||||
{{go}} vet ./...
|
||||
# golangci-lint run ./...
|
||||
{{go}} test -race -coverprofile=cover.out -timeout=30s ./...
|
||||
{{go}} test -race -coverprofile=cover.out -timeout=60s ./...
|
||||
{{go}} tool cover -html=cover.out -o=cover.html
|
||||
GOCMD={{go}} ./test
|
||||
|
||||
|
||||
2
merge.go
2
merge.go
@@ -29,7 +29,7 @@ func merge(dst any, src any) (any, error) {
|
||||
|
||||
default:
|
||||
if src == dst {
|
||||
return nil, fmt.Errorf("%v: %w", src, ErrUselessOverride)
|
||||
return nil, fmt.Errorf("%#v: %w", src, ErrUselessOverride)
|
||||
}
|
||||
|
||||
return src, nil
|
||||
|
||||
38
parser.go
38
parser.go
@@ -12,6 +12,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/gopatchy/bkl/polyfill"
|
||||
"go.jetpack.io/typeid"
|
||||
)
|
||||
|
||||
// A Parser reads input documents, merges layers, and generates outputs.
|
||||
@@ -80,7 +81,7 @@ func (p *Parser) SetDebug(debug bool) {
|
||||
// MergeDocument applies the supplied Document to the [Parser]'s current
|
||||
// internal document state using bkl's merge semantics. If expand is true,
|
||||
// documents without $match will append; otherwise this is an error.
|
||||
func (p *Parser) MergeDocument(patch *Document, expand bool) error {
|
||||
func (p *Parser) MergeDocument(patch *Document) error {
|
||||
matched, err := p.mergePatchMatch(patch)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -90,17 +91,31 @@ func (p *Parser) MergeDocument(patch *Document, expand bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if expand {
|
||||
docIDs := map[typeid.TypeID]bool{}
|
||||
|
||||
for _, doc := range p.docs {
|
||||
docIDs[doc.ID] = true
|
||||
}
|
||||
|
||||
for _, parent := range patch.AllParents() {
|
||||
if !docIDs[parent.ID] {
|
||||
// Parent but not in the parser's state
|
||||
continue
|
||||
}
|
||||
|
||||
matched = true
|
||||
|
||||
err = mergeDocs(parent, patch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
p.docs = append(p.docs, patch)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Don't require $match when there's only one document
|
||||
if len(p.docs) == 1 {
|
||||
return mergeDocs(p.docs[0], patch)
|
||||
}
|
||||
|
||||
return fmt.Errorf("%v: %w", patch, ErrMissingMatch)
|
||||
return nil
|
||||
}
|
||||
|
||||
// mergePatchMatch attempts to apply the supplied patch to one or more
|
||||
@@ -172,15 +187,12 @@ func (p *Parser) MergeFileLayers(path string) error {
|
||||
// mergeFile applies an already-parsed file object into the [Parser]'s
|
||||
// document state.
|
||||
func (p *Parser) mergeFile(f *file) error {
|
||||
// First file in an empty parser can append without $match
|
||||
first := len(p.docs) == 0
|
||||
|
||||
p.log("[%s] merging", f)
|
||||
|
||||
for _, doc := range f.docs {
|
||||
p.log("[%s] merging", doc)
|
||||
|
||||
err := p.MergeDocument(doc, first)
|
||||
err := p.MergeDocument(doc)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s:%s]: %w", f, doc, err)
|
||||
}
|
||||
|
||||
@@ -93,12 +93,12 @@ func ExampleParser_MergeDocument() {
|
||||
doc2 := bkl.NewDocumentWithData(map[string]any{"b": 2})
|
||||
doc2.AddParents(doc1)
|
||||
|
||||
err := b.MergeDocument(doc1, true)
|
||||
err := b.MergeDocument(doc1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = b.MergeDocument(doc2, false)
|
||||
err = b.MergeDocument(doc2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -15,10 +15,13 @@ func MapsClone[M ~map[K]V, K comparable, V any](m M) M { //nolint:ireturn
|
||||
}
|
||||
|
||||
func MapsKeys[M ~map[K]V, K comparable, V any](m M) []K { //nolint:ireturn
|
||||
// Added to 1.21 maps then removed again
|
||||
return xmaps.Keys(m)
|
||||
}
|
||||
|
||||
func MapsValues[M ~map[K]V, K comparable, V any](m M) []V { //nolint:ireturn
|
||||
return xmaps.Values(m)
|
||||
}
|
||||
|
||||
func SlicesClone[S ~[]E, E any](s S) S { //nolint:ireturn
|
||||
return slices.Clone(s)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ func MapsKeys[M ~map[K]V, K comparable, V any](m M) []K { //nolint:ireturn
|
||||
return maps.Keys(m)
|
||||
}
|
||||
|
||||
func MapsValues[M ~map[K]V, K comparable, V any](m M) []V { //nolint:ireturn
|
||||
return maps.Values(m)
|
||||
}
|
||||
|
||||
// Copied from go1.21 slices
|
||||
func SlicesClone[S ~[]E, E any](s S) S { //nolint:ireturn
|
||||
if s == nil {
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
$match: {}
|
||||
b: 10
|
||||
c: 3
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
$match: {}
|
||||
b: 2
|
||||
|
||||
Reference in New Issue
Block a user