Skip to content

Commit f418b1f

Browse files
author
Kevin Wiesmüller
committed
add extended remove method for typed values
1 parent fda0dd5 commit f418b1f

File tree

3 files changed

+159
-4
lines changed

3 files changed

+159
-4
lines changed

typed/remove.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ type removingWalker struct {
2323
value *value.Value
2424
schema *schema.Schema
2525
toRemove *fieldpath.Set
26+
shallow bool
2627
}
2728

28-
func removeItemsWithSchema(value *value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef) {
29+
func removeItemsWithSchema(value *value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef, shallow bool) {
2930
w := &removingWalker{
3031
value: value,
3132
schema: schema,
3233
toRemove: toRemove,
34+
shallow: shallow,
3335
}
3436
resolveSchema(schema, typeRef, value, w)
3537
}
@@ -58,7 +60,7 @@ func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
5860
continue
5961
}
6062
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
61-
removeItemsWithSchema(&l.Items[i], subset, w.schema, t.ElementType)
63+
removeItemsWithSchema(&l.Items[i], subset, w.schema, t.ElementType, w.shallow)
6264
}
6365
newItems = append(newItems, l.Items[i])
6466
}
@@ -88,6 +90,13 @@ func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
8890
item := m.Items[i]
8991
pe := fieldpath.PathElement{FieldName: &item.Name}
9092
path, _ := fieldpath.MakePath(pe)
93+
94+
if w.shallow {
95+
if w.toRemove.Has(path) {
96+
continue
97+
}
98+
}
99+
91100
fieldType := t.ElementType
92101
if ft, ok := fieldTypes[item.Name]; ok {
93102
fieldType = ft
@@ -97,7 +106,7 @@ func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
97106
}
98107
}
99108
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
100-
removeItemsWithSchema(&m.Items[i].Value, subset, w.schema, fieldType)
109+
removeItemsWithSchema(&m.Items[i].Value, subset, w.schema, fieldType, w.shallow)
101110
}
102111
newMap.Set(item.Name, m.Items[i].Value)
103112
}

typed/remove_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package typed
2+
3+
import (
4+
"testing"
5+
6+
"sigs.k8s.io/structured-merge-diff/fieldpath"
7+
"sigs.k8s.io/structured-merge-diff/schema"
8+
"sigs.k8s.io/structured-merge-diff/value"
9+
)
10+
11+
func TestRemoveShallowRemovesParents(t *testing.T) {
12+
13+
test, err := value.FromJSON([]byte(`
14+
{
15+
"removeMap": {
16+
"child": "value"
17+
},
18+
"removeList": [
19+
{"child": "value"}
20+
],
21+
"keep": "value",
22+
"keepMap": {
23+
"child": "value"
24+
},
25+
"keepList": [
26+
{"child": "value"}
27+
]
28+
}`))
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
33+
remove := fieldpath.NewSet(
34+
fieldpath.MakePathOrDie("removeMap"),
35+
fieldpath.MakePathOrDie("removeList"),
36+
)
37+
38+
str := schema.String
39+
40+
atom := schema.Atom{
41+
Map: &schema.Map{
42+
Fields: []schema.StructField{
43+
schema.StructField{
44+
Name: "removeMap",
45+
Type: schema.TypeRef{
46+
Inlined: schema.Atom{Map: &schema.Map{
47+
Fields: []schema.StructField{
48+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
49+
},
50+
},
51+
},
52+
schema.StructField{
53+
Name: "removeList",
54+
Type: schema.TypeRef{
55+
Inlined: schema.Atom{
56+
List: &schema.List{
57+
ElementRelationship: schema.Separable,
58+
ElementType: schema.TypeRef{
59+
Inlined: schema.Atom{Map: &schema.Map{
60+
Fields: []schema.StructField{
61+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
62+
},
63+
},
64+
},
65+
},
66+
},
67+
},
68+
schema.StructField{
69+
Name: "keep",
70+
Type: schema.TypeRef{
71+
Inlined: schema.Atom{
72+
Scalar: &str,
73+
},
74+
},
75+
},
76+
schema.StructField{
77+
Name: "keepMap",
78+
Type: schema.TypeRef{
79+
Inlined: schema.Atom{Map: &schema.Map{
80+
Fields: []schema.StructField{
81+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
82+
},
83+
},
84+
},
85+
schema.StructField{
86+
Name: "keepList",
87+
Type: schema.TypeRef{
88+
Inlined: schema.Atom{
89+
List: &schema.List{
90+
ElementRelationship: schema.Separable,
91+
ElementType: schema.TypeRef{
92+
Inlined: schema.Atom{Map: &schema.Map{
93+
Fields: []schema.StructField{
94+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
95+
},
96+
},
97+
},
98+
},
99+
},
100+
},
101+
},
102+
},
103+
}
104+
105+
typeDef := schema.TypeDef{
106+
Name: "test",
107+
Atom: atom,
108+
}
109+
110+
typeRef := schema.TypeRef{
111+
Inlined: atom,
112+
}
113+
114+
schema := &schema.Schema{
115+
Types: []schema.TypeDef{
116+
typeDef,
117+
},
118+
}
119+
120+
removeItemsWithSchema(&test, remove, schema, typeRef, false)
121+
122+
expect, err := value.FromJSON([]byte(`{"keep": "value", "keepMap": {"child": "value"}, "keepList": [{"child": "value"}], "removeMap": {"child":"value"}, "removeList": [{"child": "value"}]}`))
123+
if err != nil {
124+
t.Fatal(err)
125+
}
126+
if !test.Equals(expect) {
127+
t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", test.String(), expect.String())
128+
}
129+
130+
removeItemsWithSchema(&test, remove, schema, typeRef, true)
131+
132+
expect, err = value.FromJSON([]byte(`{"keep": "value", "keepMap": {"child": "value"}, "keepList": [{"child": "value"}]}`))
133+
if err != nil {
134+
t.Fatal(err)
135+
}
136+
if !test.Equals(expect) {
137+
t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", test.String(), expect.String())
138+
}
139+
}

typed/typed.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,14 @@ func (tv TypedValue) Compare(rhs *TypedValue) (c *Comparison, err error) {
144144
// RemoveItems removes each provided list or map item from the value.
145145
func (tv TypedValue) RemoveItems(items *fieldpath.Set) *TypedValue {
146146
tv.value, _ = value.FromUnstructured(tv.value.ToUnstructured(true))
147-
removeItemsWithSchema(&tv.value, items, tv.schema, tv.typeRef)
147+
removeItemsWithSchema(&tv.value, items, tv.schema, tv.typeRef, false)
148+
return &tv
149+
}
150+
151+
// Remove removes each provided path from the value.
152+
func (tv TypedValue) Remove(paths *fieldpath.Set) *TypedValue {
153+
tv.value, _ = value.FromUnstructured(tv.value.ToUnstructured(true))
154+
removeItemsWithSchema(&tv.value, paths, tv.schema, tv.typeRef, true)
148155
return &tv
149156
}
150157

0 commit comments

Comments
 (0)