# class Chef::Util::Diff

### Public Instance Methods

diff(old_file, new_file) click to toggle source

    # File lib/chef/util/diff.rb, line 78
    def diff(old_file, new_file)
      use_tempfile_if_missing(old_file) do |old_file|
        use_tempfile_if_missing(new_file) do |new_file|
          @error = do_diff(old_file, new_file)
        end
      end
    end

for_output() click to toggle source

@todo: to_a, to_s, to_json, inspect defs, accessors for @diff and @error @todo: move coercion to UTF-8 into to_json @todo: replace shellout to diff -u with diff-lcs gem

    # File lib/chef/util/diff.rb, line 53
    def for_output
      # formatted output to a terminal uses arrays of strings and returns error strings
      @diff.nil? ? [ @error ] : @diff
    end

for_reporting() click to toggle source

    # File lib/chef/util/diff.rb, line 58
    def for_reporting
      # caller needs to ensure that new files aren't posted to resource reporting
      return nil if @diff.nil?
      @diff.join("\\n")
    end

udiff(old_file, new_file) click to toggle source

produces a unified-output-format diff with 3 lines of context ChefFS uses udiff() directly

    # File lib/chef/util/diff.rb, line 88
    def udiff(old_file, new_file)
      diff_str = ""
      file_length_difference = 0

      old_data = IO.readlines(old_file).map { |e| e.chomp }
      new_data = IO.readlines(new_file).map { |e| e.chomp }
      diff_data = ::Diff::LCS.diff(old_data, new_data)

      return diff_str if old_data.empty? && new_data.empty?
      return "No differences encountered\n" if diff_data.empty?

      # write diff header (standard unified format)
      ft = File.stat(old_file).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z')
      diff_str << "--- #{old_file}\t#{ft}\n"
      ft = File.stat(new_file).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z')
      diff_str << "+++ #{new_file}\t#{ft}\n"

      # loop over diff hunks. if a hunk overlaps with the last hunk,
      # join them. otherwise, print out the old one.
      old_hunk = hunk = nil
      diff_data.each do |piece|
        begin
          hunk = ::Diff::LCS::Hunk.new(old_data, new_data, piece, 3, file_length_difference)
          file_length_difference = hunk.file_length_difference
          next unless old_hunk
          next if hunk.merge(old_hunk)
          diff_str << old_hunk.diff(:unified) << "\n"
        ensure
          old_hunk = hunk
        end
      end
      diff_str << old_hunk.diff(:unified) << "\n"
      return diff_str
    end

use_tempfile_if_missing(file) { |file| ... } click to toggle source

    # File lib/chef/util/diff.rb, line 64
    def use_tempfile_if_missing(file)
      tempfile = nil
      unless File.exists?(file)
        Chef::Log.debug("file #{file} does not exist to diff against, using empty tempfile")
        tempfile = Tempfile.new("chef-diff")
        file = tempfile.path
      end
      yield file
      unless tempfile.nil?
        tempfile.close
        tempfile.unlink
      end
    end