jscruggs-metric_fu 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,95 @@
1
+ namespace :metrics do
2
+ CHURN_DIR = File.join(MetricFu::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,38 @@
1
+ require 'fileutils'
2
+
3
+ begin
4
+ require 'rcov'
5
+ require 'rcov/rcovtask'
6
+
7
+ namespace :metrics do
8
+
9
+ COVERAGE_DIR = File.join(MetricFu::BASE_DIRECTORY, 'coverage')
10
+ COVERAGE_DATA_FILE = File.join(MetricFu::BASE_DIRECTORY, 'coverage.data')
11
+
12
+ namespace :coverage do
13
+ rcov_output = COVERAGE_DIR
14
+
15
+ desc "Delete aggregate coverage data."
16
+ task(:clean) { rm_f("rcov_tmp", :verbose => false) }
17
+
18
+ desc "RCov task to generate report"
19
+ Rcov::RcovTask.new(:do => :clean) do |t|
20
+ FileUtils.mkdir_p(MetricFu::BASE_DIRECTORY) unless File.directory?(MetricFu::BASE_DIRECTORY)
21
+ t.test_files = FileList['test/**/*_test.rb']
22
+ t.rcov_opts = ["--sort coverage", "--aggregate '#{COVERAGE_DATA_FILE}'", "--html", "--rails"]
23
+ t.output_dir = COVERAGE_DIR
24
+ end
25
+ end
26
+
27
+ desc "Generate and open coverage report"
28
+ task :coverage => ['coverage:do'] do
29
+ system("open #{COVERAGE_DIR}/index.html") if PLATFORM['darwin']
30
+ end
31
+ end
32
+ rescue LoadError
33
+ if RUBY_PLATFORM =~ /java/
34
+ puts 'running in jruby - rcov tasks not available'
35
+ else
36
+ puts 'sudo gem install rcov # if you want the rcov tasks'
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'metricks', 'md5_tracker')
2
+ require File.join(File.dirname(__FILE__), '..', 'metricks', 'flog_reporter')
3
+
4
+ begin
5
+ FLOG_DIR = File.join(MetricFu::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 MetricFu::MD5Tracker.file_changed?(filename, FLOG_DIR)
12
+ end
13
+ end
14
+
15
+ namespace :metrics 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
+ MetricFu::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 :metrics 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 :metrics do
2
+
3
+ SAIKURO_DIR = File.join(MetricFu::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 :metrics do
2
+
3
+ STATS_DIR = File.join(MetricFu::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/metric_fu.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "metric_fu"
3
+ s.version = "0.7.0"
4
+ s.date = "2008-09-11"
5
+ s.summary = "Generates project metrics using Flog, RCov, Saikuro and more"
6
+ s.email = "jake.scruggs@gmail.com"
7
+ s.homepage = "http://metric-fu.rubyforge.org/"
8
+ s.description = "Gives you a fist full of code metrics"
9
+ s.has_rdoc = true
10
+ s.authors = ["Jake Scruggs", "Sean Soper"]
11
+ s.files = ["History.txt", "Manifest.txt", "metric_fu.gemspec", "MIT-LICENSE", "README", "TODO.txt", "lib/metric_fu", "lib/metric_fu/flog_reporter", "lib/metric_fu/flog_reporter/base.rb", "lib/metric_fu/flog_reporter/flog_reporter.css", "lib/metric_fu/flog_reporter/generator.rb", "lib/metric_fu/flog_reporter/operator.rb", "lib/metric_fu/flog_reporter/page.rb", "lib/metric_fu/flog_reporter/scanned_method.rb", "lib/metric_fu/flog_reporter.rb", "lib/metric_fu/md5_tracker.rb", "lib/metric_fu/saikuro", "lib/metric_fu/saikuro/saikuro.rb", "lib/metric_fu/saikuro/SAIKURO_README", "lib/metric_fu.rb", "lib/tasks", "lib/tasks/churn.rake", "lib/tasks/coverage.rake", "lib/tasks/flog.rake", "lib/tasks/metric_fu.rake", "lib/tasks/metric_fu.rb", "lib/tasks/saikuro.rake", "lib/tasks/stats.rake", "test/test_helper.rb", "test/test_md5_tracker.rb"]
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("flog", ["> 0.0.0"])
16
+ s.add_dependency("rcov", ["> 0.0.0"])
17
+ 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 = MetricFu::MD5Tracker.track(@file1.path, @tmp_dir)
20
+
21
+ @file2.puts("Hello World")
22
+ @file2.close
23
+ file2_md5 = MetricFu::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 = MetricFu::MD5Tracker.track(@file1.path, @tmp_dir)
32
+
33
+ @file2.puts("Goodbye World")
34
+ @file2.close
35
+ file2_md5 = MetricFu::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 = MetricFu::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 MetricFu::MD5Tracker.file_changed?(@file1.path, @tmp_dir)
51
+ end
52
+
53
+ def test_file_changed_if_not_tracking
54
+ @file2.close
55
+
56
+ assert MetricFu::MD5Tracker.file_changed?(@file1.path, @tmp_dir)
57
+ assert File.exist?(MetricFu::MD5Tracker.md5_file(@file1.path, @tmp_dir))
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jscruggs-metric_fu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.0
5
+ platform: ruby
6
+ authors:
7
+ - Jake Scruggs
8
+ - Sean Soper
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2008-09-11 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: flog
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rcov
27
+ version_requirement:
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.0
33
+ version:
34
+ description: Gives you a fist full of code metrics
35
+ email: jake.scruggs@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - History.txt
42
+ - Manifest.txt
43
+ - README
44
+ files:
45
+ - History.txt
46
+ - Manifest.txt
47
+ - metric_fu.gemspec
48
+ - MIT-LICENSE
49
+ - README
50
+ - TODO.txt
51
+ - lib/metric_fu
52
+ - lib/metric_fu/flog_reporter
53
+ - lib/metric_fu/flog_reporter/base.rb
54
+ - lib/metric_fu/flog_reporter/flog_reporter.css
55
+ - lib/metric_fu/flog_reporter/generator.rb
56
+ - lib/metric_fu/flog_reporter/operator.rb
57
+ - lib/metric_fu/flog_reporter/page.rb
58
+ - lib/metric_fu/flog_reporter/scanned_method.rb
59
+ - lib/metric_fu/flog_reporter.rb
60
+ - lib/metric_fu/md5_tracker.rb
61
+ - lib/metric_fu/saikuro
62
+ - lib/metric_fu/saikuro/saikuro.rb
63
+ - lib/metric_fu/saikuro/SAIKURO_README
64
+ - lib/metric_fu.rb
65
+ - lib/tasks
66
+ - lib/tasks/churn.rake
67
+ - lib/tasks/coverage.rake
68
+ - lib/tasks/flog.rake
69
+ - lib/tasks/metric_fu.rake
70
+ - lib/tasks/metric_fu.rb
71
+ - lib/tasks/saikuro.rake
72
+ - lib/tasks/stats.rake
73
+ - test/test_helper.rb
74
+ - test/test_md5_tracker.rb
75
+ has_rdoc: true
76
+ homepage: http://metric-fu.rubyforge.org/
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --main
80
+ - README
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ version:
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "0"
94
+ version:
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 1.2.0
99
+ signing_key:
100
+ specification_version: 2
101
+ summary: Generates project metrics using Flog, RCov, Saikuro and more
102
+ test_files:
103
+ - test/test_md5_tracker.rb