class Nanoc::CLI::Commands::Compile::DiffGenerator

Generates diffs for every output file written

Public Class Methods

enable_for?(command_runner) click to toggle source

@see Listener#enable_for?

# File lib/nanoc/cli/commands/compile.rb, line 57
def self.enable_for?(command_runner)
  command_runner.site.config[:enable_output_diff]
end

Public Instance Methods

start() click to toggle source

@see Nanoc::CLI::Commands::Compile::Listener#start

# File lib/nanoc/cli/commands/compile.rb, line 62
def start
  require 'tempfile'
  setup_diffs
  old_contents = {}
  Nanoc::Int::NotificationCenter.on(:will_write_rep) do |rep, path|
    old_contents[rep] = File.file?(path) ? File.read(path) : nil
  end
  Nanoc::Int::NotificationCenter.on(:rep_written) do |rep, path, _is_created, _is_modified|
    unless rep.binary?
      new_contents = File.file?(path) ? File.read(path) : nil
      if old_contents[rep] && new_contents
        generate_diff_for(path, old_contents[rep], new_contents)
      end
      old_contents.delete(rep)
    end
  end
end
stop() click to toggle source

@see Nanoc::CLI::Commands::Compile::Listener#stop

# File lib/nanoc/cli/commands/compile.rb, line 81
def stop
  super
  teardown_diffs
end

Protected Instance Methods

diff_strings(a, b) click to toggle source
# File lib/nanoc/cli/commands/compile.rb, line 114
def diff_strings(a, b)
  require 'open3'

  # Create files
  Tempfile.open('old') do |old_file|
    Tempfile.open('new') do |new_file|
      # Write files
      old_file.write(a)
      old_file.flush
      new_file.write(b)
      new_file.flush

      # Diff
      cmd = ['diff', '-u', old_file.path, new_file.path]
      Open3.popen3(*cmd) do |_stdin, stdout, _stderr|
        result = stdout.read
        return (result == '' ? nil : result)
      end
    end
  end
rescue Errno::ENOENT
  warn 'Failed to run `diff`, so no diff with the previously compiled '               'content will be available.'
  nil
end
generate_diff_for(path, old_content, new_content) click to toggle source
# File lib/nanoc/cli/commands/compile.rb, line 98
def generate_diff_for(path, old_content, new_content)
  return if old_content == new_content

  @diff_threads << Thread.new do
    # Generate diff
    diff = diff_strings(old_content, new_content)
    diff.sub!(/^--- .*/,    '--- ' + path)
    diff.sub!(/^\+\+\+ .*/, '+++ ' + path)

    # Write diff
    @diff_lock.synchronize do
      File.open('output.diff', 'a') { |io| io.write(diff) }
    end
  end
end
setup_diffs() click to toggle source
# File lib/nanoc/cli/commands/compile.rb, line 88
def setup_diffs
  @diff_lock    = Mutex.new
  @diff_threads = []
  FileUtils.rm('output.diff') if File.file?('output.diff')
end
teardown_diffs() click to toggle source
# File lib/nanoc/cli/commands/compile.rb, line 94
def teardown_diffs
  @diff_threads.each(&:join)
end