rferraz-churn 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem 'rake'
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rferraz-churn (0.0.16)
5
+ arrayfields (>= 4.7.4)
6
+ chronic (>= 0.2.3)
7
+ chronic (>= 0.2.3)
8
+ fattr (>= 2.2.0)
9
+ hirb (>= 0.5.0)
10
+ jeweler (>= 1.6.4)
11
+ json (>= 1.6.1)
12
+ json_pure
13
+ main
14
+ main (>= 4.6.0)
15
+ map (>= 4.3.0)
16
+ ruby_parser (>= 2.3.1)
17
+ ruby_parser (~> 2.3)
18
+ sexp_processor (>= 3.0.7)
19
+ sexp_processor (~> 3.0.3)
20
+
21
+ GEM
22
+ remote: http://rubygems.org/
23
+ specs:
24
+ arrayfields (4.7.4)
25
+ chronic (0.6.6)
26
+ fattr (2.2.0)
27
+ git (1.2.5)
28
+ hirb (0.6.0)
29
+ jeweler (1.6.4)
30
+ bundler (~> 1.0)
31
+ git (>= 1.2.5)
32
+ rake
33
+ json (1.6.4)
34
+ json_pure (1.6.4)
35
+ main (4.7.1)
36
+ map (5.2.0)
37
+ mocha (0.9.12)
38
+ rake (0.8.7)
39
+ ruby_parser (2.3.1)
40
+ sexp_processor (~> 3.0)
41
+ sexp_processor (3.0.10)
42
+ shoulda (2.11.3)
43
+ test-construct (1.2.0)
44
+
45
+ PLATFORMS
46
+ ruby
47
+
48
+ DEPENDENCIES
49
+ jeweler (~> 1.6.0)
50
+ mocha (~> 0.9.5)
51
+ rake
52
+ rferraz-churn!
53
+ shoulda
54
+ test-construct
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Dan Mayer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,123 @@
1
+ = churn
2
+
3
+ A Project to give the churn file, class, and method for a project for a given checkin
4
+ Over time the tool adds up the history of chruns to give the number of times a file, class, or method is changing during the life of a project.
5
+ Churn for files is immediate, but classes and methods requires buildings up a history using churn between revisions. The history is stored in ./tmp
6
+
7
+ Currently has full Git, Mercurial (hg), and Bazaar (bzr) support, and partial SVN support (supports only file level churn currently)
8
+
9
+ Authors:
10
+ * danmayer
11
+ * ajwalters
12
+ * cldwalker
13
+ * absurdhero
14
+
15
+ Execute with:
16
+ rake churn #after adding require 'lib/tasks/churn_tasks' to projects rakefile
17
+ churn
18
+
19
+ == Example Output
20
+ **********************************************************************
21
+ * Revision Changes
22
+ **********************************************************************
23
+ Files:
24
+ +-------------------------------+
25
+ | file |
26
+ +-------------------------------+
27
+ | Rakefile |
28
+ | lib/churn/churn_calculator.rb |
29
+ +-------------------------------+
30
+
31
+ Classes:
32
+ +-------------------------------+-----------------+
33
+ | file | klass |
34
+ +-------------------------------+-----------------+
35
+ | lib/churn/churn_calculator.rb | ChurnCalculator |
36
+ +-------------------------------+-----------------+
37
+
38
+ Methods:
39
+ +-------------------------------+-----------------+-------------------------------+
40
+ | file | klass | method |
41
+ +-------------------------------+-----------------+-------------------------------+
42
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#filters |
43
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#display_array |
44
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s |
45
+ +-------------------------------+-----------------+-------------------------------+
46
+
47
+ **********************************************************************
48
+ * Project Churn
49
+ **********************************************************************
50
+ Files:
51
+ +------------------------------------+---------------+
52
+ | file_path | times_changed |
53
+ +------------------------------------+---------------+
54
+ | lib/churn/churn_calculator.rb | 14 |
55
+ | README.rdoc | 7 |
56
+ | lib/tasks/churn_tasks.rb | 6 |
57
+ | Rakefile | 6 |
58
+ | lib/churn/git_analyzer.rb | 4 |
59
+ | VERSION | 4 |
60
+ | test/test_helper.rb | 4 |
61
+ | test/unit/churn_calculator_test.rb | 3 |
62
+ | test/churn_test.rb | 3 |
63
+ +------------------------------------+---------------+
64
+
65
+ Classes:
66
+ +-------------------------------+-----------------+---------------+
67
+ | file | klass | times_changed |
68
+ +-------------------------------+-----------------+---------------+
69
+ | lib/churn/churn_calculator.rb | ChurnCalculator | 1 |
70
+ | lib/churn/churn_calculator.rb | ChurnCalculator | 1 |
71
+ +-------------------------------+-----------------+---------------+
72
+
73
+ Methods:
74
+ +-------------------------------+-----------------+-----------------------------------------+---------------+
75
+ | file | klass | method | times_changed |
76
+ +-------------------------------+-----------------+-----------------------------------------+---------------+
77
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s | 1 |
78
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#display_array | 1 |
79
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#calculate_revision_data | 1 |
80
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#filters | 1 |
81
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#initialize | 1 |
82
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#filters | 1 |
83
+ | lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s | 1 |
84
+ +-------------------------------+-----------------+-----------------------------------------+---------------+
85
+
86
+
87
+ TODO:
88
+ * SVN only supports file, add full SVN support
89
+ * support bazaar, cvs, and darcs
90
+ * make storage directory configurable instead of using tmp
91
+ * allow passing in directories to churn, directories to ignore
92
+ * add a filter that allows for other files besides. *.rb
93
+ * ignore files pattern, so you can ignore things like vendor/, lib/, or docs/
94
+ * finish adding better documenation using YARD
95
+ * better man page formatting from README (switch to markdown?)
96
+ * rake task for building manpage (currently manually run ronn -b1 README.rdoc)
97
+ * bug that reports '/dev/null' as a file during revision changes
98
+ * don't output methods and classes on a commit that has none detected (css and view only commits, etc)
99
+
100
+ Executable Usage:
101
+ * 'gem install churn'
102
+ * go to project root run 'churn'
103
+
104
+ Rake Usage:
105
+ * 'gem install churn'
106
+ * on any project you want to use churn, add "require 'churn'" to your rake file
107
+ * run 'rake churn' to view the current output, file churn history is immediate, class and method churn builds up a history as it is run on each revision
108
+ * temporary files with class / method churn history are stored in /tmp, to clear churn history delete them
109
+
110
+ == Note on Patches/Pull Requests
111
+
112
+ * Fork the project.
113
+ * Make your feature addition or bug fix.
114
+ * Add tests for it. This is important so I don't break it in a
115
+ future version unintentionally.
116
+ * Commit, do not mess with rakefile, version, or history.
117
+ (if you want to have your own version, that is fine but
118
+ bump version in a commit by itself I can ignore when I pull)
119
+ * Send me a pull request. Bonus points for topic branches.
120
+
121
+ == Copyright
122
+
123
+ Copyright (c) 2010 Dan Mayer. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,96 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'lib/tasks/churn_tasks'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "churn"
9
+ gem.summary = %Q{Providing additional churn metrics over the original metric_fu churn}
10
+ gem.description = %Q{High method and class churn has been shown to have increased bug and error rates. This gem helps you know what is changing a lot so you can do additional testing, code review, or refactoring to try to tame the volatile code. }
11
+ gem.email = "dan@mayerdan.com"
12
+ gem.homepage = "http://github.com/danmayer/churn"
13
+ gem.authors = ["Dan Mayer"]
14
+ gem.add_development_dependency "shoulda"
15
+ gem.add_development_dependency "jeweler", '~> 1.6.0'
16
+ gem.add_development_dependency "test-construct"
17
+ gem.add_development_dependency "mocha", '~> 0.9.5'
18
+ gem.add_dependency "main"
19
+ gem.add_dependency "json_pure"
20
+ gem.add_dependency "chronic", '>= 0.2.3'
21
+ gem.add_dependency "sexp_processor", '~> 3.0.3'
22
+ gem.add_dependency "ruby_parser", '~> 2.3'
23
+ gem.add_dependency 'hirb'
24
+ gem.executables = ['churn']
25
+ end
26
+ rescue LoadError
27
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
28
+ end
29
+
30
+ begin
31
+ #for additional metrics, mostly Rcov which caliper doesn't do
32
+ require 'metric_fu'
33
+
34
+ MetricFu::Configuration.run do |config|
35
+ config.metrics = [:churn, :saikuro, :roodi, :flog, :flay, :reek, :roodi, :rcov, :hotspots]
36
+ config.graphs = [:roodi, :flog, :flay, :reek, :roodi, :rcov]
37
+
38
+ config.flay = { :dirs_to_flay => ['lib'] }
39
+ config.flog = { :dirs_to_flog => ['lib'] }
40
+ config.reek = { :dirs_to_reek => ['lib'] }
41
+ config.roodi = { :dirs_to_roodi => ['lib'] }
42
+ config.saikuro = { :output_directory => 'tmp/tmp_saikuro',
43
+ :input_directory => ['lib'],
44
+ :cyclo => "",
45
+ :filter_cyclo => "0",
46
+ :warn_cyclo => "5",
47
+ :error_cyclo => "7",
48
+ :formater => "text"} #this needs to be set to "text"
49
+ config.churn = { :start_date => "3 months ago", :minimum_churn_count => 10}
50
+ config.rcov = { :test_files => ['test/unit/**/*_test.rb'],
51
+ :rcov_opts => ["--sort coverage",
52
+ "--no-html",
53
+ "--text-coverage",
54
+ "--no-color",
55
+ "--profile",
56
+ "--exclude /gems/,spec"]}
57
+ end
58
+ rescue Exception
59
+ puts "metric_fu not working install it"
60
+ end
61
+
62
+ require 'rake/testtask'
63
+ Rake::TestTask.new(:test) do |test|
64
+ test.libs << 'lib' << 'test'
65
+ test.pattern = 'test/**/*_test.rb'
66
+ test.verbose = true
67
+ end
68
+
69
+ begin
70
+ require 'rcov/rcovtask'
71
+ Rcov::RcovTask.new do |test|
72
+ test.libs << 'test'
73
+ test.pattern = 'test/**/*_test.rb'
74
+ test.verbose = true
75
+ end
76
+ rescue LoadError
77
+ task :rcov do
78
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
79
+ end
80
+ end
81
+
82
+ task :default => :test
83
+
84
+ require 'rake/rdoctask'
85
+ Rake::RDocTask.new do |rdoc|
86
+ if File.exist?('VERSION')
87
+ version = File.read('VERSION')
88
+ else
89
+ version = ""
90
+ end
91
+
92
+ rdoc.rdoc_dir = 'rdoc'
93
+ rdoc.title = "churn #{version}"
94
+ rdoc.rdoc_files.include('README*')
95
+ rdoc.rdoc_files.include('lib/**/*.rb')
96
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.15
data/bin/churn ADDED
@@ -0,0 +1,32 @@
1
+ #! /usr/bin/env ruby
2
+ require 'main'
3
+ require 'yaml'
4
+
5
+ #example usage. In the root of a project 'churn', or 'churn --help'
6
+ Main do
7
+ option('minimum_churn_count', 'c') do
8
+ argument :required
9
+ cast :int
10
+ default 3
11
+ end
12
+
13
+ option('yaml', 'y') do
14
+ cast :boolean
15
+ default false
16
+ end
17
+
18
+ def report_churn(output_string)
19
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'churn', 'churn_calculator')
20
+ result = Churn::ChurnCalculator.new({:minimum_churn_count => params['minimum_churn_count'].value}).report(output_string)
21
+ unless output_string
22
+ result = YAML::dump(result)
23
+ end
24
+ result
25
+ end
26
+
27
+ def run
28
+ report = report_churn(!params['yaml'].value)
29
+ puts report
30
+ end
31
+
32
+ end
data/churn.gemspec ADDED
@@ -0,0 +1,123 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "rferraz-churn"
8
+ s.version = "0.0.16"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dan Mayer"]
12
+ s.date = "2011-11-22"
13
+ s.description = "High method and class churn has been shown to have increased bug and error rates. This gem helps you know what is changing a lot so you can do additional testing, code review, or refactoring to try to tame the volatile code. "
14
+ s.email = "dan@mayerdan.com"
15
+ s.executables = ["churn"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/churn",
29
+ "churn.gemspec",
30
+ "lib/churn.rb",
31
+ "lib/churn/bzr_analyzer.rb",
32
+ "lib/churn/churn_calculator.rb",
33
+ "lib/churn/churn_history.rb",
34
+ "lib/churn/git_analyzer.rb",
35
+ "lib/churn/hg_analyzer.rb",
36
+ "lib/churn/location_mapping.rb",
37
+ "lib/churn/source_control.rb",
38
+ "lib/churn/svn_analyzer.rb",
39
+ "lib/tasks/churn_tasks.rb",
40
+ "man/churn.1",
41
+ "man/churn.html",
42
+ "test/data/churn_calculator.rb",
43
+ "test/data/test_helper.rb",
44
+ "test/test_helper.rb",
45
+ "test/unit/bzr_analyzer_test.rb",
46
+ "test/unit/churn_calculator_test.rb",
47
+ "test/unit/churn_history_test.rb",
48
+ "test/unit/git_analyzer_test.rb",
49
+ "test/unit/hg_analyzer_test.rb",
50
+ "test/unit/location_mapping_test.rb"
51
+ ]
52
+ s.homepage = "http://github.com/danmayer/churn"
53
+ s.require_paths = ["lib"]
54
+ s.rubygems_version = "1.8.10"
55
+ s.summary = "Providing additional churn metrics over the original metric_fu churn"
56
+
57
+ if s.respond_to? :specification_version then
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
+ s.add_runtime_dependency(%q<arrayfields>, [">= 4.7.4"])
62
+ s.add_runtime_dependency(%q<chronic>, [">= 0.2.3"])
63
+ s.add_runtime_dependency(%q<fattr>, [">= 2.2.0"])
64
+ s.add_runtime_dependency(%q<hirb>, [">= 0.5.0"])
65
+ s.add_runtime_dependency(%q<jeweler>, [">= 1.6.4"])
66
+ s.add_runtime_dependency(%q<json>, [">= 1.6.1"])
67
+ s.add_runtime_dependency(%q<main>, [">= 4.6.0"])
68
+ s.add_runtime_dependency(%q<map>, [">= 4.3.0"])
69
+ s.add_runtime_dependency(%q<ruby_parser>, [">= 2.3.1"])
70
+ s.add_runtime_dependency(%q<sexp_processor>, [">= 3.0.7"])
71
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
72
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
73
+ s.add_development_dependency(%q<test-construct>, [">= 0"])
74
+ s.add_development_dependency(%q<mocha>, ["~> 0.9.5"])
75
+ s.add_runtime_dependency(%q<main>, [">= 0"])
76
+ s.add_runtime_dependency(%q<json_pure>, [">= 0"])
77
+ s.add_runtime_dependency(%q<chronic>, [">= 0.2.3"])
78
+ s.add_runtime_dependency(%q<sexp_processor>, ["~> 3.0.3"])
79
+ s.add_runtime_dependency(%q<ruby_parser>, ["~> 2.3"])
80
+ else
81
+ s.add_dependency(%q<arrayfields>, [">= 4.7.4"])
82
+ s.add_dependency(%q<chronic>, [">= 0.2.3"])
83
+ s.add_dependency(%q<fattr>, [">= 2.2.0"])
84
+ s.add_dependency(%q<hirb>, [">= 0.5.0"])
85
+ s.add_dependency(%q<jeweler>, [">= 1.6.4"])
86
+ s.add_dependency(%q<json>, [">= 1.6.1"])
87
+ s.add_dependency(%q<main>, [">= 4.6.0"])
88
+ s.add_dependency(%q<map>, [">= 4.3.0"])
89
+ s.add_dependency(%q<ruby_parser>, [">= 2.3.1"])
90
+ s.add_dependency(%q<sexp_processor>, [">= 3.0.7"])
91
+ s.add_dependency(%q<shoulda>, [">= 0"])
92
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
93
+ s.add_dependency(%q<test-construct>, [">= 0"])
94
+ s.add_dependency(%q<mocha>, ["~> 0.9.5"])
95
+ s.add_dependency(%q<main>, [">= 0"])
96
+ s.add_dependency(%q<json_pure>, [">= 0"])
97
+ s.add_dependency(%q<chronic>, [">= 0.2.3"])
98
+ s.add_dependency(%q<sexp_processor>, ["~> 3.0.3"])
99
+ s.add_dependency(%q<ruby_parser>, ["~> 2.3"])
100
+ end
101
+ else
102
+ s.add_dependency(%q<arrayfields>, [">= 4.7.4"])
103
+ s.add_dependency(%q<chronic>, [">= 0.2.3"])
104
+ s.add_dependency(%q<fattr>, [">= 2.2.0"])
105
+ s.add_dependency(%q<hirb>, [">= 0.5.0"])
106
+ s.add_dependency(%q<jeweler>, [">= 1.6.4"])
107
+ s.add_dependency(%q<json>, [">= 1.6.1"])
108
+ s.add_dependency(%q<main>, [">= 4.6.0"])
109
+ s.add_dependency(%q<map>, [">= 4.3.0"])
110
+ s.add_dependency(%q<ruby_parser>, [">= 2.3.1"])
111
+ s.add_dependency(%q<sexp_processor>, [">= 3.0.7"])
112
+ s.add_dependency(%q<shoulda>, [">= 0"])
113
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
114
+ s.add_dependency(%q<test-construct>, [">= 0"])
115
+ s.add_dependency(%q<mocha>, ["~> 0.9.5"])
116
+ s.add_dependency(%q<main>, [">= 0"])
117
+ s.add_dependency(%q<json_pure>, [">= 0"])
118
+ s.add_dependency(%q<chronic>, [">= 0.2.3"])
119
+ s.add_dependency(%q<sexp_processor>, ["~> 3.0.3"])
120
+ s.add_dependency(%q<ruby_parser>, ["~> 2.3"])
121
+ end
122
+ end
123
+
@@ -0,0 +1,31 @@
1
+ module Churn
2
+
3
+ #analizes Bzr / Bazaar SCM to find recently changed files, and what lines have been altered
4
+ class BzrAnalyzer < SourceControl
5
+ def get_logs
6
+ `bzr log -v --short #{date_range}`.split("\n").reject{|line| line !~ /^[ ]*(M|A) /}.map{|line| line.strip.split(" ")[1..-1]}.flatten
7
+ end
8
+
9
+ def get_revisions
10
+ `bzr log --line #{date_range}`.split("\n").map{|line| line[/^(\S+):/, 1] }
11
+ end
12
+
13
+ private
14
+
15
+ def get_diff(revision, previous_revision)
16
+ `bzr diff -r #{previous_revision}..#{revision}`.split(/\n/).select{|line| line.match(/^@@/) || line.match(/^---/) || line.match(/^\+\+\+/) }
17
+ end
18
+
19
+ def date_range
20
+ if @start_date
21
+ date = Chronic.parse(@start_date)
22
+ "-r #{date.strftime('%Y-%m-%d')}.."
23
+ end
24
+ end
25
+
26
+ def get_recent_file(line)
27
+ super(line).split("\t")[0]
28
+ end
29
+
30
+ end
31
+ end