From 0554560f9f0f8fca1e5a302e9ac3dd9d3a68562d Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 13 Oct 2024 11:27:33 -0700 Subject: [PATCH] Support multiple $merge in a list --- merge.go | 3 +-- parser.go | 1 + process1.go | 44 ++++++++++++++++++++++----------- process2.go | 2 +- tests/merge-list-multi/a.yaml | 9 +++++++ tests/merge-list-multi/cmd | 1 + tests/merge-list-multi/expected | 9 +++++++ 7 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 tests/merge-list-multi/a.yaml create mode 100644 tests/merge-list-multi/cmd create mode 100644 tests/merge-list-multi/expected diff --git a/merge.go b/merge.go index 33284e6..3f4dea0 100644 --- a/merge.go +++ b/merge.go @@ -91,7 +91,7 @@ func mergeMapMap(dst map[string]any, src map[string]any) (map[string]any, error) return dst, nil } -func mergeList(dst []any, src any) (any, error) { +func mergeList(dst []any, src any) ([]any, error) { switch src2 := src.(type) { case []any: return mergeListList(dst, src2) @@ -171,7 +171,6 @@ func mergeListDelete(obj []any, del any) ([]any, error) { return []any{v}, nil }) - if err != nil { return nil, err } diff --git a/parser.go b/parser.go index f6b6e0a..f208ff4 100644 --- a/parser.go +++ b/parser.go @@ -44,6 +44,7 @@ import ( // Phase 5 // - $"" // - $encode +// - $decode // - $env // - $repeat // - $value diff --git a/process1.go b/process1.go index d0677b8..605983d 100644 --- a/process1.go +++ b/process1.go @@ -82,16 +82,35 @@ func process1MapReplace(obj map[string]any, mergeFrom *Document, mergeFromDocs [ } func process1List(obj []any, mergeFrom *Document, mergeFromDocs []*Document, depth int) (any, error) { - m, obj, err := popListMapValue(obj, "$merge") - if err != nil { - return nil, err + merge := []any{} + + obj, err := filterList(obj, func(v any) ([]any, error) { + v2, ok := v.(map[string]any) + if !ok { + return []any{v}, nil + } + + if len(v2) != 1 { + return []any{v}, nil + } + + found, val, v2 := popMapValue(v2, "$merge") + if found { + merge = append(merge, val) + return nil, nil + } + + return []any{v2}, nil + }) + + for _, m := range merge { + obj, err = process1ListMerge(obj, mergeFrom, mergeFromDocs, m, depth) + if err != nil { + return nil, err + } } - if m != nil { - return process1ListMerge(obj, mergeFrom, mergeFromDocs, m, depth) - } - - m, obj, err = popListMapValue(obj, "$replace") + m, obj, err := popListMapValue(obj, "$replace") if err != nil { return nil, err } @@ -114,18 +133,13 @@ func process1List(obj []any, mergeFrom *Document, mergeFromDocs []*Document, dep }) } -func process1ListMerge(obj []any, mergeFrom *Document, mergeFromDocs []*Document, m any, depth int) (any, error) { +func process1ListMerge(obj []any, mergeFrom *Document, mergeFromDocs []*Document, m any, depth int) ([]any, error) { in, err := get(mergeFrom, mergeFromDocs, m) if err != nil { return nil, err } - next, err := mergeList(obj, in) - if err != nil { - return nil, err - } - - return process1(next, mergeFrom, mergeFromDocs, depth) + return mergeList(obj, in) } func process1ListReplace(obj []any, mergeFrom *Document, mergeFromDocs []*Document, m any, depth int) (any, error) { diff --git a/process2.go b/process2.go index fa4f842..5aae5cd 100644 --- a/process2.go +++ b/process2.go @@ -236,7 +236,7 @@ func process2DecodeString(obj any, mergeFrom *Document, mergeFromDocs []*Documen func process2DecodeStringMap(obj map[string]any, mergeFrom *Document, mergeFromDocs []*Document, v string, depth int) (any, error) { found, val, obj := popMapValue(obj, "$value") if !found { - return nil, fmt.Errorf("$decode: missing $value in %#v (#w)", obj, ErrInvalidType) + return nil, fmt.Errorf("$decode: missing $value in %#v (%w)", obj, ErrInvalidType) } val2, ok := val.(string) diff --git a/tests/merge-list-multi/a.yaml b/tests/merge-list-multi/a.yaml new file mode 100644 index 0000000..b8c5f44 --- /dev/null +++ b/tests/merge-list-multi/a.yaml @@ -0,0 +1,9 @@ +foo: + bar: + - a: 1 + zag: + - c: 3 +zig: + - b: 2 + - $merge: foo.zag + - $merge: foo.bar diff --git a/tests/merge-list-multi/cmd b/tests/merge-list-multi/cmd new file mode 100644 index 0000000..d3724ee --- /dev/null +++ b/tests/merge-list-multi/cmd @@ -0,0 +1 @@ +bkl a.yaml diff --git a/tests/merge-list-multi/expected b/tests/merge-list-multi/expected new file mode 100644 index 0000000..7adf756 --- /dev/null +++ b/tests/merge-list-multi/expected @@ -0,0 +1,9 @@ +foo: + bar: + - a: 1 + zag: + - c: 3 +zig: + - b: 2 + - c: 3 + - a: 1