require 'erb'
module MetricFu
TEMPLATE_DIR = File.join(File.dirname(__FILE__), '..', 'templates')
BASE_DIRECTORY = ENV['CC_BUILD_ARTIFACTS'] || 'tmp/metric_fu'
class << self
# The Configuration instance used to configure the Rails environment
def configuration
@@configuration ||= Configuration.new
end
def churn
configuration.churn
end
def coverage
configuration.coverage
end
def flay
configuration.flay
end
def flog
configuration.flog
end
def metrics
configuration.metrics
end
def open_in_browser?
configuration.general[:open_in_browser] && PLATFORM['darwin'] && !run_by_cruise_control?
end
def saikuro
configuration.saikuro
end
def reek
configuration.reek
end
def roodi
configuration.roodi
end
def run_by_cruise_control?
!!ENV['CC_BUILD_ARTIFACTS']
end
def uses_git?
File.exist?(".git")
end
def uses_svn?
File.exist?(".svn")
end
def can_churn?
uses_git? || uses_svn?
end
def is_rails?
File.exist?("config/environment.rb")
end
def code_dirs
dirs = ['lib']
dirs << 'app' if is_rails?
dirs.sort{|v1, v2| v1.to_s <=> v2.to_s}
end
def default_metrics
metrics = [:coverage, :flog, :flay, :reek, :roodi, :saikuro ]
metrics << :stats if is_rails?
# Churning requires a subversion or git repo
metrics << :churn if can_churn?
metrics.sort{|v1, v2| v1.to_s <=> v2.to_s}
end
end
class Configuration
attr_accessor :churn, :coverage, :flay, :flog, :metrics, :reek, :roodi, :saikuro, :general
def initialize
raise "Use config.churn instead of MetricFu::CHURN_OPTIONS" if defined? ::MetricFu::CHURN_OPTIONS
raise "Use config.flog[:dirs_to_flog] instead of MetricFu::DIRECTORIES_TO_FLOG" if defined? ::MetricFu::DIRECTORIES_TO_FLOG
raise "Use config.saikuro instead of MetricFu::SAIKURO_OPTIONS" if defined? ::MetricFu::SAIKURO_OPTIONS
reset
end
def self.run()
yield MetricFu.configuration
end
def reset
@general = { :open_in_browser => true }
@churn = {}
rcov_opts = ["--sort coverage", "--html", "--exclude /gems/,/Library/,spec"]
rcov_opts << "--rails" if MetricFu.is_rails?
@coverage = { :test_files => ['test/**/*_test.rb', 'spec/**/*_spec.rb'],
:rcov_opts => rcov_opts }
@flay = { :dirs_to_flay => MetricFu.code_dirs}
@flog = { :dirs_to_flog => MetricFu.code_dirs}
@reek = { :dirs_to_reek => MetricFu.code_dirs}
@roodi = { :dirs_to_roodi => MetricFu.code_dirs}
@metrics = MetricFu.default_metrics
@saikuro = {}
end
def saikuro=(options)
raise "saikuro need to be a Hash" unless options.is_a?(Hash)
@saikuro = options
end
end
module Base
######################################################################
# Base class for report Generators
#
class Generator
def initialize(options={})
@base_dir = self.class.metric_dir
end
def self.metric_dir
File.join(BASE_DIRECTORY, template_name)
end
def self.template_name
self.to_s.split('::').last.downcase
end
def self.generate_report(options={})
FileUtils.mkdir_p(metric_dir, :verbose => false) unless File.directory?(metric_dir)
self.new(options).generate_report
end
def save_html(content, file='index.html')
open("#{@base_dir}/#{file}", "w") do |f|
f.puts content
end
end
def generate_report
save_html(generate_html)
end
def generate_html
analyze
html = ERB.new(File.read(template_file)).result(binding)
end
def template_name
self.class.template_name
end
def template_file
File.join(MetricFu::TEMPLATE_DIR, "#{template_name}.html.erb")
end
########################
# Template methods
def inline_css(css)
open(File.join(MetricFu::TEMPLATE_DIR, css)) { |f| f.read }
end
def link_to_filename(name, line = nil)
if MetricFu.run_by_cruise_control?
cc_link_to_filename(name, line)
else
system_link_to_filename(name, line)
end
end
def cycle(first_value, second_value, iteration)
return first_value if iteration % 2 == 0
return second_value
end
private
def cc_link_to_filename(name, line = nil)
if MetricFu.configuration.general[:url_prefix]
MetricFu.configuration.general[:url_prefix] += '/' unless MetricFu.configuration.general[:url_prefix] =~ /\/$/
%{#{name}}
else
%{"#{name}"} # No link for cruise control without a prefix
end
end
def system_link_to_filename(name, line = nil)
filename = File.expand_path(name)
if PLATFORM['darwin']
%{#{name}}
else
%{#{name}}
end
end
end
end
end