    # File lib/chef/mixin/deep_merge.rb, line 93
          def self.deep_merge!(source, dest, options = {})
            # turn on this line for stdout debugging text
            merge_debug = options[:merge_debug] || false
            overwrite_unmergeable = !options[:preserve_unmergeables]
            knockout_prefix = options[:knockout_prefix] || nil
            raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!" if knockout_prefix == ""
            raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!" if knockout_prefix && !overwrite_unmergeable
            # if present: we will split and join arrays on this char before merging
            array_split_char = options[:unpack_arrays] || false
            # request that we sort together any arrays when they are merged
            sort_merged_arrays = options[:sort_merged_arrays] || false
            di = options[:debug_indent] || ''
            # do nothing if source is nil
            return dest if source.nil?
            # if dest doesn't exist, then simply copy source to it
            if dest.nil? && overwrite_unmergeable
              dest = source; return dest
            end

            puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
            if source.kind_of?(Hash)
              puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
              source.each do |src_key, src_value|
                if dest.kind_of?(Hash)
                  puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
                  if dest[src_key]
                    puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
                    dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + '  '))
                  else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
                    puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
                    # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
                    begin
                      src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
                    rescue TypeError
                      src_dup = src_value
                    end
                    dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + '  '))
                  end
                else # dest isn't a hash, so we overwrite it completely (if permitted)
                  if overwrite_unmergeable
                    puts "#{di}  overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over->  #{dest.inspect}" if merge_debug
                    dest = overwrite_unmergeables(source, dest, options)
                  end
                end
              end
            elsif source.kind_of?(Array)
              puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
              # if we are instructed, join/split any source arrays before processing
              if array_split_char
                puts "#{di} split/join on source: #{source.inspect}" if merge_debug
                source = source.join(array_split_char).split(array_split_char)
                if dest.kind_of?(Array)
                  dest = dest.join(array_split_char).split(array_split_char)
                end
              end
              # if there's a naked knockout_prefix in source, that means we are to truncate dest
              if source.index(knockout_prefix)
                dest = clear_or_nil(dest); source.delete(knockout_prefix)
              end
              if dest.kind_of?(Array)
                if knockout_prefix
                  print "#{di} knocking out: " if merge_debug
                  # remove knockout prefix items from both source and dest
                  source.delete_if do |ko_item|
                    retval = false
                    item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
                    if item != ko_item
                      print "#{ko_item} - " if merge_debug
                      dest.delete(item)
                      dest.delete(ko_item)
                      retval = true
                    end
                    retval
                  end
                  puts if merge_debug
                end
                puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
                dest = dest | source
                dest.sort! if sort_merged_arrays
              elsif overwrite_unmergeable
                puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
                dest = overwrite_unmergeables(source, dest, options)
              end
            else # src_hash is not an array or hash, so we'll have to overwrite dest
              puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
              dest = overwrite_unmergeables(source, dest, options)
            end
            puts "#{di}Returning #{dest.inspect}" if merge_debug
            dest
          end