lib/quality/rake/task.rb in quality-0.2.12 vs lib/quality/rake/task.rb in quality-1.0.0

- old
+ new

@@ -29,26 +29,62 @@ # class Task < ::Rake::TaskLib # Name of quality task. # Defaults to :quality. - attr_accessor :name + attr_accessor :quality_name + # Name of ratchet task. + # Defaults to :ratchet. + attr_accessor :ratchet_name + # Array of strings describing tools to be skipped--e.g., ["cane"] # # Defaults to [] attr_accessor :skip_tools # Array of directory names which contain ruby files to analyze. # - # Defaults to %w{lib test features}, which translates to *.rb in the base directory, as well as lib, test, and features. + # Defaults to %w{lib test features}, which translates to *.rb in + # the base directory, as well as lib, test, and features. attr_writer :ruby_dirs + # Relative path to output directory where *_high_water_mark + # files will be read/written + # + # Defaults to . + attr_writer :output_dir + # Defines a new task, using the name +name+. def initialize(args = {}) - @name = args[:name] - @name = 'quality' if @name.nil? + @quality_name = args[:quality_name] || 'quality' + + @ratchet_name = args[:ratchet_name] || 'ratchet' + + # allow unit tests to override the class that Rake DSL + # messages are sent to. + @dsl = args[:dsl] + + # likewise, but for system() + @cmd_runner = args[:cmd_runner] || Kernel + + # likewise, but for IO.popen() + @popener = args[:popener] || IO + + # likewise, but for File.open() on the count files + @count_file = args[:count_file] || File + + # likewise, but for IO.read()/IO.exist? on the count files + @count_io = args[:count_io] || IO + + # likewise, but for Dir.glob() on target Ruby files + @globber = args[:globber] || Dir + + # uses exist?() and open() to write out configuration files + # for tools if needed (e.g., .cane file) + @configuration_writer = args[:configuration_writer] || File + @skip_tools = [] if @skip_tools.nil? @config_files = nil @source_files = nil @ruby_opts = [] @reek_opts = '' @@ -56,23 +92,29 @@ @sort = nil yield self if block_given? @config_files ||= 'config/**/*.reek' @source_files ||= 'lib/**/*.rb' + @output_dir ||= "." define end private def define # :nodoc: desc 'Verify quality has increased or stayed ' + 'the same' unless ::Rake.application.last_comment - task(name) { run_task } - self + if @dsl.nil? + task(quality_name) { run_quality } + task(ratchet_name) { run_ratchet } + else + @dsl.task(quality_name) { run_quality } + @dsl.task(ratchet_name) { run_ratchet } + end end - def run_task + def run_quality tools = ['cane', 'flog', 'flay', 'reek', 'rubocop'] tools.each do |tool| installed = Gem::Specification.find_all_by_name(tool).any? suppressed = @skip_tools.include? tool @@ -84,15 +126,31 @@ method("quality_#{tool}".to_sym).call end end end + def run_ratchet + @globber.glob("*_high_water_mark").each { |filename| + puts "Processing #{filename}" + existing_violations = @count_io.read(filename).to_i + if existing_violations < 0 + raise "Problem with file #{filename}" + end + new_violations = [0, existing_violations - 1].max + @count_file.open(filename, 'w') {|f| f.write(new_violations.to_s) } + if new_violations != existing_violations + @cmd_runner.system("git commit -m 'tighten quality standard' #{filename}") + end + } + end + def ratchet_quality_cmd(cmd, options, &process_output_line) gives_error_code_on_violations ||= options[:gives_error_code_on_violations] + args ||= options[:args] emacs_format ||= options[:emacs_format] violations = 0 out = "" @@ -107,11 +165,11 @@ if !args.nil? full_cmd = "#{full_cmd} #{args}" end - IO.popen(full_cmd) do |f| + @popener.popen(full_cmd) do |f| while line = f.gets if emacs_format if line =~ /^ *(\S*.rb:[0-9]*) *(.*)/ out << $1 << ": " << $2 << "\n" elsif line =~ /^ *(.*) +(\S*.rb:[0-9]*) *(.*)/ @@ -130,30 +188,32 @@ if !gives_error_code_on_violations if exit_status != 0 fail "Error detected running #{full_cmd}. Exit status is #{exit_status}, output is [#{out}]" end end - filename = "#{cmd}_high_water_mark" - if File.exist?(filename) - existing_violations = IO.read(filename).to_i + filename = File.join(@output_dir, "#{cmd}_high_water_mark") + if @count_file.exist?(filename) + existing_violations = @count_io.read(filename).to_i else existing_violations = 9999999999 end puts "Existing violations: #{existing_violations}" puts "Found #{violations} #{cmd} violations" if violations > existing_violations fail "Output from #{cmd}\n\n#{out}\n\n" + "Reduce total number of #{cmd} violations to #{existing_violations} or below!" elsif violations < existing_violations puts "Ratcheting quality up..." - File.open(filename, 'w') {|f| f.write(violations.to_s) } + @count_file.open(filename, 'w') do |f| + f.write(violations.to_s) + end end end def quality_cane - if ! File.exist?(".cane") - File.open(".cane", "w") {|f| f.write("-f **/*.rb")} + if ! @configuration_writer.exist?(".cane") + @configuration_writer.open(".cane", "w") {|f| f.write("-f **/*.rb")} end ratchet_quality_cmd("cane", gives_error_code_on_violations: true, emacs_format: true) { |line| if line =~ /\(([0-9]*)\):$/ @@ -167,11 +227,11 @@ def ruby_dirs @ruby_dirs ||= %w{lib test features} end def ruby_files - Dir.glob('*.rb').concat(Dir.glob(File.join("{#{ruby_dirs.join(',')}}", '**', '*.rb'))).join(' ') + @globber.glob('*.rb').concat(@globber.glob(File.join("{#{ruby_dirs.join(',')}}", '**', '*.rb'))).join(' ') end def quality_reek args = "--line-number #{ruby_files}" ratchet_quality_cmd("reek", @@ -229,20 +289,8 @@ 1 end } end - def quality - Dir.glob("*_high_water_mark").each { |filename| - puts "Processing #{filename}" - existing_violations = IO.read(filename).to_i - if existing_violations <= 0 - raise "Problem with file #{filename}" - end - new_violations = existing_violations - 1 - File.open(filename, 'w') {|f| f.write(new_violations.to_s) } - system("git commit -m 'tighten quality standard' #{filename}") - } - end end end end