lib/xcodeproj/project/recursive_diff.rb
class Hash # Computes the recursive difference of two hashes. # # Useful to compare two projects. # # Inspired from 'active_support/core_ext/hash/diff'. # # @example # h1 = { :common => 'value', :changed => 'v1' } # h2 = { :common => 'value', :changed => 'v2', :addition => 'new_value' } # h1.recursive_diff(h2) == { # :changed => { # :self => 'v1', # :other => 'v2' # }, # :addition => { # :self => nil, # :other => 'new_value' # } # } #=> true # # @return [Hash] Returns the recursive difference of a hash. # def recursive_diff(other, self_key = 'self', other_key = 'other') if other.is_a?(Hash) r = {} all_keys = self.keys + other.keys all_keys.each do |key| v1 = self[key] v2 = other[key] diff = v1.recursive_diff(v2, self_key, other_key) r[key] = diff if diff end r unless r == {} else super end end # @return [void] # def recursive_delete(key_to_delete) delete(key_to_delete) self.each do |key, value| case value when Hash value.recursive_delete(key_to_delete) when Array value.each { |v| v.recursive_delete(key_to_delete) if v.is_a?(Hash)} end end end end class Array # @return [Array] # def recursive_diff(other, self_key = 'self', other_key = 'other') if other.is_a?(Array) new_objects_self = (self - other) new_objects_other = (other - self) unmatched_objects_self = [] array_result = [] # Try to match objects to reduce noise new_objects_self.each do |value| if value.is_a?(Hash) other_value = new_objects_other.find do |other| other.is_a?(Hash) && (value['displayName'] == other['displayName']) end if other_value new_objects_other.delete(other_value) match_diff = value.recursive_diff(other_value, self_key, other_key) array_result << { value['displayName'] => match_diff} unless match_diff == {} else unmatched_objects_self << value end end end unless unmatched_objects_self.empty? array_result << { self_key => unmatched_objects_self.map do |v| { v['displayName'] => v } end } end unless new_objects_other.empty? array_result << { other_key => new_objects_other.map do |v| { v['displayName'] => v } end } end array_result unless array_result == [] else super end end end class Object # @return [Hash] # def recursive_diff(other, self_key = 'self', other_key = 'other') { self_key => self, other_key => other } unless self == other end end