revolutionhealth-metricks 0.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/metricks.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Metricks
2
+ BASE_DIRECTORY = ENV['CC_BUILD_ARTIFACTS'] || 'tmp/metricks'
3
+ end
4
+
5
+ require File.join(File.dirname(__FILE__), 'metricks', 'md5_tracker')
6
+ require File.join(File.dirname(__FILE__), 'metricks', 'flog_reporter')
7
+ require File.join(File.dirname(__FILE__), 'tasks', 'metricks')
@@ -0,0 +1,95 @@
1
+ namespace :metricks do
2
+ CHURN_DIR = File.join(Metricks::BASE_DIRECTORY, 'churn')
3
+
4
+ desc "Which files change the most"
5
+ task :churn do
6
+ date_range, minimum_churn_count = churn_options()
7
+ svn_logs = `svn log #{date_range} --verbose`.split(/\n/).select {|line| line.strip =~ /^[A,M]/}
8
+
9
+ changes = {}
10
+ svn_logs.each do |line|
11
+ line.strip =~ /^[A,M] (.*)/
12
+ changes[$1] ? changes[$1] += 1 : changes[$1] = 1
13
+ end
14
+ write_churn_file(changes.reject {|file, change_count| change_count < minimum_churn_count})
15
+ system("open #{CHURN_DIR}/index.html") if PLATFORM['darwin']
16
+ end
17
+
18
+ def churn_options
19
+ options = defined?(CHURN_OPTIONS) ? CHURN_OPTIONS : {}
20
+ if options[:start_date]
21
+ require File.dirname(__FILE__) + '/../../../../config/environment'
22
+ date_range = "--revision {#{options[:start_date].call.strftime('%Y-%m-%d')}}:{#{Time.now.strftime('%Y-%m-%d')}}"
23
+ else
24
+ date_range = ""
25
+ end
26
+ minimum_churn_count = options[:minimum_churn_count] ? options[:minimum_churn_count] : 5
27
+ return date_range, minimum_churn_count
28
+ end
29
+
30
+ def write_churn_file changes
31
+ FileUtils.mkdir_p(CHURN_DIR, :verbose => false) unless File.directory?(CHURN_DIR)
32
+ File.open("#{CHURN_DIR}/index.html", "w+") do |file|
33
+ file << CHURN_FILE_BEGINING
34
+ changes.to_a.sort {|x,y| y[1] <=> x[1]}.each do |change|
35
+ file << "<tr><td>#{change[0]}</td><td class='warning'>#{change[1]}</td></tr>\n"
36
+ end
37
+ file << CHURN_FILE_END
38
+ end
39
+ end
40
+
41
+ CHURN_FILE_BEGINING = <<-EOS
42
+ <html><head><title>Source Control Churn Results</title></head>
43
+ <style>
44
+ body {
45
+ margin: 20px;
46
+ padding: 0;
47
+ font-size: 12px;
48
+ font-family: bitstream vera sans, verdana, arial, sans serif;
49
+ background-color: #efefef;
50
+ }
51
+
52
+ table {
53
+ border-collapse: collapse;
54
+ /*border-spacing: 0;*/
55
+ border: 1px solid #666;
56
+ background-color: #fff;
57
+ margin-bottom: 20px;
58
+ }
59
+
60
+ table, th, th+th, td, td+td {
61
+ border: 1px solid #ccc;
62
+ }
63
+
64
+ table th {
65
+ font-size: 12px;
66
+ color: #fc0;
67
+ padding: 4px 0;
68
+ background-color: #336;
69
+ }
70
+
71
+ th, td {
72
+ padding: 4px 10px;
73
+ }
74
+
75
+ td {
76
+ font-size: 13px;
77
+ }
78
+
79
+ .warning {
80
+ background-color: yellow;
81
+ }
82
+ </style>
83
+
84
+ <body>
85
+ <h1>Source Control Churn Results</h1>
86
+ <table width="100%" border="1">
87
+ <tr><th>File Path</th><th>Times Changed</th></tr>
88
+ EOS
89
+
90
+ CHURN_FILE_END = <<-EOS
91
+ </table>
92
+ </body>
93
+ </html>
94
+ EOS
95
+ end
@@ -0,0 +1,36 @@
1
+ require 'fileutils'
2
+
3
+ namespace :metricks do
4
+
5
+ COVERAGE_DIR = File.join(Metricks::BASE_DIRECTORY, 'coverage')
6
+ COVERAGE_DATA_FILE = File.join(COVERAGE_DIR, "coverage.data")
7
+
8
+ desc "A coverage report using rcov"
9
+ task :coverage do
10
+ FileUtils.rm_rf(COVERAGE_DATA_FILE, :verbose => false) if File.exist?(COVERAGE_DATA_FILE)
11
+ FileUtils.mkdir_p(COVERAGE_DIR) unless File.directory?(COVERAGE_DIR)
12
+ paths = defined?(TEST_PATHS_FOR_RCOV) ? TEST_PATHS_FOR_RCOV : ['test/**/*_test.rb']
13
+ paths.each { |path| execute_rcov(path) }
14
+ end
15
+
16
+ def execute_rcov(test_list)
17
+ default_options = {"--rails" => "",
18
+ "--aggregate" => "#{File.join(COVERAGE_DIR, 'coverage.data')}",
19
+ "--sort" => "coverage",
20
+ "--exclude" => '"gems/*,rcov*,spec/*,test/*"',
21
+ "--output" => %["#{COVERAGE_DIR}"]}
22
+
23
+ default_options.merge!(RCOV_OPTIONS) if defined?(RCOV_OPTIONS)
24
+ options = ""
25
+ default_options.each_pair { |key, value| options << "#{key} #{value} " }
26
+
27
+ sh "rcov #{options} #{test_list}" do |ok, response|
28
+ unless ok
29
+ puts "Rcov failed with exit status: #{response.exitstatus}"
30
+ exit 1
31
+ end
32
+ end
33
+
34
+ system("open #{COVERAGE_DIR}/index.html") if PLATFORM['darwin']
35
+ end
36
+ end
@@ -0,0 +1,58 @@
1
+ require 'metricks/md5_tracker'
2
+ require 'metricks/flog_reporter'
3
+
4
+ begin
5
+ FLOG_DIR = File.join(Metricks::BASE_DIRECTORY, 'flog')
6
+
7
+ def flog(output, directory)
8
+ Dir.glob("#{directory}/**/*.rb").each do |filename|
9
+ output_dir = "#{FLOG_DIR}/#{filename.split("/")[0..-2].join("/")}"
10
+ mkdir_p(output_dir, :verbose => false) unless File.directory?(output_dir)
11
+ `flog #{filename} > #{FLOG_DIR}/#{filename.split('.')[0]}.txt` if Metricks::MD5Tracker.file_changed?(filename, FLOG_DIR)
12
+ end
13
+ end
14
+
15
+ namespace :metricks do
16
+
17
+ task :flog => ['flog:all'] do
18
+ end
19
+
20
+ namespace :flog do
21
+ desc "Delete aggregate flog data."
22
+ task(:clean) { rm_rf(FLOG_DIR, :verbose => false) }
23
+
24
+ desc "Flog code in app/models"
25
+ task :models do
26
+ flog "models", "app/models"
27
+ end
28
+
29
+ desc "Flog code in app/controllers"
30
+ task :controllers do
31
+ flog "controllers", "app/controllers"
32
+ end
33
+
34
+ desc "Flog code in app/helpers"
35
+ task :helpers do
36
+ flog "helpers", "app/helpers"
37
+ end
38
+
39
+ desc "Flog code in lib"
40
+ task :lib do
41
+ flog "lib", "lib"
42
+ end
43
+
44
+ desc "Generate and open flog report"
45
+ task :all => [:models, :controllers, :helpers, :lib] do
46
+ Metricks::FlogReporter::Generator.generate_report(FLOG_DIR)
47
+ system("open #{FLOG_DIR}/index.html") if PLATFORM['darwin']
48
+ end
49
+ end
50
+
51
+ end
52
+ rescue LoadError
53
+ if RUBY_PLATFORM =~ /java/
54
+ puts 'running in jruby - flog tasks not available'
55
+ else
56
+ puts 'sudo gem install flog # if you want the flog tasks'
57
+ end
58
+ end
@@ -0,0 +1,11 @@
1
+ namespace :metricks do
2
+ task :prepare do
3
+ RAILS_ENV = 'test'
4
+ 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]
11
+ end
@@ -0,0 +1,6 @@
1
+ require 'fileutils'
2
+ require 'rubygems'
3
+ require 'rake'
4
+
5
+ # Load rake files
6
+ Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext }
@@ -0,0 +1,33 @@
1
+ namespace :metricks do
2
+
3
+ SAIKURO_DIR = File.join(Metricks::BASE_DIRECTORY, 'saikuro')
4
+
5
+ desc "A cyclomatic complexity report using Saikuro"
6
+ task :saikuro do
7
+ default_options = {"--output_directory" => SAIKURO_DIR,
8
+ "--input_directory" => "app",
9
+ "--cyclo" => "",
10
+ "--filter_cyclo" => "0",
11
+ "--warn_cyclo" => "5",
12
+ "--error_cyclo" => "7"}
13
+
14
+ default_options.merge!(SAIKURO_OPTIONS) if defined?(SAIKURO_OPTIONS)
15
+ options = ""
16
+ default_options.each_pair { |key, value| options << "#{key} #{value} " }
17
+
18
+ sh "ruby #{File.expand_path(File.join(File.dirname(__FILE__), '..', 'metricks', 'saikuro'))}/saikuro.rb " +
19
+ "#{options}" do |ok, response|
20
+ unless ok
21
+ puts "Saikuro failed with exit status: #{response.exitstatus}"
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ if File.exist? "#{SAIKURO_DIR}/index_cyclo.html"
27
+ mv "#{SAIKURO_DIR}/index_cyclo.html",
28
+ "#{SAIKURO_DIR}/index.html"
29
+ end
30
+
31
+ system("open #{SAIKURO_DIR}/index.html") if PLATFORM['darwin']
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ namespace :metricks do
2
+
3
+ STATS_DIR = File.join(Metricks::BASE_DIRECTORY, 'stats')
4
+ STATS_FILE = File.join(STATS_DIR, 'index.html')
5
+
6
+ desc "A stats report"
7
+ task :stats do
8
+ mkdir_p(STATS_DIR) unless File.directory?(STATS_DIR)
9
+ `echo '<pre>' > #{STATS_FILE}`
10
+ `rake stats >> #{STATS_FILE}`
11
+ `echo '</pre>' >> #{STATS_FILE}`
12
+ system("open #{STATS_FILE}") if PLATFORM['darwin']
13
+ end
14
+ end
data/metricks.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "metricks"
3
+ s.version = "0.4"
4
+ s.date = "2008-06-13"
5
+ s.summary = "Generates project metrics using Flog, RCov, Saikuro and more"
6
+ s.email = "sean.soper@gmail.com"
7
+ s.homepage = "http://github.com/revolutionhealth/metricks"
8
+ s.description = "Metricks is a fork of the metric_fu project and adds support for additional code analysis tools"
9
+ s.has_rdoc = true
10
+ s.authors = ["Sean Soper"]
11
+ s.files = %w(History.txt Manifest.txt metricks.gemspec MIT-LICENSE README TODO.txt) + Dir.glob("{lib,test}/**/*")
12
+ s.test_files = ["test/test_md5_tracker.rb"]
13
+ s.rdoc_options = ["--main", "README"]
14
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README"]
15
+ # s.add_dependency("mime-types", ["> 0.0.0"])
16
+ end
@@ -0,0 +1,6 @@
1
+ require 'test/unit'
2
+ require 'fileutils'
3
+
4
+ ENV['CC_BUILD_ARTIFACTS'] = File.join(File.dirname(__FILE__), 'tmp')
5
+
6
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'metricks')
@@ -0,0 +1,59 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class TestMD5Tracker < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
7
+ FileUtils.mkdir_p(@tmp_dir, :verbose => false) unless File.directory?(@tmp_dir)
8
+ @file1 = File.new(File.join(@tmp_dir, 'file1.txt'), 'w')
9
+ @file2 = File.new(File.join(@tmp_dir, 'file2.txt'), 'w')
10
+ end
11
+
12
+ def teardown
13
+ FileUtils.rm_rf(@tmp_dir, :verbose => false)
14
+ end
15
+
16
+ def test_identical_files_match
17
+ @file1.puts("Hello World")
18
+ @file1.close
19
+ file1_md5 = Metricks::MD5Tracker.track(@file1.path, @tmp_dir)
20
+
21
+ @file2.puts("Hello World")
22
+ @file2.close
23
+ file2_md5 = Metricks::MD5Tracker.track(@file2.path, @tmp_dir)
24
+
25
+ assert file1_md5 == file2_md5
26
+ end
27
+
28
+ def test_different_files_dont_match
29
+ @file1.puts("Hello World")
30
+ @file1.close
31
+ file1_md5 = Metricks::MD5Tracker.track(@file1.path, @tmp_dir)
32
+
33
+ @file2.puts("Goodbye World")
34
+ @file2.close
35
+ file2_md5 = Metricks::MD5Tracker.track(@file2.path, @tmp_dir)
36
+
37
+ assert file1_md5 != file2_md5
38
+ end
39
+
40
+ def test_file_changed
41
+ @file2.close
42
+
43
+ @file1.puts("Hello World")
44
+ @file1.close
45
+ file1_md5 = Metricks::MD5Tracker.track(@file1.path, @tmp_dir)
46
+
47
+ @file1 = File.new(File.join(@tmp_dir, 'file1.txt'), 'w')
48
+ @file1.puts("Goodbye World")
49
+ @file1.close
50
+ assert Metricks::MD5Tracker.file_changed?(@file1.path, @tmp_dir)
51
+ end
52
+
53
+ def test_file_changed_if_not_tracking
54
+ @file2.close
55
+
56
+ assert Metricks::MD5Tracker.file_changed?(@file1.path, @tmp_dir)
57
+ assert File.exist?(Metricks::MD5Tracker.md5_file(@file1.path, @tmp_dir))
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: revolutionhealth-metricks
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.4"
5
+ platform: ruby
6
+ authors:
7
+ - Sean Soper
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Metricks is a fork of the metric_fu project and adds support for additional code analysis tools
17
+ email: sean.soper@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - History.txt
24
+ - Manifest.txt
25
+ - README
26
+ files:
27
+ - History.txt
28
+ - Manifest.txt
29
+ - metricks.gemspec
30
+ - MIT-LICENSE
31
+ - README
32
+ - TODO.txt
33
+ - lib/metricks
34
+ - lib/metricks/saikuro
35
+ - lib/metricks/saikuro/SAIKURO_README
36
+ - lib/metricks/saikuro/saikuro.rb
37
+ - lib/metricks/flog_reporter.rb
38
+ - lib/metricks/flog_reporter
39
+ - lib/metricks/flog_reporter/scanned_method.rb
40
+ - lib/metricks/flog_reporter/generator.rb
41
+ - lib/metricks/flog_reporter/flog_reporter.css
42
+ - lib/metricks/flog_reporter/base.rb
43
+ - lib/metricks/flog_reporter/page.rb
44
+ - lib/metricks/flog_reporter/operator.rb
45
+ - lib/metricks/md5_tracker.rb
46
+ - lib/tasks
47
+ - lib/tasks/flog.rake
48
+ - lib/tasks/metricks.rb
49
+ - lib/tasks/metricks.rake
50
+ - lib/tasks/coverage.rake
51
+ - lib/tasks/churn.rake
52
+ - lib/tasks/saikuro.rake
53
+ - lib/tasks/stats.rake
54
+ - lib/metricks.rb
55
+ - test/test_md5_tracker.rb
56
+ - test/test_helper.rb
57
+ has_rdoc: true
58
+ homepage: http://github.com/revolutionhealth/metricks
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - README
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.0.1
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: Generates project metrics using Flog, RCov, Saikuro and more
84
+ test_files:
85
+ - test/test_md5_tracker.rb