jscruggs-metric_fu 0.7.0

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.
@@ -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