Skip to content

Commit 8fff187

Browse files
authored
Merge pull request #161 from kwiesmueller/ignore-fields
Add ignored fields to update
2 parents 621c035 + 02d431a commit 8fff187

File tree

9 files changed

+608
-8
lines changed

9 files changed

+608
-8
lines changed

fieldpath/set.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ func (s *Set) Difference(s2 *Set) *Set {
9494
}
9595
}
9696

97+
// RecursiveDifference returns a Set containing elements which:
98+
// * appear in s
99+
// * do not appear in s2
100+
//
101+
// Compared to a regular difference,
102+
// this removes every field **and its children** from s that is contained in s2.
103+
//
104+
// For example, with s containing `a.b.c` and s2 containing `a.b`,
105+
// a RecursiveDifference will result in `a`, as the entire node `a.b` gets removed.
106+
func (s *Set) RecursiveDifference(s2 *Set) *Set {
107+
return &Set{
108+
Members: *s.Members.Difference(&s2.Members),
109+
Children: *s.Children.RecursiveDifference(s2),
110+
}
111+
}
112+
97113
// Size returns the number of members of the set.
98114
func (s *Set) Size() int {
99115
return s.Members.Size() + s.Children.Size()
@@ -333,6 +349,48 @@ func (s *SetNodeMap) Difference(s2 *Set) *SetNodeMap {
333349
return out
334350
}
335351

352+
// RecursiveDifference returns a SetNodeMap with members that appear in s but not in s2.
353+
//
354+
// Compared to a regular difference,
355+
// this removes every field **and its children** from s that is contained in s2.
356+
//
357+
// For example, with s containing `a.b.c` and s2 containing `a.b`,
358+
// a RecursiveDifference will result in `a`, as the entire node `a.b` gets removed.
359+
func (s *SetNodeMap) RecursiveDifference(s2 *Set) *SetNodeMap {
360+
out := &SetNodeMap{}
361+
362+
i, j := 0, 0
363+
for i < len(s.members) && j < len(s2.Children.members) {
364+
if s.members[i].pathElement.Less(s2.Children.members[j].pathElement) {
365+
if !s2.Members.Has(s.members[i].pathElement) {
366+
out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set})
367+
}
368+
i++
369+
} else {
370+
if !s2.Children.members[j].pathElement.Less(s.members[i].pathElement) {
371+
if !s2.Members.Has(s.members[i].pathElement) {
372+
diff := s.members[i].set.RecursiveDifference(s2.Children.members[j].set)
373+
if !diff.Empty() {
374+
out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: diff})
375+
}
376+
}
377+
i++
378+
}
379+
j++
380+
}
381+
}
382+
383+
if i < len(s.members) {
384+
for _, c := range s.members[i:] {
385+
if !s2.Members.Has(c.pathElement) {
386+
out.members = append(out.members, c)
387+
}
388+
}
389+
}
390+
391+
return out
392+
}
393+
336394
// Iterate calls f for each PathElement in the set.
337395
func (s *SetNodeMap) Iterate(f func(PathElement)) {
338396
for _, n := range s.members {

fieldpath/set_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ func BenchmarkFieldSet(b *testing.B) {
131131
randOperand().Difference(randOperand())
132132
}
133133
})
134+
b.Run(fmt.Sprintf("recursive-difference-%v", here.size), func(b *testing.B) {
135+
b.ReportAllocs()
136+
for i := 0; i < b.N; i++ {
137+
randOperand().RecursiveDifference(randOperand())
138+
}
139+
})
134140
}
135141
}
136142

@@ -447,6 +453,94 @@ func TestSetIntersectionDifference(t *testing.T) {
447453
})
448454
}
449455

456+
func TestSetDifference(t *testing.T) {
457+
table := []struct {
458+
name string
459+
a *Set
460+
b *Set
461+
expectDifference *Set
462+
expectRecursiveDifference *Set
463+
}{
464+
{
465+
name: "removes simple path",
466+
a: NewSet(MakePathOrDie("a")),
467+
b: NewSet(MakePathOrDie("a")),
468+
expectDifference: NewSet(),
469+
expectRecursiveDifference: NewSet(),
470+
},
471+
{
472+
name: "removes direct path",
473+
a: NewSet(MakePathOrDie("a", "b", "c")),
474+
b: NewSet(MakePathOrDie("a", "b", "c")),
475+
expectDifference: NewSet(),
476+
expectRecursiveDifference: NewSet(),
477+
},
478+
{
479+
name: "only removes matching child",
480+
a: NewSet(
481+
MakePathOrDie("a", "b", "c"),
482+
MakePathOrDie("b", "b", "c"),
483+
),
484+
b: NewSet(MakePathOrDie("a", "b", "c")),
485+
expectDifference: NewSet(MakePathOrDie("b", "b", "c")),
486+
expectRecursiveDifference: NewSet(MakePathOrDie("b", "b", "c")),
487+
},
488+
{
489+
name: "does not remove parent of specific path",
490+
a: NewSet(
491+
MakePathOrDie("a"),
492+
),
493+
b: NewSet(MakePathOrDie("a", "aa")),
494+
expectDifference: NewSet(MakePathOrDie("a")),
495+
expectRecursiveDifference: NewSet(MakePathOrDie("a")),
496+
},
497+
{
498+
name: "RecursiveDifference removes nested path",
499+
a: NewSet(MakePathOrDie("a", "b", "c")),
500+
b: NewSet(MakePathOrDie("a")),
501+
expectDifference: NewSet(MakePathOrDie("a", "b", "c")),
502+
expectRecursiveDifference: NewSet(),
503+
},
504+
{
505+
name: "RecursiveDifference only removes nested path for matching children",
506+
a: NewSet(
507+
MakePathOrDie("a", "aa", "aab"),
508+
MakePathOrDie("a", "ab", "aba"),
509+
),
510+
b: NewSet(MakePathOrDie("a", "aa")),
511+
expectDifference: NewSet(
512+
MakePathOrDie("a", "aa", "aab"),
513+
MakePathOrDie("a", "ab", "aba"),
514+
),
515+
expectRecursiveDifference: NewSet(MakePathOrDie("a", "ab", "aba")),
516+
},
517+
{
518+
name: "RecursiveDifference removes all matching children",
519+
a: NewSet(
520+
MakePathOrDie("a", "aa", "aab"),
521+
MakePathOrDie("a", "ab", "aba"),
522+
),
523+
b: NewSet(MakePathOrDie("a")),
524+
expectDifference: NewSet(
525+
MakePathOrDie("a", "aa", "aab"),
526+
MakePathOrDie("a", "ab", "aba"),
527+
),
528+
expectRecursiveDifference: NewSet(),
529+
},
530+
}
531+
532+
for _, c := range table {
533+
t.Run(c.name, func(t *testing.T) {
534+
if result := c.a.Difference(c.b); !result.Equals(c.expectDifference) {
535+
t.Fatalf("Difference expected: \n%v\n, got: \n%v\n", c.expectDifference, result)
536+
}
537+
if result := c.a.RecursiveDifference(c.b); !result.Equals(c.expectRecursiveDifference) {
538+
t.Fatalf("RecursiveDifference expected: \n%v\n, got: \n%v\n", c.expectRecursiveDifference, result)
539+
}
540+
})
541+
}
542+
}
543+
450544
func TestSetNodeMapIterate(t *testing.T) {
451545
set := &SetNodeMap{}
452546
toAdd := 5

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/json-iterator/go v1.1.6
88
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
99
github.com/modern-go/reflect2 v1.0.1 // indirect
10+
github.com/stretchr/testify v1.3.0 // indirect
1011
)
1112

1213
go 1.13

go.sum

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,4 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
1717
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1818
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
1919
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
20-
sigs.k8s.io/structured-merge-diff v1.0.1 h1:LOs1LZWMsz1xs77Phr/pkB4LFaavH7IVq/3+WTN9XTA=
21-
sigs.k8s.io/structured-merge-diff v1.0.1/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
20+
sigs.k8s.io/structured-merge-diff v1.0.2 h1:WiMoyniAVAYm03w+ImfF9IE2G23GLR/SwDnQyaNZvPk=

internal/fixture/state.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ type TestCase struct {
405405
Managed fieldpath.ManagedFields
406406
// Set to true if the test case needs the union behavior enabled.
407407
RequiresUnions bool
408+
// IgnoredFields containing the set to ignore for every version
409+
IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set
408410
}
409411

410412
// Test runs the test-case using the given parser and a dummy converter.
@@ -436,7 +438,7 @@ func (tc TestCase) PreprocessOperations(parser Parser) error {
436438
// actually passes..
437439
func (tc TestCase) BenchWithConverter(parser Parser, converter merge.Converter) error {
438440
state := State{
439-
Updater: &merge.Updater{Converter: converter},
441+
Updater: &merge.Updater{Converter: converter, IgnoredFields: tc.IgnoredFields},
440442
Parser: parser,
441443
}
442444
if tc.RequiresUnions {
@@ -456,7 +458,7 @@ func (tc TestCase) BenchWithConverter(parser Parser, converter merge.Converter)
456458
// TestWithConverter runs the test-case using the given parser and converter.
457459
func (tc TestCase) TestWithConverter(parser Parser, converter merge.Converter) error {
458460
state := State{
459-
Updater: &merge.Updater{Converter: converter},
461+
Updater: &merge.Updater{Converter: converter, IgnoredFields: tc.IgnoredFields},
460462
Parser: parser,
461463
}
462464
if tc.RequiresUnions {

0 commit comments

Comments
 (0)