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