@@ -183,6 +183,62 @@ def list_merge(last_applied, actual, desired, position):
183
183
return desired
184
184
185
185
186
+ def recursive_list_diff (list1 , list2 , position = None ):
187
+ result = (list (), list ())
188
+ if position in STRATEGIC_MERGE_PATCH_KEYS :
189
+ patch_merge_key = STRATEGIC_MERGE_PATCH_KEYS [position ]
190
+ dict1 = list_to_dict (list1 , patch_merge_key , position )
191
+ dict2 = list_to_dict (list2 , patch_merge_key , position )
192
+ dict1_keys = set (dict1 .keys ())
193
+ dict2_keys = set (dict2 .keys ())
194
+ for key in dict1_keys - dict2_keys :
195
+ result [0 ].append (dict1 [key ])
196
+ for key in dict2_keys - dict1_keys :
197
+ result [1 ].append (dict2 [key ])
198
+ for key in dict1_keys & dict2_keys :
199
+ diff = recursive_diff (dict1 [key ], dict2 [key ], position )
200
+ if diff :
201
+ # reinsert patch merge key to relate changes in other keys to
202
+ # a specific list element
203
+ diff [0 ].update ({patch_merge_key : dict1 [key ][patch_merge_key ]})
204
+ diff [1 ].update ({patch_merge_key : dict2 [key ][patch_merge_key ]})
205
+ result [0 ].append (diff [0 ])
206
+ result [1 ].append (diff [1 ])
207
+ if result [0 ] or result [1 ]:
208
+ return result
209
+ elif list1 != list2 :
210
+ return (list1 , list2 )
211
+ return None
212
+
213
+
214
+ def recursive_diff (dict1 , dict2 , position = None ):
215
+ if not position :
216
+ if 'kind' in dict1 and dict1 .get ('kind' ) == dict2 .get ('kind' ):
217
+ position = dict1 ['kind' ]
218
+ left = dict ((k , v ) for (k , v ) in dict1 .items () if k not in dict2 )
219
+ right = dict ((k , v ) for (k , v ) in dict2 .items () if k not in dict1 )
220
+ for k in (set (dict1 .keys ()) & set (dict2 .keys ())):
221
+ if position :
222
+ this_position = "%s.%s" % (position , k )
223
+ if isinstance (dict1 [k ], dict ) and isinstance (dict2 [k ], dict ):
224
+ result = recursive_diff (dict1 [k ], dict2 [k ], this_position )
225
+ if result :
226
+ left [k ] = result [0 ]
227
+ right [k ] = result [1 ]
228
+ elif isinstance (dict1 [k ], list ) and isinstance (dict2 [k ], list ):
229
+ result = recursive_list_diff (dict1 [k ], dict2 [k ], this_position )
230
+ if result :
231
+ left [k ] = result [0 ]
232
+ right [k ] = result [1 ]
233
+ elif dict1 [k ] != dict2 [k ]:
234
+ left [k ] = dict1 [k ]
235
+ right [k ] = dict2 [k ]
236
+ if left or right :
237
+ return left , right
238
+ else :
239
+ return None
240
+
241
+
186
242
def get_deletions (last_applied , desired ):
187
243
patch = {}
188
244
for k , last_applied_value in last_applied .items ():
0 commit comments