jscruggs-metric_fu 0.8.0 → 0.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{History.txt → HISTORY} +12 -0
- data/MIT-LICENSE +1 -1
- data/Manifest.txt +3 -6
- data/README +66 -16
- data/Rakefile +11 -0
- data/TODO +13 -0
- data/lib/metric_fu/base.rb +159 -0
- data/lib/metric_fu/churn.rb +88 -0
- data/lib/metric_fu/flay.rb +17 -0
- data/lib/metric_fu/flog.rb +129 -0
- data/lib/metric_fu/md5_tracker.rb +6 -6
- data/lib/metric_fu/reek.rb +17 -0
- data/lib/metric_fu/roodi.rb +17 -0
- data/lib/metric_fu.rb +3 -7
- data/lib/tasks/churn.rake +4 -106
- data/lib/tasks/coverage.rake +25 -9
- data/lib/tasks/flay.rake +6 -0
- data/lib/tasks/flog.rake +28 -21
- data/lib/tasks/metric_fu.rake +21 -8
- data/lib/tasks/metric_fu.rb +1 -1
- data/lib/tasks/railroad.rake +36 -0
- data/lib/tasks/reek.rake +6 -0
- data/lib/tasks/roodi.rake +7 -0
- data/lib/tasks/saikuro.rake +20 -19
- data/lib/tasks/stats.rake +3 -3
- data/lib/templates/churn.html.erb +22 -0
- data/lib/templates/default.css +45 -0
- data/lib/templates/flay.html.erb +30 -0
- data/lib/templates/flog.html.erb +31 -0
- data/lib/templates/flog_page.html.erb +25 -0
- data/lib/templates/reek.html.erb +30 -0
- data/lib/templates/roodi.html.erb +26 -0
- data/spec/base_spec.rb +57 -0
- data/spec/churn_spec.rb +117 -0
- data/spec/config_spec.rb +110 -0
- data/spec/flay_spec.rb +19 -0
- data/spec/flog_spec.rb +208 -0
- data/spec/md5_tracker_spec.rb +57 -0
- data/spec/reek_spec.rb +26 -0
- data/spec/spec_helper.rb +11 -0
- metadata +76 -27
- data/TODO.txt +0 -9
- data/lib/metric_fu/flog_reporter/base.rb +0 -58
- data/lib/metric_fu/flog_reporter/flog_reporter.css +0 -39
- data/lib/metric_fu/flog_reporter/generator.rb +0 -71
- data/lib/metric_fu/flog_reporter/operator.rb +0 -10
- data/lib/metric_fu/flog_reporter/page.rb +0 -36
- data/lib/metric_fu/flog_reporter/scanned_method.rb +0 -28
- data/lib/metric_fu/flog_reporter.rb +0 -5
- data/lib/metric_fu/saikuro/SAIKURO_README +0 -142
- data/metric_fu.gemspec +0 -16
- data/test/test_helper.rb +0 -4
- data/test/test_md5_tracker.rb +0 -59
@@ -0,0 +1,17 @@
|
|
1
|
+
module MetricFu
|
2
|
+
|
3
|
+
def self.generate_roodi_report
|
4
|
+
MetricFu::Roodi.generate_report
|
5
|
+
system("open #{Roodi.metric_dir}/index.html") if open_in_browser?
|
6
|
+
end
|
7
|
+
|
8
|
+
class Roodi < Base::Generator
|
9
|
+
|
10
|
+
def analyze
|
11
|
+
files_to_analyze = MetricFu.roodi[:dirs_to_roodi].map{|dir| Dir[File.join(dir, "**/*.rb")] }
|
12
|
+
output = `roodi #{files_to_analyze.join(" ")}`
|
13
|
+
@matches = output.chomp.split("\n").map{|m| m.split(" - ") }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/metric_fu.rb
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require File.join(File.dirname(__FILE__), 'metric_fu', 'md5_tracker')
|
6
|
-
require File.join(File.dirname(__FILE__), 'metric_fu', 'flog_reporter')
|
7
|
-
require File.join(File.dirname(__FILE__), 'tasks', 'metric_fu')
|
1
|
+
require File.join(File.dirname(__FILE__), 'metric_fu', 'base') #require first because of dependecies
|
2
|
+
require File.join(File.dirname(__FILE__), 'tasks', 'metric_fu')
|
3
|
+
Dir[File.join(File.dirname(__FILE__), 'metric_fu/*.rb')].each{|l| require l }
|
data/lib/tasks/churn.rake
CHANGED
@@ -1,111 +1,9 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../metric_fu/churn')
|
2
|
+
|
1
3
|
namespace :metrics do
|
2
|
-
|
3
|
-
|
4
|
+
|
4
5
|
desc "Which files change the most"
|
5
6
|
task :churn do
|
6
|
-
|
7
|
-
|
8
|
-
changes = {}
|
9
|
-
if scm == :git
|
10
|
-
git_logs = `git log #{date_range} --name-only --pretty=format:`.split(/\n/)
|
11
|
-
git_logs.reject!{|line| line == ""}
|
12
|
-
|
13
|
-
git_logs.each do |line|
|
14
|
-
changes[line] ? changes[line] += 1 : changes[line] = 1
|
15
|
-
end
|
16
|
-
else
|
17
|
-
svn_logs = `svn log #{date_range} --verbose`.split(/\n/).select {|line| line.strip =~ /^[A,M]/}
|
18
|
-
|
19
|
-
svn_logs.each do |line|
|
20
|
-
line.strip =~ /^[A,M] (.*)/
|
21
|
-
changes[$1] ? changes[$1] += 1 : changes[$1] = 1
|
22
|
-
end
|
23
|
-
end
|
24
|
-
write_churn_file(changes.reject {|file, change_count| change_count < minimum_churn_count})
|
25
|
-
system("open #{CHURN_DIR}/index.html") if PLATFORM['darwin']
|
7
|
+
MetricFu.generate_churn_report
|
26
8
|
end
|
27
|
-
|
28
|
-
def churn_options
|
29
|
-
raise "CHURN_OPTIONS is now MetricFu::CHURN_OPTIONS" if defined?(CHURN_OPTIONS)
|
30
|
-
options = defined?(MetricFu::CHURN_OPTIONS) ? MetricFu::CHURN_OPTIONS : {}
|
31
|
-
if options[:start_date]
|
32
|
-
require RAILS_ROOT + '/config/environment'
|
33
|
-
if options[:scm] == :git
|
34
|
-
date_range = "--after=#{options[:start_date].call.strftime('%Y-%m-%d')}"
|
35
|
-
else
|
36
|
-
date_range = "--revision {#{options[:start_date].call.strftime('%Y-%m-%d')}}:{#{Time.now.strftime('%Y-%m-%d')}}"
|
37
|
-
end
|
38
|
-
else
|
39
|
-
date_range = ""
|
40
|
-
end
|
41
|
-
minimum_churn_count = options[:minimum_churn_count] ? options[:minimum_churn_count] : 5
|
42
|
-
scm = options[:scm] == :git ? :git : :svn
|
43
|
-
return date_range, minimum_churn_count, scm
|
44
|
-
end
|
45
|
-
|
46
|
-
def write_churn_file changes
|
47
|
-
FileUtils.mkdir_p(CHURN_DIR, :verbose => false) unless File.directory?(CHURN_DIR)
|
48
|
-
File.open("#{CHURN_DIR}/index.html", "w+") do |file|
|
49
|
-
file << CHURN_FILE_BEGINING
|
50
|
-
changes.to_a.sort {|x,y| y[1] <=> x[1]}.each do |change|
|
51
|
-
file << "<tr><td>#{change[0]}</td><td class='warning'>#{change[1]}</td></tr>\n"
|
52
|
-
end
|
53
|
-
file << CHURN_FILE_END
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
CHURN_FILE_BEGINING = <<-EOS
|
58
|
-
<html><head><title>Source Control Churn Results</title></head>
|
59
|
-
<style>
|
60
|
-
body {
|
61
|
-
margin: 20px;
|
62
|
-
padding: 0;
|
63
|
-
font-size: 12px;
|
64
|
-
font-family: bitstream vera sans, verdana, arial, sans serif;
|
65
|
-
background-color: #efefef;
|
66
|
-
}
|
67
|
-
|
68
|
-
table {
|
69
|
-
border-collapse: collapse;
|
70
|
-
/*border-spacing: 0;*/
|
71
|
-
border: 1px solid #666;
|
72
|
-
background-color: #fff;
|
73
|
-
margin-bottom: 20px;
|
74
|
-
}
|
75
|
-
|
76
|
-
table, th, th+th, td, td+td {
|
77
|
-
border: 1px solid #ccc;
|
78
|
-
}
|
79
|
-
|
80
|
-
table th {
|
81
|
-
font-size: 12px;
|
82
|
-
color: #fc0;
|
83
|
-
padding: 4px 0;
|
84
|
-
background-color: #336;
|
85
|
-
}
|
86
|
-
|
87
|
-
th, td {
|
88
|
-
padding: 4px 10px;
|
89
|
-
}
|
90
|
-
|
91
|
-
td {
|
92
|
-
font-size: 13px;
|
93
|
-
}
|
94
|
-
|
95
|
-
.warning {
|
96
|
-
background-color: yellow;
|
97
|
-
}
|
98
|
-
</style>
|
99
|
-
|
100
|
-
<body>
|
101
|
-
<h1>Source Control Churn Results</h1>
|
102
|
-
<table width="100%" border="1">
|
103
|
-
<tr><th>File Path</th><th>Times Changed</th></tr>
|
104
|
-
EOS
|
105
|
-
|
106
|
-
CHURN_FILE_END = <<-EOS
|
107
|
-
</table>
|
108
|
-
</body>
|
109
|
-
</html>
|
110
|
-
EOS
|
111
9
|
end
|
data/lib/tasks/coverage.rake
CHANGED
@@ -1,32 +1,47 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
|
2
|
+
|
3
3
|
begin
|
4
4
|
require 'rcov'
|
5
5
|
require 'rcov/rcovtask'
|
6
|
-
|
6
|
+
require 'spec/rake/spectask'
|
7
|
+
|
7
8
|
namespace :metrics do
|
8
|
-
|
9
|
+
|
9
10
|
COVERAGE_DIR = File.join(MetricFu::BASE_DIRECTORY, 'coverage')
|
10
11
|
COVERAGE_DATA_FILE = File.join(MetricFu::BASE_DIRECTORY, 'coverage.data')
|
11
|
-
|
12
|
+
SPEC_HTML_FILE = File.join(MetricFu::BASE_DIRECTORY, 'specs.html')
|
13
|
+
|
12
14
|
namespace :coverage do
|
13
15
|
rcov_output = COVERAGE_DIR
|
14
|
-
|
16
|
+
|
15
17
|
desc "Delete aggregate coverage data."
|
16
18
|
task(:clean) { rm_f("rcov_tmp", :verbose => false) }
|
17
|
-
|
19
|
+
|
18
20
|
desc "RCov task to generate report"
|
19
21
|
Rcov::RcovTask.new(:do => :clean) do |t|
|
20
22
|
FileUtils.mkdir_p(MetricFu::BASE_DIRECTORY) unless File.directory?(MetricFu::BASE_DIRECTORY)
|
21
|
-
t.test_files = FileList[
|
23
|
+
t.test_files = FileList[*MetricFu.coverage[:test_files]]
|
22
24
|
t.rcov_opts = ["--sort coverage", "--html", "--rails", "--exclude /gems/,/Library/"]
|
23
25
|
t.output_dir = COVERAGE_DIR
|
26
|
+
# this line is a fix for Rails 2.1 relative loading issues
|
27
|
+
t.libs << 'test'
|
24
28
|
end
|
29
|
+
# TODO not sure what this improves but it requires the diff-lcs gem
|
30
|
+
# http://github.com/indirect/metric_fu/commit/b9c1cf75f09d5b531b388cd01661eb16b5126968#diff-1
|
31
|
+
# Spec::Rake::SpecTask.new(:do => :clean) do |t|
|
32
|
+
# FileUtils.mkdir_p(MetricFu::BASE_DIRECTORY) unless File.directory?(MetricFu::BASE_DIRECTORY)
|
33
|
+
# t.ruby_opts = ['-rtest/unit']
|
34
|
+
# t.spec_files = FileList['test/**/*_test.rb', 'spec/**/*spec.rb']
|
35
|
+
# t.spec_opts = ["--format", "html:#{SPEC_HTML_FILE}", "--diff"]
|
36
|
+
# t.rcov = true
|
37
|
+
# t.rcov_opts = ["--sort coverage", "--html", "--rails", "--exclude /gems/,/Library/"]
|
38
|
+
# t.rcov_dir = COVERAGE_DIR
|
39
|
+
# end
|
25
40
|
end
|
26
|
-
|
41
|
+
|
27
42
|
desc "Generate and open coverage report"
|
28
43
|
task :coverage => ['coverage:do'] do
|
29
|
-
system("open #{COVERAGE_DIR}/index.html") if
|
44
|
+
system("open #{COVERAGE_DIR}/index.html") if MetricFu.open_in_browser?
|
30
45
|
end
|
31
46
|
end
|
32
47
|
rescue LoadError
|
@@ -34,5 +49,6 @@ rescue LoadError
|
|
34
49
|
puts 'running in jruby - rcov tasks not available'
|
35
50
|
else
|
36
51
|
puts 'sudo gem install rcov # if you want the rcov tasks'
|
52
|
+
|
37
53
|
end
|
38
54
|
end
|
data/lib/tasks/flay.rake
ADDED
data/lib/tasks/flog.rake
CHANGED
@@ -1,55 +1,62 @@
|
|
1
1
|
begin
|
2
|
-
FLOG_DIR = File.join(MetricFu::BASE_DIRECTORY, 'flog')
|
3
2
|
|
4
3
|
def flog(output, directory)
|
4
|
+
metric_dir = MetricFu::Flog::Generator.metric_dir
|
5
5
|
Dir.glob("#{directory}/**/*.rb").each do |filename|
|
6
|
-
output_dir = "#{
|
6
|
+
output_dir = "#{metric_dir}/#{filename.split("/")[0..-2].join("/")}"
|
7
7
|
mkdir_p(output_dir, :verbose => false) unless File.directory?(output_dir)
|
8
|
-
|
8
|
+
if MetricFu::MD5Tracker.file_changed?(filename, metric_dir)
|
9
|
+
`flog #{filename} > #{metric_dir}/#{filename.split('.')[0]}.txt`
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
14
|
namespace :metrics do
|
13
|
-
|
15
|
+
|
14
16
|
task :flog => ['flog:all'] do
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
namespace :flog do
|
18
20
|
desc "Delete aggregate flog data."
|
19
|
-
task(:clean) { rm_rf(
|
20
|
-
|
21
|
+
task(:clean) { rm_rf(MetricFu::Flog.metric_dir, :verbose => false) }
|
22
|
+
|
21
23
|
desc "Flog code in app/models"
|
22
24
|
task :models do
|
23
25
|
flog "models", "app/models"
|
24
26
|
end
|
25
27
|
|
26
|
-
desc "Flog code in app/controllers"
|
28
|
+
desc "Flog code in app/controllers"
|
27
29
|
task :controllers do
|
28
30
|
flog "controllers", "app/controllers"
|
29
31
|
end
|
30
32
|
|
31
|
-
desc "Flog code in app/helpers"
|
33
|
+
desc "Flog code in app/helpers"
|
32
34
|
task :helpers do
|
33
35
|
flog "helpers", "app/helpers"
|
34
36
|
end
|
35
37
|
|
36
|
-
desc "Flog code in lib"
|
38
|
+
desc "Flog code in lib"
|
37
39
|
task :lib do
|
38
40
|
flog "lib", "lib"
|
39
|
-
end
|
40
|
-
|
41
|
-
desc "Generate and open flog report"
|
42
|
-
task :all => [:models, :controllers, :helpers, :lib] do
|
43
|
-
MetricFu::FlogReporter::Generator.generate_report(FLOG_DIR)
|
44
|
-
system("open #{FLOG_DIR}/index.html") if PLATFORM['darwin']
|
45
41
|
end
|
46
|
-
|
42
|
+
|
47
43
|
desc "Generate a flog report from specified directories"
|
48
44
|
task :custom do
|
49
|
-
|
50
|
-
MetricFu
|
51
|
-
|
52
|
-
|
45
|
+
MetricFu::flog[:dirs_to_flog].each { |directory| flog(directory, directory) }
|
46
|
+
MetricFu.generate_flog_report
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Generate and open flog report"
|
50
|
+
if MetricFu::RAILS
|
51
|
+
task :all => [:models, :controllers, :helpers, :lib] do
|
52
|
+
MetricFu.generate_flog_report
|
53
|
+
end
|
54
|
+
else
|
55
|
+
task :all => [:custom] do
|
56
|
+
MetricFu.generate_flog_report
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
53
60
|
end
|
54
61
|
|
55
62
|
end
|
data/lib/tasks/metric_fu.rake
CHANGED
@@ -1,11 +1,24 @@
|
|
1
|
+
# only load configured metrics
|
2
|
+
MetricFu.metrics.each { |task| import "#{File.dirname(__FILE__)}/#{task}.rake" }
|
3
|
+
|
1
4
|
namespace :metrics do
|
2
|
-
|
3
|
-
|
5
|
+
if MetricFu::RAILS
|
6
|
+
|
7
|
+
desc "Generate coverage, cyclomatic complexity, flog, flay, railroad, reek, roodi, stats and churn reports"
|
8
|
+
task :all => MetricFu.metrics
|
9
|
+
|
10
|
+
task :set_testing_env do
|
11
|
+
RAILS_ENV = 'test'
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Generate metrics after migrating (for continuous integration)"
|
15
|
+
task :all_with_migrate => [:set_testing_env, "db:migrate", :all]
|
16
|
+
|
17
|
+
else
|
18
|
+
|
19
|
+
desc "Generate coverage, cyclomatic complexity, flog, flay, railroad and churn reports"
|
20
|
+
task :all => MetricFu.metrics
|
21
|
+
|
4
22
|
end
|
5
|
-
|
6
|
-
desc "Useful for continuous integration"
|
7
|
-
task :all_with_migrate => [:prepare, "db:migrate", :all]
|
8
|
-
|
9
|
-
desc "Generate coverage, cyclomatic complexity (saikuro), flog, stats, and churn reports"
|
10
|
-
task :all => [:coverage, :saikuro, :flog, :churn, :stats]
|
23
|
+
|
11
24
|
end
|
data/lib/tasks/metric_fu.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
namespace :metrics do
|
2
|
+
|
3
|
+
RAILROAD_DIR = File.join(MetricFu::BASE_DIRECTORY, 'railroad')
|
4
|
+
RAILROAD_INDEX = File.join(RAILROAD_DIR, 'index.html')
|
5
|
+
|
6
|
+
task :railroad => ['railroad:all'] do
|
7
|
+
end
|
8
|
+
|
9
|
+
namespace :railroad do
|
10
|
+
|
11
|
+
desc "Create all railroad reports"
|
12
|
+
task :all => [:models, :controllers, :aasm] do
|
13
|
+
#system("open #{RAILROAD_INDEX}") if PLATFORM['darwin']
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Create a railroad models report"
|
17
|
+
task :models do
|
18
|
+
mkdir_p(RAILROAD_DIR) unless File.directory?(RAILROAD_DIR)
|
19
|
+
`railroad -M -a -m -l -v | neato -Tpng > #{File.join(RAILROAD_DIR,'models.png')}`
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Create a railroad controllers report"
|
23
|
+
task :controllers do
|
24
|
+
mkdir_p(RAILROAD_DIR) unless File.directory?(RAILROAD_DIR)
|
25
|
+
`railroad -C -l -v | neato -Tpng > #{File.join(RAILROAD_DIR,'controllers.png')}`
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Create a railroad acts_as_state_machine report"
|
29
|
+
task :aasm do
|
30
|
+
mkdir_p(RAILROAD_DIR) unless File.directory?(RAILROAD_DIR)
|
31
|
+
`railroad -A -l -v | neato -Tpng > #{File.join(RAILROAD_DIR,'aasm.png')}`
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/tasks/reek.rake
ADDED
data/lib/tasks/saikuro.rake
CHANGED
@@ -1,23 +1,24 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
1
3
|
namespace :metrics do
|
2
|
-
|
3
|
-
SAIKURO_DIR = File.join(MetricFu::BASE_DIRECTORY, 'saikuro')
|
4
|
-
|
4
|
+
|
5
5
|
desc "A cyclomatic complexity report using Saikuro"
|
6
6
|
task :saikuro do
|
7
|
+
SAIKURO_DIR = File.join(MetricFu::BASE_DIRECTORY, 'saikuro')
|
8
|
+
SAIKURO = File.expand_path(File.join(File.dirname(__FILE__), '..', 'metric_fu', 'saikuro', 'saikuro.rb'))
|
9
|
+
|
7
10
|
raise "SAIKURO_OPTIONS is now MetricFu::SAIKURO_OPTIONS" if defined?(SAIKURO_OPTIONS)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
sh "ruby \"#{File.expand_path(File.join(File.dirname(__FILE__), '..', 'metric_fu', 'saikuro'))}/saikuro.rb\" " +
|
20
|
-
"#{options}" do |ok, response|
|
11
|
+
options = { :output_directory => SAIKURO_DIR,
|
12
|
+
:input_directory => MetricFu::CODE_DIRS,
|
13
|
+
:cyclo => "",
|
14
|
+
:filter_cyclo => "0",
|
15
|
+
:warn_cyclo => "5",
|
16
|
+
:error_cyclo => "7"}
|
17
|
+
|
18
|
+
options.merge!(MetricFu::SAIKURO_OPTIONS) if defined?(MetricFu::SAIKURO_OPTIONS)
|
19
|
+
options_string = options.inject(""){ |o, h| o + "--#{h.join(' ')} " }
|
20
|
+
|
21
|
+
sh %{ruby "#{SAIKURO}" #{options_string}} do |ok, response|
|
21
22
|
unless ok
|
22
23
|
puts "Saikuro failed with exit status: #{response.exitstatus}"
|
23
24
|
exit 1
|
@@ -25,10 +26,10 @@ namespace :metrics do
|
|
25
26
|
end
|
26
27
|
|
27
28
|
if File.exist? "#{SAIKURO_DIR}/index_cyclo.html"
|
28
|
-
mv "#{SAIKURO_DIR}/index_cyclo.html",
|
29
|
+
mv "#{SAIKURO_DIR}/index_cyclo.html",
|
29
30
|
"#{SAIKURO_DIR}/index.html"
|
30
31
|
end
|
31
|
-
|
32
|
-
system("open #{SAIKURO_DIR}/index.html") if
|
32
|
+
|
33
|
+
system("open #{SAIKURO_DIR}/index.html") if MetricFu.open_in_browser?
|
33
34
|
end
|
34
35
|
end
|
data/lib/tasks/stats.rake
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
namespace :metrics do
|
2
|
-
|
2
|
+
|
3
3
|
STATS_DIR = File.join(MetricFu::BASE_DIRECTORY, 'stats')
|
4
4
|
STATS_FILE = File.join(STATS_DIR, 'index.html')
|
5
|
-
|
5
|
+
|
6
6
|
desc "A stats report"
|
7
7
|
task :stats do
|
8
8
|
mkdir_p(STATS_DIR) unless File.directory?(STATS_DIR)
|
9
9
|
`echo '<pre>' > #{STATS_FILE}`
|
10
10
|
`rake stats >> #{STATS_FILE}`
|
11
11
|
`echo '</pre>' >> #{STATS_FILE}`
|
12
|
-
system("open #{STATS_FILE}") if
|
12
|
+
system("open #{STATS_FILE}") if MetricFu.open_in_browser?
|
13
13
|
end
|
14
14
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Source Control Churn Results</title>
|
4
|
+
<style>
|
5
|
+
<%= inline_css("default.css") %>
|
6
|
+
</style>
|
7
|
+
</head>
|
8
|
+
|
9
|
+
<body>
|
10
|
+
<h1>Source Control Churn Results</h1>
|
11
|
+
<p>Files that change a lot in your project may be bad a sign.
|
12
|
+
This task uses your source control log to identify those files.
|
13
|
+
</p>
|
14
|
+
<table>
|
15
|
+
<tr><th>File Path</th><th>Times Changed</th></tr>
|
16
|
+
<% @changes.to_a.sort {|x,y| y[1] <=> x[1]}.each do |change| %>
|
17
|
+
<tr><td><%= change[0] %></td><td class='warning'><%= change[1] %></td></tr>
|
18
|
+
<% end %>
|
19
|
+
</table>
|
20
|
+
<p>Generated on <%= Time.now.localtime %></p>
|
21
|
+
</body>
|
22
|
+
</html>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
body {
|
2
|
+
background-color: #efefef;
|
3
|
+
margin: 20px;
|
4
|
+
padding: 0;
|
5
|
+
font: 12px verdana, arial, helvetica;
|
6
|
+
}
|
7
|
+
|
8
|
+
table {
|
9
|
+
border-collapse: collapse;
|
10
|
+
border: 1px solid #666;
|
11
|
+
background: #fff;
|
12
|
+
margin-bottom: 20px;
|
13
|
+
}
|
14
|
+
|
15
|
+
table tr.light {
|
16
|
+
background: #fff;
|
17
|
+
}
|
18
|
+
|
19
|
+
table tr.dark {
|
20
|
+
background: #f9f9f9;
|
21
|
+
}
|
22
|
+
|
23
|
+
table td, table th {
|
24
|
+
padding: 4px 10px;
|
25
|
+
font-size: 13px;
|
26
|
+
}
|
27
|
+
table th {
|
28
|
+
text-align: center;
|
29
|
+
color: #fc0;
|
30
|
+
background: #336;
|
31
|
+
font-weight: bold;
|
32
|
+
border: #d0d0d0 1px solid;
|
33
|
+
}
|
34
|
+
|
35
|
+
table td {
|
36
|
+
border: #d0d0d0 1px solid;
|
37
|
+
}
|
38
|
+
|
39
|
+
table td.score {
|
40
|
+
text-align: right;
|
41
|
+
}
|
42
|
+
|
43
|
+
.warning {
|
44
|
+
background: yellow;
|
45
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Flay Results</title>
|
4
|
+
<style>
|
5
|
+
<%= inline_css("default.css") %>
|
6
|
+
</style>
|
7
|
+
</head>
|
8
|
+
|
9
|
+
<body>
|
10
|
+
<h1>Flay Results</h1>
|
11
|
+
<p><a href='http://ruby.sadi.st/Flay.html'>Flay</a> analyzes ruby code for structural similarities.</p>
|
12
|
+
<table>
|
13
|
+
<tr>
|
14
|
+
<th>Files</th>
|
15
|
+
<th>Matches</th>
|
16
|
+
</tr>
|
17
|
+
<% @matches.each_with_index do |match, count| %>
|
18
|
+
<tr class='<%= cycle("light", "dark", count) %>'>
|
19
|
+
<td>
|
20
|
+
<% match[1..-1].each do |filename| %>
|
21
|
+
<%= link_to_filename(*filename.split(":")) %><br>
|
22
|
+
<% end %>
|
23
|
+
</td>
|
24
|
+
<td><%= match.first %></td>
|
25
|
+
</tr>
|
26
|
+
<% end %>
|
27
|
+
</table>
|
28
|
+
<p>Generated on <%= Time.now.localtime %></p>
|
29
|
+
</body>
|
30
|
+
</html>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Flog Reporter</title>
|
4
|
+
<style>
|
5
|
+
<%= inline_css("default.css") %>
|
6
|
+
</style>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<h1>Flog Results</h1>
|
10
|
+
<p><a href='http://ruby.sadi.st/Flog.html'>Flog</a> measures code complexity.</p>
|
11
|
+
<table>
|
12
|
+
<tr>
|
13
|
+
<th>File</th>
|
14
|
+
<th>Total score</th>
|
15
|
+
<th>Methods</th>
|
16
|
+
<th>Average score</th>
|
17
|
+
<th>Highest score</th>
|
18
|
+
</tr>
|
19
|
+
<% pages.sort {|x,y| y.highest_score <=> x.highest_score }.each_with_index do |page, count| %>
|
20
|
+
<tr class='<%= cycle("light", "dark", count) %>'>
|
21
|
+
<td><a href='<%= page.path %>'><%= page.path.sub('.html', '.rb') %></a></td>
|
22
|
+
<td class='score'><%= sprintf(SCORE_FORMAT, page.score) %></td>
|
23
|
+
<td class='score'><%= page.scanned_methods.length %></td>
|
24
|
+
<td class='score'><%= sprintf(SCORE_FORMAT, page.average_score) %></td>
|
25
|
+
<td class='score'><%= sprintf(SCORE_FORMAT, page.highest_score) %></td>
|
26
|
+
</tr>
|
27
|
+
<% end %>
|
28
|
+
</table>
|
29
|
+
<p>Generated on <%= Time.now.localtime %></p>
|
30
|
+
</body>
|
31
|
+
</html>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<style>
|
4
|
+
<%= inline_css("default.css") %>
|
5
|
+
</style>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<p>Score: <%= score %></p>
|
9
|
+
<% scanned_methods.each do |sm| %>
|
10
|
+
<p><strong><%= sm.name %> (<%= sm.score %>)</strong></p>
|
11
|
+
<table>
|
12
|
+
<tr>
|
13
|
+
<th>Score</th>
|
14
|
+
<th>Operator</th>
|
15
|
+
</tr>
|
16
|
+
<% sm.operators.each_with_index do |operator, count| %>
|
17
|
+
<tr class='<%= cycle("light", "dark", count) %>'>
|
18
|
+
<td class='score'><%= sprintf(SCORE_FORMAT, operator.score) %></td>
|
19
|
+
<td class='score'><%= operator.operator %></td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</table>
|
23
|
+
<% end %>
|
24
|
+
</body>
|
25
|
+
</html>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Reek Results</title>
|
4
|
+
<style>
|
5
|
+
<%= inline_css("default.css") %>
|
6
|
+
</style>
|
7
|
+
</head>
|
8
|
+
|
9
|
+
<body>
|
10
|
+
<h1>Reek Results</h1>
|
11
|
+
<p><a href="http://reek.rubyforge.org/">Reek</a> detects common code smells in ruby code.</p>
|
12
|
+
<table>
|
13
|
+
<tr>
|
14
|
+
<th>File Path</th>
|
15
|
+
<th>Code Smell</th>
|
16
|
+
</tr>
|
17
|
+
<% @matches.each_with_index do |match, count| %>
|
18
|
+
<tr class='<%= cycle("light", "dark", count) %>'>
|
19
|
+
<td><%= match.first %></td>
|
20
|
+
<td>
|
21
|
+
<% match[1..-1].each do |line| %>
|
22
|
+
<%= line %><br>
|
23
|
+
<% end %>
|
24
|
+
</td>
|
25
|
+
</tr>
|
26
|
+
<% end %>
|
27
|
+
</table>
|
28
|
+
<p>Generated on <%= Time.now.localtime %></p>
|
29
|
+
</body>
|
30
|
+
</html>
|