class Sumodev::Commands::Hooks

Public Instance Methods

build_error_or_warning(type, line, message) click to toggle source

Build a hash that we will use for errors or warnings.

# File lib/sumodev/commands/hooks.rb, line 12
def build_error_or_warning(type, line, message)
  {
    :type => type,
    :line => line,
    :message => message
  }
end
check(*files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 309
def check(*files)
  errors_and_warnings = {}

  # Check the CSS files
  css_files = find_files_by_extension(files, 'css')
  if css_files.any?
    results = check_css_files(css_files)
    errors_and_warnings['CSS'] = results unless results.empty?
  end

  # Check the SCSS files
  scss_files = find_files_by_extension(files, 's(c|a)ss')
  if scss_files.any?
    results = check_scss_files(scss_files)
    errors_and_warnings['SCSS'] = results unless results.empty?
  end

  # Check the Coffee files
  coffee_files = find_files_by_extension(files, 'coffee')
  if coffee_files.any?
    results = check_coffee_files(coffee_files)
    errors_and_warnings['Coffee'] = results unless results.empty?
  end

  # Check the JS files
  js_files = find_files_by_extension(files, 'js')
  if js_files.any?
    results = check_js_files(js_files)
    errors_and_warnings['JS'] = results unless results.empty?
  end

  # Check the php files
  php_files = find_files_by_extension(files, 'php')
  if php_files.any?
    results = check_php_files(php_files)
    errors_and_warnings['PHP'] = results unless results.empty?
  end

  output_results(errors_and_warnings)
end
check_coffee_files(files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 142
def check_coffee_files(files)
  methods = [
    {
      :human_readable_message => "Checking for keywords in Coffee-files",
      :command => "egrep -no 'console\.' %{file}",
      :line_handler => lambda { |line|
        return build_error_or_warning(
          'warning',
          line.scan(/([0-9]*):/)[0][0],
          "Keyword found: " + line.scan(/[0-9]*:(.*)/)[0][0]
        )
      }
    }
  ]

  check_files(files, methods)
end
check_css_files(files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 88
def check_css_files(files)
  methods = [
    {
      :human_readable_message => "Checking for CSS-lint errors",
      :command => "csslint --format=compact %{file}",
      :line_handler => lambda { |line|
        if line.include? "Warning - "
          return build_error_or_warning(
            'warning',
            line.scan(/line\ ([0-9*])/i)[0][0],
            line.scan(/Warning - (.*)/)[0][0]
          )
        end
        if line.include? "Error - "
          return build_error_or_warning(
            'error',
            line.scan(/line\ ([0-9*])/i)[0][0],
            line.scan(/Error - (.*)/)[0][0]
          )
        end
      }
    }
  ]

  check_files(files, methods)
end
check_files(files, methods) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 25
def check_files(files, methods)
  errors_and_warnings = []

  methods.each do |method|
    has_warnings = false
    has_errors = false
    output_before_check(method[:human_readable_message])

    files.each do |file|
      case method[:command].class.to_s
      when "String"
        # if the command is a string we will run it on the CLI
        command = "#{method[:command]}" % {:file => file}
        IO.popen(command) do |f|
          f.read.split("\n").each do |line|
            error_or_warning = method[:line_handler].call(line)
            unless error_or_warning.nil?
              if 'error' == error_or_warning[:type]
                has_errors = true
              elsif 'warning' == error_or_warning[:type]
                has_warnings = true
              end
              error_or_warning[:file] = file
              errors_and_warnings << error_or_warning
            end
          end
        end
      when "Proc"
        # a method is provided so call it.
        error_or_warning = method[:command].call(file)
      else
        raise "Unknown type"
      end
    end

    output_result_after_check(
      method[:human_readable_message],
      has_errors,
      has_warnings
    )
  end

  errors_and_warnings
end
check_for_merge_conflicts(files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 70
def check_for_merge_conflicts(files)
  methods = [
    {
      :human_readable_message => "Checking for merge conflicts",
      :command => "egrep -no '<<<<<<<' %{file}",
      :line_handler => lambda { |line|
        return build_error_or_warning(
          'warning',
          line.scan(/([0-9]*):/)[0][0],
          "Merge conflict found: " + line.scan(/[0-9]*:(.*)/)[0][0]
        )
      }
    }
  ]

  check_files(files, methods)
end
check_js_files(files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 160
def check_js_files(files)
  methods = [
    {
      :human_readable_message => "Checking for js errors",
      :command => "esvalidate --format=junit %{file}",
      :line_handler => lambda { |line|
        if line.include? "<warning "
          return build_error_or_warning(
            'warning',
            line.scan(/Line ([0-9]*):/)[0][0],
            line.scan(/>Line.*: (.*)\(/)[0][0]
          )
        end
        if line.include? "<error "
          return build_error_or_warning(
            'error',
            line.scan(/Line ([0-9]*):/)[0][0],
            line.scan(/>Line.*: (.*)\(/)[0][0]
          )
        end
      }
    },
    {
      :human_readable_message => "Checking for keywords in JS-files",
      :command => "egrep -no 'console\.' %{file}",
      :line_handler => lambda { |line|
        return build_error_or_warning(
          'warning',
          line.scan(/([0-9]*):/)[0][0],
          "Keyword found: " + line.scan(/[0-9]*:(.*)/)[0][0]
        )
      }
    }
  ]

  check_files(files, methods)
end
check_php_files(files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 198
def check_php_files(files)
  methods = [
    {
      :human_readable_message => "Checking for PHP syntax errors",
      :command => "php -l %{file} 2>&1",
      :line_handler => lambda { |line|
        if line.include? "PHP Parse error: "
          return build_error_or_warning(
            'error',
            line.scan(/line ([0-9]*)$/)[0][0],
            line.scan(/:  (.*) in/)[0][0]
          )
        end
      }
    },
    {
      :human_readable_message => "Checking for PHP Coding standards errors",
      :command => "phpcs --standard=PSR2 --extensions=php --encoding=utf8 --report=xml %{file}",
      :line_handler => lambda { |line|
        if line.include? "<warning "
          return build_error_or_warning(
            'warning',
            line.scan(/line="([0-9]*)"/)[0][0],
            line.scan(/>(.*)<\/warning>/)[0][0]
          )
        end
        if line.include? "<error "
          return build_error_or_warning(
            'error',
            line.scan(/line="([0-9]*)"/)[0][0],
            line.scan(/>(.*)<\/error>/)[0][0]
          )
        end
      }
    },
    {
      :human_readable_message => "Checking for keywords in PHP-files",
      :command => "egrep -no '(dump\\(|var_dump\\(|print_r\\(|exit|die|Zend_Debug::)' %{file}",
      :line_handler => lambda { |line|
        return build_error_or_warning(
          'warning',
          line.scan(/([0-9]*):/)[0][0],
          "Keyword found: " + line.scan(/[0-9]*:(.*)/)[0][0]
        )
      }
    }
  ]

  check_files(files, methods)
end
check_scss_files(files) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 115
def check_scss_files(files)
  methods = [
    {
      :human_readable_message => "Checking SCSS lint errors",
      :command => "scss-lint %{file}",
      :line_handler => lambda { |line|
        if line.include? "[W] "
          return build_error_or_warning(
            'warning',
            line.scan(/\:([0-9*])/i)[0][0],
            line.scan(/\[W\] (.*)/)[0][0]
          )
        end
        if line.include? "[E] "
          return build_error_or_warning(
            'error',
            line.scan(/\:([0-9*])/i)[0][0],
            line.scan(/\[E\] (.*)/)[0][0]
          )
        end
      }
    }
  ]

  check_files(files, methods)
end
find_files_by_extension(files, extension) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 7
def find_files_by_extension(files, extension)
  files.select{ |i| i[/\.#{extension}$/] }
end
output_before_check(message) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 20
def output_before_check(message)
  # this has to end with a space so our next output is appended
  say("--> #{message} ")
end
output_result_after_check(message, has_errors, has_warnings) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 249
def output_result_after_check(message, has_errors, has_warnings)
  # as we append 7 characters ourself we should decrease the allowed maximum width.
  say(".".rjust(72 - 7 - message.length, ".") + " ")
  if has_errors
    say("✘", :red)
  elsif has_warnings
    say("⚠", :yellow)
  else
    say("✔", :green)
  end
end
output_results(errors_and_warnings) click to toggle source
# File lib/sumodev/commands/hooks.rb, line 261
def output_results(errors_and_warnings)
  puts "\n"

  if errors_and_warnings.empty?
    say("Atta boy, no errors! 🍺", :green)
    return
  end

  # split into seperate arrays
  errors = []
  warnings = []
  errors_and_warnings.each do |group,items|
    items.each do |error_or_warning|
      if error_or_warning[:type] == "error"
        errors << error_or_warning
      end
      if error_or_warning[:type] == "warning"
        warnings << error_or_warning
      end
    end
  end

  # some encouragement
  if errors.empty? && !warnings.empty?
    say("⚠ Yeah, only warnings!", :yellow)
  end
  if !errors.empty?
    say("✘ Woops, errors! Check them below.", :red)
  end

  # output the warnings and errors
  if !warnings.empty?
    puts "\nWarnings\n--------\n"
    warnings.each do |warning|
      puts "• Warning: %{file}:%{line} - %{message}" % warning
    end
  end

  if !errors.empty?
    puts "\nErrors\n------\n"
    errors.each do |error|
      puts "• Error: %{file}:%{line} - %{message}" % error
    end
  end
end