metric_fu 4.3.1 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.metrics +55 -26
  3. data/.travis.yml +4 -1
  4. data/AUTHORS +12 -0
  5. data/Gemfile +1 -0
  6. data/HISTORY.md +24 -0
  7. data/README.md +27 -22
  8. data/checksum/metric_fu-4.3.1.gem.sha512 +1 -0
  9. data/checksum/metric_fu-4.4.0.gem.sha512 +1 -0
  10. data/lib/metric_fu.rb +28 -79
  11. data/lib/metric_fu/cli/helper.rb +1 -1
  12. data/lib/metric_fu/cli/parser.rb +1 -1
  13. data/lib/metric_fu/configuration.rb +104 -150
  14. data/lib/metric_fu/environment.rb +88 -0
  15. data/lib/metric_fu/formatter.rb +23 -0
  16. data/lib/metric_fu/formatter/html.rb +12 -9
  17. data/lib/metric_fu/initial_requires.rb +1 -0
  18. data/lib/metric_fu/io.rb +60 -1
  19. data/lib/metric_fu/load_files.rb +4 -2
  20. data/lib/metric_fu/loader.rb +62 -0
  21. data/lib/metric_fu/metric.rb +102 -0
  22. data/lib/metric_fu/metrics/base_template.rb +15 -9
  23. data/lib/metric_fu/metrics/cane/cane.rb +9 -5
  24. data/lib/metric_fu/metrics/cane/init.rb +35 -13
  25. data/lib/metric_fu/metrics/churn/churn.rb +5 -1
  26. data/lib/metric_fu/metrics/churn/init.rb +24 -4
  27. data/lib/metric_fu/metrics/flay/flay.rb +7 -3
  28. data/lib/metric_fu/metrics/flay/init.rb +29 -13
  29. data/lib/metric_fu/metrics/flay/template_awesome/flay.html.erb +1 -1
  30. data/lib/metric_fu/metrics/flog/flog.rb +14 -38
  31. data/lib/metric_fu/metrics/flog/init.rb +30 -7
  32. data/lib/metric_fu/metrics/generator.rb +21 -6
  33. data/lib/metric_fu/metrics/graph.rb +2 -2
  34. data/lib/metric_fu/metrics/hotspots/hotspots.rb +5 -1
  35. data/lib/metric_fu/metrics/hotspots/init.rb +21 -5
  36. data/lib/metric_fu/metrics/rails_best_practices/init.rb +29 -5
  37. data/lib/metric_fu/metrics/rails_best_practices/rails_best_practices.rb +20 -27
  38. data/lib/metric_fu/metrics/rails_best_practices/template_awesome/rails_best_practices.html.erb +1 -1
  39. data/lib/metric_fu/metrics/rcov/init.rb +40 -15
  40. data/lib/metric_fu/metrics/rcov/rcov.rb +15 -10
  41. data/lib/metric_fu/metrics/reek/init.rb +25 -6
  42. data/lib/metric_fu/metrics/reek/reek.rb +52 -31
  43. data/lib/metric_fu/metrics/reek/template_awesome/reek.html.erb +1 -1
  44. data/lib/metric_fu/metrics/roodi/init.rb +25 -6
  45. data/lib/metric_fu/metrics/roodi/roodi.rb +7 -3
  46. data/lib/metric_fu/metrics/saikuro/init.rb +22 -6
  47. data/lib/metric_fu/metrics/saikuro/saikuro.rb +8 -3
  48. data/lib/metric_fu/metrics/stats/init.rb +28 -5
  49. data/lib/metric_fu/metrics/stats/stats.rb +24 -6
  50. data/lib/metric_fu/metrics/stats/template_awesome/stats.html.erb +2 -2
  51. data/lib/metric_fu/parser_ext.rb +15 -0
  52. data/lib/metric_fu/reporting/graphs/engines/gchart.rb +1 -1
  53. data/lib/metric_fu/reporting/graphs/engines/init.rb +18 -4
  54. data/lib/metric_fu/reporting/graphs/grapher.rb +1 -1
  55. data/lib/metric_fu/reporting/result.rb +13 -6
  56. data/lib/metric_fu/reporting/templates/awesome/awesome_template.rb +1 -1
  57. data/lib/metric_fu/run.rb +7 -10
  58. data/lib/metric_fu/sexp_ext.rb +11 -0
  59. data/lib/metric_fu/version.rb +1 -1
  60. data/metric_fu.gemspec +23 -20
  61. data/spec/cli/helper_spec.rb +5 -16
  62. data/spec/metric_fu/configuration_spec.rb +62 -88
  63. data/spec/metric_fu/formatter/html_spec.rb +26 -16
  64. data/spec/metric_fu/formatter/yaml_spec.rb +2 -2
  65. data/spec/metric_fu/metric_spec.rb +50 -0
  66. data/spec/metric_fu/metrics/base_template_spec.rb +9 -7
  67. data/spec/metric_fu/metrics/cane/cane_spec.rb +19 -24
  68. data/spec/metric_fu/metrics/churn/churn_spec.rb +8 -8
  69. data/spec/metric_fu/metrics/flay/flay_spec.rb +7 -13
  70. data/spec/metric_fu/metrics/flog/flog_spec.rb +63 -58
  71. data/spec/metric_fu/metrics/generator_spec.rb +4 -0
  72. data/spec/metric_fu/metrics/hotspots/hotspots_spec.rb +7 -7
  73. data/spec/metric_fu/metrics/rails_best_practices/rails_best_practices_spec.rb +14 -33
  74. data/spec/metric_fu/metrics/rcov/rcov_spec.rb +17 -18
  75. data/spec/metric_fu/metrics/reek/reek_spec.rb +9 -10
  76. data/spec/metric_fu/metrics/roodi/roodi_spec.rb +5 -11
  77. data/spec/metric_fu/metrics/saikuro/saikuro_spec.rb +15 -14
  78. data/spec/metric_fu/metrics/stats/stats_spec.rb +5 -6
  79. data/spec/metric_fu/reporting/graphs/engines/bluff_spec.rb +2 -3
  80. data/spec/metric_fu/reporting/graphs/engines/gchart_spec.rb +12 -9
  81. data/spec/metric_fu/reporting/result_spec.rb +3 -3
  82. data/spec/run_spec.rb +45 -29
  83. data/spec/spec_helper.rb +7 -0
  84. data/spec/support/helper_methods.rb +9 -0
  85. data/spec/support/suite.rb +17 -11
  86. metadata +59 -56
  87. data/bin/mf-rails_best_practices +0 -9
  88. data/bin/mf-stats +0 -7
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 741f0378823b8b42fce3ad9e4bc36b0312988660
4
+ data.tar.gz: 66dce50c5876c8dc84d672e5ed5571e6e9854dd5
5
+ SHA512:
6
+ metadata.gz: fc38e9dfd106e6f8c92d9f044a3ee1d9d192d6ae3de367b871efa70bc40bd7c67f877f6bc9628440c05094284eb333a635d96c9626e05f2e79f6be4aacd79b14
7
+ data.tar.gz: 1487b7c82f5f8bf932bbd81b1b538fdd0bf03216fd32af2b3c3f294c7d83edd808cae889f827b1c4e0b788667593f2d0f9e159ce149beb7396b1cd29bd270267
data/.metrics CHANGED
@@ -3,34 +3,63 @@
3
3
  # For testing that this file gets loaded
4
4
  $metric_file_loaded = true
5
5
 
6
- # example configuration
7
- # MetricFu::Configuration.run do |config|
8
- # coverage_file = File.expand_path("coverage/rcov/rcov.txt", Dir.pwd)
9
- # config.add_metric(:rcov)
10
- # config.add_graph(:rcov)
11
- # config.configure_metric(:rcov, {:external => coverage_file})
12
- # config.cane = {:abc_max => 15, :line_length => 80, :no_doc => 'y', :no_readme => 'y'}
13
- # end
14
- # or
6
+ # Example Configuration
7
+ #
15
8
  # MetricFu::Configuration.run do |config|
16
- # config.metrics -= [ :rcov ]
17
- # end
18
- # you may enable running rcov manually with
19
- # MetricFu.run_rcov
20
9
  #
21
- # By default, metric_fu will use the built-in html formatter
22
- # to generate HTML reports for each metric with pretty graphs.
10
+ # Configure Metrics
11
+ #
12
+ # To configure individual metrics...
13
+ #
14
+ # config.configure_metric(:rcov) do |rcov|
15
+ # rcov.enabled = true
16
+ # coverage_file = File.expand_path("coverage/rcov/rcov.txt", Dir.pwd)
17
+ # rcov.external = coverage_file
18
+ # end
19
+ #
20
+ # config.configure_metric(:cane) do |cane|
21
+ # cane.enabled = true
22
+ # cane.abc_max = 15
23
+ # cane.line_length = 80
24
+ # cane.no_doc = 'y'
25
+ # cane.no_readme = 'y'
26
+ # end
27
+ #
28
+ # Or, to configure a group of metrics...
29
+ # config.configure_metrics.each do |metric|
30
+ # if [:churn, :flay, :flog].include?(metric.name)
31
+ # metric.enabled = true
32
+ # else
33
+ # metric.enabled = false
34
+ # end
35
+ # end
36
+ #
37
+ #
38
+ # Configure Formatters
39
+ #
40
+ # By default, metric_fu will use the built-in html formatter
41
+ # to generate HTML reports for each metric with pretty graphs.
23
42
 
24
- # To configure different formatter(s) or output ...
25
- # MetricFu::Configuration.run do |config|
26
- # config.add_formatter(:html)
27
- # config.add_formatter(:yaml, "customreport.yml")
28
- # config.add_formatter(MyCustomFormatter)
29
- # end
43
+ # To configure different formatter(s) or output ...
44
+ #
45
+ # config.configure_formatter(:html)
46
+ # config.configure_formatter(:yaml, "customreport.yml")
47
+ # config.configure_formatter(MyCustomFormatter)
48
+ #
49
+ # MetricFu will attempt to require a custom formatter by
50
+ # fully qualified name based on ruby search path,
51
+ # but you may find that you need to add a require above.
30
52
  #
31
- # metric_fu will attempt to require a custom formatter by
32
- # fully qualified name based on ruby search path,
33
- # but you may find that you need to add a require above.
53
+ # For instance, to require a formatter in your app's lib directory, add the
54
+ # following line to the top of this file.
55
+ # require './lib/my_custom_formatter.rb'
34
56
  #
35
- # For instance, to require a formatter in your app's lib directory:
36
- # require './lib/my_custom_formatter.rb'
57
+ #
58
+ # Configure Graph Engine
59
+ #
60
+ # By default, metric_fu uses the bluff graph engine.
61
+ # To configure a different graph engine...
62
+ #
63
+ # config.configure_graph_engine(:gchart)
64
+ #
65
+ # end
data/.travis.yml CHANGED
@@ -9,6 +9,9 @@ gemfile:
9
9
  rvm:
10
10
  - 2.0.0
11
11
  - 1.9.3
12
- - 1.9.2
12
+ # - 1.9.2 # code_metric 0.1.0 requires ruby 1.9.3 or greater
13
13
  - jruby-19mode # JRuby in 1.9 mode
14
14
  - rbx-19mode
15
+ # matrix:
16
+ # allow_failures:
17
+ # - rvm: rbx-19mode
data/AUTHORS ADDED
@@ -0,0 +1,12 @@
1
+ Jake Scruggs
2
+ Sean Soper
3
+ Andre Arko
4
+ Petrik de Heus
5
+ Grant McInnes
6
+ Nick Quaranto
7
+ Édouard Brière
8
+ Carl Youngblood
9
+ Richard Huang
10
+ Dan Mayer
11
+ Benjamin Fleischer
12
+ Robin Curry
data/Gemfile CHANGED
@@ -15,5 +15,6 @@ group :test do
15
15
  gem 'simplecov-rcov-text'
16
16
  end
17
17
  gem "fakefs", :require => "fakefs/safe"
18
+ gem 'json'
18
19
  end
19
20
  gemspec :path => File.expand_path('..', __FILE__)
data/HISTORY.md CHANGED
@@ -10,6 +10,30 @@ As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch.
10
10
  * Fixes
11
11
  * Misc
12
12
 
13
+ ### MetricFu 4.4.0 / 2013-08-15
14
+
15
+ * Features
16
+ * Metrics now configure themselves in a subclass of MetricFu::Metric ( Benjamin Fleischer / Robin Curry #91, #111)
17
+ * Metrics can be configured individually via Metric.configuration.configure_metric(:some_metric) or Metric.configuration.configure_metrics {|metric| }. See .metrics file for examples ( Benjamin Fleischer / Robin Curry #91, #111)
18
+ * Distinguish between an activated metric library and an enabled metric.
19
+ * An enabled metric will be run.
20
+ * An activated metric has had its library successfully required. (Benjamin Fleischer #125)
21
+ * Code Statistics metrics always runs now, relies on the code_metrics gem extracted from Rails. Does not shell out. ( Benjamin Fleischer, #108 )
22
+ * Rails Best Practices report now provides a link to the description and solution of the problem (Calveto #117)
23
+ * Rails Best Practices now runs as a library. It is no longer shelled out. (Calveto #117)
24
+ * Update flog to ~> 4.1.1, this is needed to use keyword parameters in ruby 2. (George Erickson, #122)
25
+ * Fixes
26
+ * Skip reek when no files are found to run against. Otherwise, reek hangs trying to read from STDIN (Benjamin Fleischer, #119, #121)
27
+ * Reek will now find files on Windows. Remove *nix-specific '/' directory separators from Reek file glob. (Benjamin Fleischer, #119, #121)
28
+ * Link to correct reek url on report. (Calveto #116)
29
+ * Hack to accomodate Rails Best Practices dependency Code Analyzer monkey patch of Sexp (Benjamin Fleischer #123, #124)
30
+ * Misc
31
+ * Moved environmental concerns into an Environment module ( Benjamin Fleischer / Robin Curry #91, #111)
32
+ * Exposed RubyParser patch ( Benjamin Fleischer / Robin Curry #91, #111)
33
+ * Separated out io / filesystem /templating concerns into their own classes or modules. Thus, we removed all the metaprogrammatically defined methods and instance variables.( Benjamin Fleischer / Robin Curry #91, #111, #112, #115)
34
+ * Generator subclasses can now be found by metric name. MetricFu::Generator.get_generator(:flog) (Benjamin Fleischer, #126)
35
+ * Breaking change related to the above: removed configuration methods / MetricFu module methods: add_graph, add_metric, configure_graph, configure_metric, configure_graph_engine, graph_engine, metrics, formatters, graphs, graph_engines, rails?, code_dirs, base_directory, scratch_directory, output_directory, data_directory, file_globs_to_ignore, metric_fu_root_directory, template_directory, template_class, link_prefix, darwin_txmt_protocol_no_thanks, syntax_highlighting
36
+
13
37
  ### MetricFu 4.3.1 / 2013-08-02
14
38
 
15
39
  * Features
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
- # MetricFu [![Gem Version](https://badge.fury.io/rb/metric_fu.png)](http://badge.fury.io/rb/metric_fu) [![Build Status](https://travis-ci.org/metricfu/metric_fu.png?branch=master)](http://travis-ci.org/metricfu/metric_fu) [Rdoc](http://rdoc.info/github/metricfu/metric_fu/)
1
+ # MetricFu [![Gem Version](https://badge.fury.io/rb/metric_fu.png)](http://badge.fury.io/rb/metric_fu) [![Build Status](https://travis-ci.org/metricfu/metric_fu.png?branch=master)](http://travis-ci.org/metricfu/metric_fu)
2
2
 
3
3
  [![Code Climate](https://codeclimate.com/github/metricfu/metric_fu.png)](https://codeclimate.com/github/metricfu/metric_fu) [![Dependency Status](https://gemnasium.com/metricfu/metric_fu.png)](https://gemnasium.com/metricfu/metric_fu)
4
4
 
5
+ [Rdoc](http://rdoc.info/github/metricfu/metric_fu/)
6
+
5
7
  ## Metrics
6
8
 
7
9
  * [Cane](https://rubygems.org/gems/cane), [Source](http://github.com/square/cane)
@@ -10,13 +12,13 @@
10
12
  * [Flay](https://rubygems.org/gems/flay), [Source](https://github.com/seattlerb/flay)
11
13
  * [Reek](https://rubygems.org/gems/reek) [Source](https://github.com/troessner/reek)
12
14
  * [Roodi](https://rubygems.org/gems/metric_fu-roodi), [Source](https://github.com/metricfu/roodi)
13
- * [Saikuro](https://rubygems.org/gems/japgolly-Saikuro), [Source](https://github.com/japgolly/Saikuro)
15
+ * [Saikuro](https://rubygems.org/gems/metric_fu-Saikuro), [Source](https://github.com/metricfu/Saikuro)
16
+ [Code Statistics](https://rubygems.org/gems/code_metrics), [Source](https://github.com/bf4/code_metrics) )
14
17
  * Rails-only
15
18
  * [Rails Best Practices](https://rubygems.org/gems/rails_best_practices), [Source](https://github.com/railsbp/rails_best_practices)
16
- * Rails `rake stats` task (see [gem](https://rubygems.org/gems/code_statistics), [Source](https://github.com/danmayer/code_statistics) )
17
19
  * Test Coverage
18
20
  * 1.9: [SimpleCov](http://rubygems.org/gems/simplecov) and [SimpleCov-Rcov-Text](http://rubygems.org/gems/simplecov-rcov-text)
19
- * 1.8 [Rcov](http://rubygems.org/gems/rcov)
21
+ * 1.8: [Rcov](http://rubygems.org/gems/rcov)
20
22
  * Hotspots (a meta-metric of the above)
21
23
 
22
24
  ## Installation
@@ -29,25 +31,25 @@ See documentation on the rubyforge page for how to customize your metrics. Other
29
31
 
30
32
  ## Usage
31
33
 
32
- By default, you can run all metrics from the root of an app with the command `metric_fu -r`
34
+ By default, you can run all metrics from the root of an app with the command `metric_fu`
33
35
 
34
36
  See `metric_fu --help` for more options
35
37
 
36
38
  ## Compatibility
37
39
 
38
- * It is currently testing on MRI 1.9.2, 1.9.3 and 2.0.0. Ruby 1.8 is no longer supported due to the cane library.
40
+ * It is currently testing on MRI (1.9.3 and 2.0.0), JRuby (19 mode), and Rubinius (19 mode). Ruby 1.8 is no longer supported due to the cane library.
39
41
 
40
42
  * For 1.8.7 support, see version 3.0.0 for partial support, or 2.1.3.7.18.1 (where [Semantic Versioning](http://semver.org/) goes to die)
41
43
 
42
- * The `japgolly-Saikuro` fork and `metric_fu-roodi` fork are a part of an attempt to get metric_fu working in a modern Ruby environment, specifically compatibility with Ruby 1.9 and Bundler.
44
+ * The `metric_fu-Saikuro` fork and `metric_fu-roodi` fork are a part of an attempt to get metric_fu working in a modern Ruby environment, specifically compatibility with Ruby 1.9 and Bundler.
43
45
 
44
46
  * metric_fu no longer runs rcov itself. You may still use rcov metrics as documented below
45
47
 
46
- * The Cane, Flog, and Rails Best Practices metrics are disabled in non-MRI rubies as they depend on ripper
48
+ * The Cane, Flog, and Rails Best Practices metrics are disabled when Ripper is not available
47
49
 
48
50
  ## Documentation
49
51
 
50
- * Cane code quality threshold checking is not included in the hotspots report
52
+ *[See wiki](https://github.com/metricfu/metric_fu/wiki#usage)
51
53
 
52
54
  ## Formatters
53
55
 
@@ -115,15 +117,14 @@ see the .metrics file
115
117
  in your .metrics file add the below to run pre-generated metrics
116
118
 
117
119
  MetricFu::Configuration.run do |config|
118
- coverage_file = File.expand_path("coverage/rcov/rcov.txt", Dir.pwd)
119
- config.add_metric(:rcov)
120
- config.add_graph(:rcov)
121
- config.configure_metric(:rcov, {:external => coverage_file})
120
+ config.configure_metric(:rcov) do |rcov|
121
+ rcov.enabled = true
122
+ coverage_file = File.expand_path("coverage/rcov/rcov.txt", Dir.pwd)
123
+ rcov.external = coverage_file
124
+ end
122
125
  end
123
126
 
124
- if you want metric_fu to actually run rcov itself (1.8 only), just add
125
-
126
- MetricFu.run_rcov
127
+ If you want metric_fu to actually run rcov itself (1.8 only), don't specify an external file to read from
127
128
 
128
129
  #### Rcov metrics with Ruby 1.8
129
130
 
@@ -156,19 +157,23 @@ There is some useful-but-out-of-date documentation about configuring metric_fu a
156
157
 
157
158
  See the TODO for some ideas
158
159
 
159
- See CONTRIBUTING for how to contribute
160
+ See [CONTRIBUTING](https://github.com/metricfu/metric_fu/blob/master/CONTRIBUTING.md) for how to contribute
160
161
 
161
162
  ## Resources:
162
163
 
163
- This is the official repository for metric_fu. The original repository by Jake Scruggs at [https://github.com/jscruggs/metric_fu](https://github.com/jscruggs/metric_fu) [has been deprecated.](http://jakescruggs.blogspot.com/2012/08/why-i-abandoned-metricfu.html).
164
+ This is the official repository for metric_fu. The original repository by Jake Scruggs at [https://github.com/jscruggs/metric_fu](https://github.com/jscruggs/metric_fu) has been deprecated.
164
165
 
165
- * Github: http://github.com/metricfu/metric_fu
166
- * Issue Tracker: http://github.com/metricfu/metric_fu/issues
167
- * Google Group: http://groups.google.com/group/metric_fu
168
- * Historical Homepage: http://metric-fu.rubyforge.org/
166
+ * [Official Repository](http://github.com/metricfu/metric_fu)
167
+ * [Issue Tracker](http://metricfu.github.io/metric_fu/)
168
+ * [Google Group](http://metricfu.github.io/metric_fu/)
169
+ * [Outdated Homepage](http://metricfu.github.io/metric_fu/)
170
+ * [List of code tools](https://github.com/metricfu/metric_fu/wiki/Code-Tools)
171
+ * [Roadmap](https://github.com/metricfu/metric_fu/wiki/Roadmap)
169
172
 
170
173
  ### Original Resources:
171
174
 
172
175
  * Github: http://github.com/jscruggs/metric_fu
173
176
  * Issue Tracker: http://github.com/jscruggs/metric_fu/issues
177
+ * Historical Homepage: http://metric-fu.rubyforge.org/
174
178
  * Jake's Blog: http://jakescruggs.blogspot.com/
179
+ * Jake's Post about stepping down: http://jakescruggs.blogspot.com/2012/08/why-i-abandoned-metricfu.html
@@ -0,0 +1 @@
1
+ 8ceae4f1bb2719d8ecbe2c7b3e929fe477cbe4ea6582297092a1bc09a6bef9e423f3a33c619b62372b208f956c4d8f9839257cd491475b58c06a2c8341eafc77
@@ -0,0 +1 @@
1
+ 1f9be27229b5a441bc4e4367d099f6f92641d994246b88f9a396fc8c99d832a00412fe7c9a5dc5078c9beecc8d77d575d9b9ab55b50ab7b0b7583130763369bf
data/lib/metric_fu.rb CHANGED
@@ -1,98 +1,47 @@
1
+ require 'metric_fu/version'
1
2
  module MetricFu
2
3
  APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__),'..'))
3
4
  LIB_ROOT = File.join(APP_ROOT,'lib/metric_fu')
4
- @loaded_files = []
5
- class << self
6
- attr_reader :loaded_files
7
- end
8
- def self.lib_require(base='',&block)
9
- paths = []
10
- base_path = File.join(LIB_ROOT, base)
11
- Array((yield paths, base_path)).each do |path|
12
- file = File.join(base_path, *Array(path))
13
- require file
14
- if @loaded_files.include?(file)
15
- puts "!!!\tAlready loaded #{file}" if !!(ENV['MF_DEBUG'] =~ /true/i)
16
- else
17
- @loaded_files << file
18
- end
19
- end
20
- end
21
5
  def self.root_dir
22
6
  APP_ROOT
23
7
  end
24
8
  def self.lib_dir
25
9
  LIB_ROOT
26
10
  end
27
- class << self
28
- %w(metrics formatter reporting logging errors data_structures tasks).each do |dir|
29
- define_method("#{dir}_dir") do
30
- File.join(lib_dir,dir)
31
- end
32
- module_eval(%Q(def #{dir}_require(&block); lib_require('#{dir}', &block); end))
33
- end
11
+
12
+ require 'metric_fu/loader'
13
+ LOADER = MetricFu::Loader.new(LIB_ROOT)
14
+ def self.lib_require(base='',&block)
15
+ LOADER.lib_require(base,&block)
34
16
  end
35
- def self.tasks_load(tasks_relative_path)
36
- load File.join(LIB_ROOT, 'tasks', *Array(tasks_relative_path))
17
+
18
+ LOADER.create_dirs(self) do
19
+ %w(metrics formatter reporting logging errors data_structures tasks)
37
20
  end
38
- # path is relative to where the task is being run,
21
+
22
+ # @note artifact_dir is relative to where the task is being run,
39
23
  # not to the metric_fu library
24
+ require 'metric_fu/io'
40
25
  def self.artifact_dir
41
- (ENV['CC_BUILD_ARTIFACTS'] || 'tmp/metric_fu')
42
- end
43
- def self.configure
44
- MetricFu.lib_require { 'configuration' }
45
- init_files = Dir.glob(File.join(MetricFu.metrics_dir, '**/init.rb')).reject do |file|
46
- if file =~ /rcov/o
47
- MetricFu.configuration.mf_debug("rcov is not available. See README")
48
- true
49
- elsif MetricFu.configuration.mri?
50
- false
51
- elsif file =~ /cane/o
52
- MetricFu.configuration.mf_debug("Cane is only available in MRI. It requires ripper")
53
- true
54
- elsif file =~ /flog/o
55
- MetricFu.configuration.mf_debug("Flog is only available in MRI. It requires ripper")
56
- true
57
- elsif file =~ /rails_best_practices/o
58
- MetricFu.configuration.mf_debug("Rails Best Practices only available in MRI. It requires ripper")
59
- true
60
- else
61
- false
62
- end
63
- end
64
- init_files.each do |file|
65
- load file
66
- end
67
- MetricFu.configuration
26
+ MetricFu::Io::FileSystem.artifact_dir
68
27
  end
69
- def self.mri_only_metrics
70
- if MetricFu.configuration.mri?
71
- []
72
- else
73
- [:cane, :flog, :rails_best_practices]
74
- end
75
- end
76
- def self.run_rcov
77
- load File.join(MetricFu.metrics_dir, 'rcov/init.rb')
28
+
29
+ LOADER.create_artifact_subdirs(self) do
30
+ %w(scratch output _data)
78
31
  end
79
- def self.skip_rcov
80
- MetricFu.metrics -= [:rcov]
81
- MetricFu.graphs -= [:rcov]
32
+
33
+ def self.tasks_load(tasks_relative_path)
34
+ LOADER.load_tasks(tasks_relative_path)
82
35
  end
83
- class << self
84
- %w(scratch output _data).each do |dir|
85
- define_method("#{dir.gsub(/[^A-Za-z0-9]/,'')}_dir") do
86
- File.join(artifact_dir,dir)
87
- end
88
- end
89
36
 
37
+ LOADER.setup
38
+
39
+ def self.reset
40
+ # TODO Don't like how this method needs to know
41
+ # all of these class variables that are defined
42
+ # in separate classes.
43
+ @configuration = nil
44
+ @graph = nil
45
+ @result = nil
90
46
  end
91
- # def const_missing(name)
92
- #
93
- # end
94
47
  end
95
- MetricFu.lib_require { 'version' }
96
- MetricFu.lib_require { 'initial_requires' }
97
- # Load a few things to make our lives easier elsewhere.
98
- MetricFu.lib_require { 'load_files' }
@@ -32,7 +32,7 @@ module MetricFu
32
32
  end
33
33
 
34
34
  def metrics
35
- MetricFu.configuration.metrics.sort_by(&:to_s)
35
+ MetricFu::Metric.metrics.map(&:name).sort_by(&:to_s)
36
36
  end
37
37
 
38
38
  def process_options(argv=[])
@@ -54,7 +54,7 @@ module MetricFu
54
54
  "This option applies to the previously",
55
55
  "specified --format, or the default format",
56
56
  "if no format is specified. Paths are relative to",
57
- "#{Pathname.pwd.join(MetricFu.base_directory)}",
57
+ "#{Pathname.pwd.join(MetricFu::Io::FileSystem.directory('base_directory'))}",
58
58
  "Check the specific formatter\'s docs to see",
59
59
  "whether to pass a file or a dir.") do |o|
60
60
  @result[:format] ||= MetricFu::Formatter::DEFAULT
@@ -1,9 +1,8 @@
1
- require 'fileutils'
2
- require 'rbconfig'
3
- MetricFu.reporting_require { 'templates/awesome/awesome_template' }
4
1
  MetricFu.logging_require { 'mf_debugger' }
5
2
  module MetricFu
6
3
 
4
+ # Even though the below class methods are defined on the MetricFu module
5
+ # They are included here as they deal with configuration
7
6
 
8
7
  # The @configuration class variable holds a global type configuration
9
8
  # object for any parts of the system to use.
@@ -12,21 +11,29 @@ module MetricFu
12
11
  @configuration ||= Configuration.new
13
12
  end
14
13
 
14
+ def self.configure
15
+ Dir.glob(File.join(MetricFu.metrics_dir, '**/init.rb')).each{|init_file|require(init_file)}
16
+ Dir.glob(File.join(MetricFu.reporting_dir, '**/init.rb')).each{|init_file|require(init_file)}
17
+ configuration.tap do |config|
18
+ config.configure_metrics
19
+ end
20
+ end
21
+
22
+ # TODO: Remove this method. It is really a test concern for identifying
23
+ # metrics turned off for environmental reasons
24
+ def self.mri_only_metrics
25
+ if MetricFu.configuration.mri?
26
+ []
27
+ else
28
+ [:cane, :flog, :rails_best_practices]
29
+ end
30
+ end
31
+
15
32
  # = Configuration
16
33
  #
17
34
  # The Configuration class, as it sounds, provides methods for
18
35
  # configuring the behaviour of MetricFu.
19
36
  #
20
- # == Customization for Rails
21
- #
22
- # The Configuration class checks for the presence of a
23
- # 'config/environment.rb' file. If the file is present, it assumes
24
- # it is running in a Rails project. If it is, it will:
25
- #
26
- # * Add 'app' to the @code_dirs directory to include the
27
- # code in the app directory in the processing
28
- # * Add :stats and :rails_best_practices to the list of metrics to run
29
- #
30
37
  # == Customization for CruiseControl.rb
31
38
  #
32
39
  # The Configuration class checks for the presence of a
@@ -36,186 +43,133 @@ module MetricFu
36
43
  #
37
44
  # == Metric Configuration
38
45
  #
39
- # Each metric can be configured by e.g. config.churn, config.flog, config.saikuro
46
+ # Each metric can be configured by e.g.
47
+ # config.configure_metric(:flog) do |flog|
48
+ # flog.enable
49
+ # flog.dirs_to_flog = %w(app lib spec)
50
+ # ...
51
+ # end
52
+ #
53
+ # or iterate over all metrics to configure by e.g.
54
+ # config.configure_metrics.each do |metric|
55
+ # ...
56
+ # end
57
+ #
58
+ # == Formatter Configuration
59
+ #
60
+ # Formatters can be configured by e.g.
61
+ # config.configure_formatter(:html)
62
+ # config.configure_formatter(:yaml, "customreport.yml")
63
+ # config.configure_formatter(MyCustomFormatter)
64
+ #
65
+ # == Graph Configuration
66
+ #
67
+ # Graphing engine can be configured by e.g.
68
+ # config.configure_graph_engine(:bluff)
69
+ #
70
+ #
40
71
  class Configuration
72
+ require_relative 'environment'
73
+ require_relative 'io'
74
+ require_relative 'formatter'
75
+ # TODO: Remove need to include the module
76
+ include MetricFu::Environment
41
77
 
42
78
  def initialize #:nodoc:#
43
79
  reset
44
80
  end
45
81
 
46
- def verbose
47
- MfDebugger::Logger.debug_on
48
- end
49
-
50
- def verbose=(toggle)
51
- MfDebugger::Logger.debug_on = toggle
52
- end
53
-
54
82
  def mf_debug(msg)
55
83
  MfDebugger.mf_debug msg
56
84
  end
57
85
 
58
86
  # TODO review if these code is functionally duplicated in the
59
87
  # base generator initialize
88
+ attr_reader :formatters
60
89
  def reset
61
- set_directories
62
- configure_template
63
- add_promiscuous_instance_variable(:metrics, [])
64
- add_promiscuous_instance_variable(:formatters, [])
65
- add_promiscuous_instance_variable(:graphs, [])
66
- add_promiscuous_instance_variable(:graph_engines, [])
67
- add_promiscuous_method(:graph_engine)
90
+ # TODO: Remove calls to self and/or allow querying the
91
+ # template/filesystem/metric/graph/environment, etc settings
92
+ # from the configuration instance
93
+ MetricFu::Io::FileSystem.set_directories(self)
94
+ MetricFu::Formatter::Templates.configure_template(self)
95
+ @formatters = []
96
+ @graph_engine_config = MetricFu::GraphEngine.new
68
97
  end
69
98
 
70
99
  # This allows us to have a nice syntax like:
71
100
  #
72
101
  # MetricFu.run do |config|
73
- # config.base_directory = 'tmp/metric_fu'
102
+ # congif.configure_metric(:churn) do
103
+ # ...
104
+ # end
105
+ #
106
+ # config.configure_graph_engine(:bluff)
74
107
  # end
75
108
  #
76
109
  # See the README for more information on configuration options.
110
+ # TODO: Consider breaking compatibility by removing this, now unused method
77
111
  def self.run
78
112
  yield MetricFu.configuration
79
113
  end
80
114
 
81
- attr_accessor :metrics
82
- # e.g. :churn
83
- def add_metric(metric)
84
- add_promiscuous_method(metric)
85
- self.metrics = (metrics << metric).uniq
115
+ def configure_metric(name)
116
+ yield MetricFu::Metric.get_metric(name)
86
117
  end
87
118
 
88
- # e.g. :reek
89
- def add_graph(metric)
90
- add_promiscuous_method(metric)
91
- self.graphs = (graphs << metric).uniq
92
- end
93
-
94
- def add_formatter(format, output = nil)
95
- @formatters << MetricFu::Formatter.class_for(format).new(output: output)
96
- end
97
-
98
- # e.g. :reek, {}
99
- def configure_metric(metric, metric_configuration)
100
- add_promiscuous_instance_variable(metric, metric_configuration)
101
- end
102
-
103
- # e.g. :bluff
104
- def add_graph_engine(graph_engine)
105
- add_promiscuous_method(graph_engine)
106
- self.graph_engines = (graph_engines << graph_engine).uniq
107
- end
108
-
109
- # e.g. :bluff
110
- def configure_graph_engine(graph_engine)
111
- add_promiscuous_instance_variable(:graph_engine, graph_engine)
112
- end
113
-
114
- # Perform a simple check to try and guess if we're running
115
- # against a rails app.
116
- #
117
- # TODO This should probably be made a bit more robust.
118
- def rails?
119
- add_promiscuous_instance_variable(:rails, File.exist?("config/environment.rb"))
120
- end
121
-
122
- def is_cruise_control_rb?
123
- !!ENV['CC_BUILD_ARTIFACTS']
124
- end
125
-
126
- def jruby?
127
- @jruby ||= !!RedCard.check(:jruby)
128
- end
129
-
130
- def mri?
131
- @mri ||= !!RedCard.check(:ruby)
132
- end
133
-
134
- def rubinius?
135
- @rubinius ||= !!RedCard.check(:rubinius)
136
- end
137
-
138
- def platform #:nodoc:
139
- # TODO, change
140
- # RbConfig::CONFIG['ruby_install_name'].dup
141
- return RUBY_PLATFORM
142
- end
143
-
144
- def self.ruby_strangely_makes_accessors_private?
145
- ruby192? || jruby?
146
- end
147
-
148
- def self.ruby192?
149
- @ruby192 ||= !!RedCard.check('1.9.2')
119
+ def configure_metrics
120
+ MetricFu::Metric.metrics.each do |metric|
121
+ if block_given?
122
+ yield metric
123
+ elsif !metric_manually_configured?(metric)
124
+ metric.enabled = false
125
+ metric.enable
126
+ end
127
+ metric.activate if metric.enabled unless metric.activated
128
+ end
150
129
  end
151
130
 
152
- protected unless ruby_strangely_makes_accessors_private?
153
-
154
- def add_promiscuous_instance_variable(name,value)
155
- instance_variable_set("@#{name}", value)
156
- add_promiscuous_method(name)
157
- value
131
+ # TODO: Remove this method. If we run configure_metrics
132
+ # and it disabled rcov, we shouldn't have to worry here
133
+ # that rcov is a special case that can only be enabled
134
+ # manually
135
+ def metric_manually_configured?(metric)
136
+ [:rcov].include?(metric.name)
158
137
  end
159
138
 
160
- def add_promiscuous_method(method_name)
161
- add_promiscuous_class_method_to_metric_fu(method_name)
162
- add_accessor_to_config(method_name)
139
+ # TODO: Reconsider method name/behavior, as it really adds a formatter
140
+ def configure_formatter(format, output = nil)
141
+ @formatters << MetricFu::Formatter.class_for(format).new(output: output)
163
142
  end
164
143
 
165
- def add_promiscuous_class_method_to_metric_fu(method_name)
166
- metric_fu_method = <<-EOF
167
- def self.#{method_name}
168
- configuration.send(:#{method_name})
169
- end
170
- EOF
171
- MetricFu.module_eval(metric_fu_method)
144
+ # @return [Array<Symbol>] names of enabled metrics with graphs
145
+ def graphs
146
+ # TODO: This is a common enough need to be pushed into MetricFu::Metric as :enabled_metrics_with_graphs
147
+ MetricFu::Metric.enabled_metrics.select{|metric|metric.has_graph?}.map(&:name)
172
148
  end
173
149
 
150
+ # TODO: Consider if we need to delegate so much to graph_engine_config
151
+ # if we should use forwardable or change the api
174
152
 
175
- def add_accessor_to_config(method_name)
176
- self.class.send(:attr_accessor, method_name)
153
+ # @return [Array<Symbol>] names of available graph engines
154
+ # @example [:bluff, :gchart]
155
+ def graph_engines
156
+ @graph_engine_config.graph_engines
177
157
  end
178
158
 
179
- private
180
-
181
- def configure_template
182
- add_promiscuous_instance_variable(:template_class, AwesomeTemplate)
183
- add_promiscuous_instance_variable(:link_prefix, nil)
184
- add_promiscuous_instance_variable(:darwin_txmt_protocol_no_thanks, true)
185
- # turning off syntax_highlighting may avoid some UTF-8 issues
186
- add_promiscuous_instance_variable(:syntax_highlighting, true)
159
+ # @return [Symbol] the selected graph engine
160
+ def graph_engine
161
+ @graph_engine_config.graph_engine
187
162
  end
188
163
 
189
- def set_directories
190
- add_promiscuous_instance_variable(:base_directory,MetricFu.artifact_dir)
191
- add_promiscuous_instance_variable(:scratch_directory,MetricFu.scratch_dir)
192
- add_promiscuous_instance_variable(:output_directory,MetricFu.output_dir)
193
- add_promiscuous_instance_variable(:data_directory,MetricFu.data_dir)
194
- # due to behavior differences between ruby 1.8.7 and 1.9.3
195
- # this is good enough for now
196
- create_directories [base_directory, scratch_directory, output_directory]
197
-
198
- add_promiscuous_instance_variable(:metric_fu_root_directory,MetricFu.root_dir)
199
- add_promiscuous_instance_variable(:template_directory,
200
- File.join(metric_fu_root_directory,
201
- 'lib', 'templates'))
202
- add_promiscuous_instance_variable(:file_globs_to_ignore,[])
203
- set_code_dirs
164
+ # @param graph_engine [Symbol] the name of an available graph engine
165
+ def add_graph_engine(graph_engine)
166
+ @graph_engine_config.add_graph_engine(graph_engine)
204
167
  end
205
168
 
206
- def create_directories(*dirs)
207
- Array(*dirs).each do |dir|
208
- FileUtils.mkdir_p dir
209
- end
169
+ # @param graph_engine [Symbol] sets the selected graph engine to use
170
+ def configure_graph_engine(graph_engine)
171
+ @graph_engine_config.configure_graph_engine(graph_engine)
210
172
  end
211
173
 
212
- # Add the 'app' directory if we're running within rails.
213
- def set_code_dirs
214
- if rails?
215
- add_promiscuous_instance_variable(:code_dirs,['app', 'lib'])
216
- else
217
- add_promiscuous_instance_variable(:code_dirs,['lib'])
218
- end
219
- end
220
174
  end
221
175
  end