churn 0.0.20 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +45 -0
- data/README.md +147 -0
- data/VERSION +1 -1
- data/bin/churn +8 -2
- data/churn.gemspec +4 -22
- data/lib/churn/churn_calculator.rb +18 -15
- data/lib/tasks/churn_tasks.rb +5 -1
- data/test/unit/churn_calculator_test.rb +21 -7
- metadata +16 -88
- data/README.rdoc +0 -123
data/Gemfile.lock
CHANGED
@@ -1,8 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
churn (0.0.20)
|
5
|
+
chronic (>= 0.2.3)
|
6
|
+
churn
|
7
|
+
hirb
|
8
|
+
json_pure
|
9
|
+
main
|
10
|
+
ruby_parser (~> 2.3)
|
11
|
+
sexp_processor (~> 3.0)
|
12
|
+
|
1
13
|
GEM
|
2
14
|
remote: http://rubygems.org/
|
3
15
|
specs:
|
16
|
+
arrayfields (4.7.4)
|
17
|
+
chronic (0.7.0)
|
18
|
+
fattr (2.2.1)
|
19
|
+
git (1.2.5)
|
20
|
+
hirb (0.7.0)
|
21
|
+
jeweler (1.8.4)
|
22
|
+
bundler (~> 1.0)
|
23
|
+
git (>= 1.2.5)
|
24
|
+
rake
|
25
|
+
rdoc
|
26
|
+
json (1.7.5)
|
27
|
+
json_pure (1.7.5)
|
28
|
+
main (5.1.0)
|
29
|
+
arrayfields (>= 4.7.4)
|
30
|
+
chronic (>= 0.6.2)
|
31
|
+
fattr (>= 2.2.0)
|
32
|
+
map (>= 5.1.0)
|
33
|
+
map (6.2.0)
|
34
|
+
mocha (0.9.12)
|
35
|
+
rake (0.9.2.2)
|
36
|
+
rdoc (3.12)
|
37
|
+
json (~> 1.4)
|
38
|
+
ruby_parser (2.3.1)
|
39
|
+
sexp_processor (~> 3.0)
|
40
|
+
sexp_processor (3.2.0)
|
41
|
+
shoulda (2.11.3)
|
42
|
+
test-construct (1.2.0)
|
4
43
|
|
5
44
|
PLATFORMS
|
6
45
|
ruby
|
7
46
|
|
8
47
|
DEPENDENCIES
|
48
|
+
churn!
|
49
|
+
jeweler
|
50
|
+
mocha (~> 0.9.5)
|
51
|
+
rake
|
52
|
+
shoulda
|
53
|
+
test-construct
|
data/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
__churn__
|
2
|
+
|
3
|
+
A Project to give the churn file, class, and method for a project for a given checkin. 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.
|
4
|
+
Churn for files is immediate, but classes and methods requires buildings up a history using churn between revisions. The history is stored in ./tmp
|
5
|
+
|
6
|
+
Currently has full Git, Mercurial (hg), and Bazaar (bzr) support, and partial SVN support (supports only file level churn currently)
|
7
|
+
|
8
|
+
Authors:
|
9
|
+
|
10
|
+
* danmayer
|
11
|
+
* ajwalters
|
12
|
+
* cldwalker
|
13
|
+
* absurdhero
|
14
|
+
|
15
|
+
__Churn Usage__
|
16
|
+
Install with `gem install churn` or for bundler add to your Gemfile `gem 'churn'`
|
17
|
+
|
18
|
+
* rake:
|
19
|
+
* add `require 'churn'` to Rakefile
|
20
|
+
* then run`rake churn` or `bundle exec rake churn`
|
21
|
+
* use environment variables to control churn defaults
|
22
|
+
|
23
|
+
ENV['CHURN_MINIMUM_CHURN_COUNT']
|
24
|
+
ENV['CHURN_START_DATE']
|
25
|
+
ENV['CHURN_IGNORE_FILES']
|
26
|
+
|
27
|
+
* CLI:
|
28
|
+
* on command line run `churn` or `bundle exec churn`
|
29
|
+
* need help run `churn -h` to get additional information
|
30
|
+
* run the executable passing in options to override defaults
|
31
|
+
|
32
|
+
churn -i "churn.gemspec, Gemfile" #ignore files
|
33
|
+
churn -y #output yaml format opposed to text
|
34
|
+
churn -c 10 #set minimum churn count on a file to 10
|
35
|
+
churn -c 5 -y -i "Gemfile" #mix and match
|
36
|
+
|
37
|
+
|
38
|
+
__Example Output__
|
39
|
+
|
40
|
+
**********************************************************************
|
41
|
+
* Revision Changes
|
42
|
+
**********************************************************************
|
43
|
+
Files:
|
44
|
+
+-------------------------------+
|
45
|
+
| file |
|
46
|
+
+-------------------------------+
|
47
|
+
| Rakefile |
|
48
|
+
| lib/churn/churn_calculator.rb |
|
49
|
+
+-------------------------------+
|
50
|
+
|
51
|
+
Classes:
|
52
|
+
+-------------------------------+-----------------+
|
53
|
+
| file | klass |
|
54
|
+
+-------------------------------+-----------------+
|
55
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator |
|
56
|
+
+-------------------------------+-----------------+
|
57
|
+
|
58
|
+
Methods:
|
59
|
+
+-------------------------------+----------------- +-------------------------------+
|
60
|
+
| file | klass | method |
|
61
|
+
+-------------------------------+-----------------+-------------------------------+
|
62
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#filters |
|
63
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#display_array |
|
64
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s |
|
65
|
+
+-------------------------------+-----------------+-------------------------------+
|
66
|
+
|
67
|
+
**********************************************************************
|
68
|
+
* Project Churn
|
69
|
+
**********************************************************************
|
70
|
+
Files:
|
71
|
+
+------------------------------------+---------------+
|
72
|
+
| file_path | times_changed |
|
73
|
+
+------------------------------------+---------------+
|
74
|
+
| lib/churn/churn_calculator.rb | 14 |
|
75
|
+
| README.rdoc | 7 |
|
76
|
+
| lib/tasks/churn_tasks.rb | 6 |
|
77
|
+
| Rakefile | 6 |
|
78
|
+
| lib/churn/git_analyzer.rb | 4 |
|
79
|
+
| VERSION | 4 |
|
80
|
+
| test/test_helper.rb | 4 |
|
81
|
+
| test/unit/churn_calculator_test.rb | 3 |
|
82
|
+
| test/churn_test.rb | 3 |
|
83
|
+
+------------------------------------+---------------+
|
84
|
+
|
85
|
+
Classes:
|
86
|
+
+-------------------------------+-----------------+---------------+
|
87
|
+
| file | klass | times_changed |
|
88
|
+
+-------------------------------+-----------------+---------------+
|
89
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | 1 |
|
90
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | 1 |
|
91
|
+
+-------------------------------+-----------------+---------------+
|
92
|
+
|
93
|
+
Methods:
|
94
|
+
+-------------------------------+-----------------+-----------------------------------------+---------------+
|
95
|
+
| file | klass | method | times_changed |
|
96
|
+
+-------------------------------+-----------------+-----------------------------------------+---------------+
|
97
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s | 1 |
|
98
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#display_array | 1 |
|
99
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#calculate_revision_data | 1 |
|
100
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#filters | 1 |
|
101
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#initialize | 1 |
|
102
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#filters | 1 |
|
103
|
+
| lib/churn/churn_calculator.rb | ChurnCalculator | ChurnCalculator#to_s | 1 |
|
104
|
+
+-------------------------------+-----------------+-----------------------------------------+---------------+
|
105
|
+
|
106
|
+
__Options__
|
107
|
+
|
108
|
+
[~/projects/churn] churn -h
|
109
|
+
NAME
|
110
|
+
churn
|
111
|
+
|
112
|
+
SYNOPSIS
|
113
|
+
churn [options]+
|
114
|
+
|
115
|
+
PARAMETERS
|
116
|
+
--minimum_churn_count=minimum_churn_count, -c (0 ~>
|
117
|
+
int(minimum_churn_count=3))
|
118
|
+
--yaml, -y
|
119
|
+
--ignore_files=[ignore_files], -i (0 ~> string(ignore_files=))
|
120
|
+
--help, -h
|
121
|
+
|
122
|
+
__TODO:__
|
123
|
+
|
124
|
+
* SVN only supports file, add full SVN support
|
125
|
+
* support bazaar, cvs, and darcs
|
126
|
+
* make storage directory configurable instead of using tmp
|
127
|
+
* allow passing in directories to churn, directories to ignore
|
128
|
+
* add a filter that allows for other files besides. *.rb
|
129
|
+
* ignore files pattern, so you can ignore things like vendor/, lib/, or docs/
|
130
|
+
* finish adding better documenation using YARD
|
131
|
+
* rake task for building manpage (currently manually run ronn -b1 README.rdoc)
|
132
|
+
* don't output methods and classes on a commit that has none detected (css and view only commits, etc)
|
133
|
+
|
134
|
+
__Notes on Patches/Pull Requests__
|
135
|
+
|
136
|
+
* Fork the project.
|
137
|
+
* Make your feature addition or bug fix.
|
138
|
+
* Add tests for it. This is important so I don't break it in a
|
139
|
+
future version unintentionally.
|
140
|
+
* Commit, do not mess with rakefile, version, or history.
|
141
|
+
(if you want to have your own version, that is fine but
|
142
|
+
bump version in a commit by itself I can ignore when I pull)
|
143
|
+
* Send me a pull request. Bonus points for topic branches.
|
144
|
+
|
145
|
+
__Copyright__
|
146
|
+
|
147
|
+
Copyright (c) 2012 Dan Mayer. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.21
|
data/bin/churn
CHANGED
@@ -15,9 +15,15 @@ Main do
|
|
15
15
|
default false
|
16
16
|
end
|
17
17
|
|
18
|
+
option('ignore_files', 'i') do
|
19
|
+
cast :string
|
20
|
+
argument :optional
|
21
|
+
default ''
|
22
|
+
end
|
23
|
+
|
18
24
|
def report_churn(output_string)
|
19
25
|
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)
|
26
|
+
result = Churn::ChurnCalculator.new({:minimum_churn_count => params['minimum_churn_count'].value, :ignore_files => params['ignore_files'].value}).report(output_string)
|
21
27
|
unless output_string
|
22
28
|
result = YAML::dump(result)
|
23
29
|
end
|
@@ -29,4 +35,4 @@ Main do
|
|
29
35
|
puts report
|
30
36
|
end
|
31
37
|
|
32
|
-
end
|
38
|
+
end
|
data/churn.gemspec
CHANGED
@@ -5,24 +5,24 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "churn"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.21"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Dan Mayer"]
|
12
|
-
s.date = "2012-09-
|
12
|
+
s.date = "2012-09-14"
|
13
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
14
|
s.email = "dan@mayerdan.com"
|
15
15
|
s.executables = ["churn"]
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"LICENSE",
|
18
|
-
"README.
|
18
|
+
"README.md"
|
19
19
|
]
|
20
20
|
s.files = [
|
21
21
|
".document",
|
22
22
|
"Gemfile",
|
23
23
|
"Gemfile.lock",
|
24
24
|
"LICENSE",
|
25
|
-
"README.
|
25
|
+
"README.md",
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"bin/churn",
|
@@ -58,12 +58,6 @@ Gem::Specification.new do |s|
|
|
58
58
|
s.specification_version = 3
|
59
59
|
|
60
60
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
61
|
-
s.add_runtime_dependency(%q<churn>, [">= 0"])
|
62
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
63
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
64
|
-
s.add_development_dependency(%q<test-construct>, [">= 0"])
|
65
|
-
s.add_development_dependency(%q<rake>, [">= 0"])
|
66
|
-
s.add_development_dependency(%q<mocha>, ["~> 0.9.5"])
|
67
61
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
68
62
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
69
63
|
s.add_development_dependency(%q<test-construct>, [">= 0"])
|
@@ -76,12 +70,6 @@ Gem::Specification.new do |s|
|
|
76
70
|
s.add_runtime_dependency(%q<ruby_parser>, ["~> 2.3"])
|
77
71
|
s.add_runtime_dependency(%q<hirb>, [">= 0"])
|
78
72
|
else
|
79
|
-
s.add_dependency(%q<churn>, [">= 0"])
|
80
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
81
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
82
|
-
s.add_dependency(%q<test-construct>, [">= 0"])
|
83
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
84
|
-
s.add_dependency(%q<mocha>, ["~> 0.9.5"])
|
85
73
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
86
74
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
87
75
|
s.add_dependency(%q<test-construct>, [">= 0"])
|
@@ -95,12 +83,6 @@ Gem::Specification.new do |s|
|
|
95
83
|
s.add_dependency(%q<hirb>, [">= 0"])
|
96
84
|
end
|
97
85
|
else
|
98
|
-
s.add_dependency(%q<churn>, [">= 0"])
|
99
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
100
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
101
|
-
s.add_dependency(%q<test-construct>, [">= 0"])
|
102
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
103
|
-
s.add_dependency(%q<mocha>, ["~> 0.9.5"])
|
104
86
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
105
87
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
106
88
|
s.add_dependency(%q<test-construct>, [">= 0"])
|
@@ -25,7 +25,9 @@ module Churn
|
|
25
25
|
def initialize(options={})
|
26
26
|
start_date = options.fetch(:start_date) { '3 months ago' }
|
27
27
|
@minimum_churn_count = options.fetch(:minimum_churn_count) { 5 }
|
28
|
-
@
|
28
|
+
@ignore_files = (options.fetch(:ignore_files){ "" }).split(',').map(&:strip)
|
29
|
+
@ignore_files << '/dev/null'
|
30
|
+
@source_control = set_source_control(start_date)
|
29
31
|
@changes = {}
|
30
32
|
@revision_changes = {}
|
31
33
|
@class_changes = {}
|
@@ -37,16 +39,16 @@ module Churn
|
|
37
39
|
# @param [Bolean] format to return the data, true for string or false for hash
|
38
40
|
# @return [Object] returns either a pretty string or a hash representing the chrun of the project
|
39
41
|
def report(print = true)
|
40
|
-
self.emit
|
42
|
+
self.emit
|
41
43
|
self.analyze
|
42
44
|
print ? self.to_s : self.to_h
|
43
45
|
end
|
44
|
-
|
46
|
+
|
45
47
|
# Emits various data from source control to be analyses later... Currently this is broken up like this as a throwback to metric_fu
|
46
48
|
def emit
|
47
|
-
@changes = parse_log_for_changes.reject {|file, change_count| change_count < @minimum_churn_count}
|
48
|
-
@revisions = parse_log_for_revision_changes
|
49
|
-
end
|
49
|
+
@changes = parse_log_for_changes.reject {|file, change_count| change_count < @minimum_churn_count || @ignore_files.include?(file) }
|
50
|
+
@revisions = parse_log_for_revision_changes
|
51
|
+
end
|
50
52
|
|
51
53
|
# Analyze the source control data, filter, sort, and find more information on the editted files
|
52
54
|
def analyze
|
@@ -83,7 +85,7 @@ module Churn
|
|
83
85
|
# Pretty print the data as a string for the user
|
84
86
|
def to_s
|
85
87
|
hash = to_h[:churn]
|
86
|
-
result = seperator
|
88
|
+
result = seperator
|
87
89
|
result +="* Revision Changes \n"
|
88
90
|
result += seperator
|
89
91
|
result += "Files: \n"
|
@@ -92,7 +94,7 @@ module Churn
|
|
92
94
|
result += display_array(hash[:changed_classes])
|
93
95
|
result += "\nMethods: \n"
|
94
96
|
result += display_array(hash[:changed_methods]) + "\n"
|
95
|
-
result += seperator
|
97
|
+
result += seperator
|
96
98
|
result +="* Project Churn \n"
|
97
99
|
result += seperator
|
98
100
|
result += "Files: \n"
|
@@ -106,7 +108,7 @@ module Churn
|
|
106
108
|
end
|
107
109
|
|
108
110
|
private
|
109
|
-
|
111
|
+
|
110
112
|
def collect_items(collection, match)
|
111
113
|
collection.map {|item| (item.delete(match) || {}).merge(item) }
|
112
114
|
end
|
@@ -165,14 +167,14 @@ module Churn
|
|
165
167
|
end
|
166
168
|
calculate_changes!(changed_methods, @method_changes) if changed_methods
|
167
169
|
calculate_changes!(changed_classes, @class_changes) if changed_classes
|
168
|
-
|
170
|
+
|
169
171
|
@revision_changes[revision] = { :files => changed_files, :classes => changed_classes, :methods => changed_methods }
|
170
172
|
end
|
171
173
|
end
|
172
174
|
|
173
175
|
def calculate_revision_data(revision)
|
174
176
|
changed_files = parse_logs_for_updated_files(revision, @revisions)
|
175
|
-
|
177
|
+
|
176
178
|
changed_classes = []
|
177
179
|
changed_methods = []
|
178
180
|
changed_files.each do |file_changes|
|
@@ -225,10 +227,10 @@ module Churn
|
|
225
227
|
end
|
226
228
|
changed_items
|
227
229
|
end
|
228
|
-
|
230
|
+
|
229
231
|
def parse_log_for_changes
|
230
232
|
changes = {}
|
231
|
-
|
233
|
+
|
232
234
|
logs = @source_control.get_logs
|
233
235
|
logs.each do |line|
|
234
236
|
changes[line] ? changes[line] += 1 : changes[line] = 1
|
@@ -240,11 +242,12 @@ module Churn
|
|
240
242
|
return [] unless @source_control.respond_to?(:get_revisions)
|
241
243
|
@source_control.get_revisions
|
242
244
|
end
|
243
|
-
|
245
|
+
|
244
246
|
def parse_logs_for_updated_files(revision, revisions)
|
245
247
|
#TODO SVN doesn't support this
|
246
248
|
return {} unless @source_control.respond_to?(:get_updated_files_change_info)
|
247
|
-
@source_control.get_updated_files_change_info(revision, revisions)
|
249
|
+
files = @source_control.get_updated_files_change_info(revision, revisions)
|
250
|
+
files.select{ |file, value| !@ignore_files.include?(file) }
|
248
251
|
end
|
249
252
|
|
250
253
|
end
|
data/lib/tasks/churn_tasks.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
def report_churn()
|
2
2
|
require File.join(File.dirname(__FILE__), '..', 'churn', 'churn_calculator')
|
3
|
-
Churn::ChurnCalculator.new({
|
3
|
+
Churn::ChurnCalculator.new({
|
4
|
+
:minimum_churn_count => ENV['CHURN_MINIMUM_CHURN_COUNT'],
|
5
|
+
:start_date => ENV['CHURN_START_DATE'],
|
6
|
+
:ignore_files => ENV['CHURN_IGNORE_FILES'],
|
7
|
+
}).report
|
4
8
|
end
|
5
9
|
|
6
10
|
desc "Report the current churn for the project"
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
2
2
|
|
3
3
|
class ChurnCalculatorTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
should "use minimum churn count" do
|
6
6
|
within_construct do |container|
|
7
7
|
Churn::ChurnCalculator.stubs(:git?).returns(true)
|
8
8
|
churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
|
9
|
-
|
9
|
+
|
10
10
|
churn.stubs(:parse_log_for_changes).returns([['file.rb', 4],['less.rb',1]])
|
11
11
|
churn.stubs(:parse_log_for_revision_changes).returns(['revision'])
|
12
12
|
churn.stubs(:analyze)
|
@@ -16,11 +16,25 @@ class ChurnCalculatorTest < Test::Unit::TestCase
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
should "use ignore_files filter" do
|
20
|
+
within_construct do |container|
|
21
|
+
Churn::ChurnCalculator.stubs(:git?).returns(true)
|
22
|
+
churn = Churn::ChurnCalculator.new({:ignore_files => "file.rb"})
|
23
|
+
|
24
|
+
churn.stubs(:parse_log_for_changes).returns([['file.rb', 10],['new.rb',11]])
|
25
|
+
churn.stubs(:parse_log_for_revision_changes).returns(['revision'])
|
26
|
+
churn.stubs(:analyze)
|
27
|
+
report = churn.report(false)
|
28
|
+
assert_equal 1, report[:churn][:changes].length
|
29
|
+
assert_equal ["new.rb", 11], report[:churn][:changes].first
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
19
33
|
should "analize sorts changes" do
|
20
34
|
within_construct do |container|
|
21
35
|
Churn::ChurnCalculator.stubs(:git?).returns(true)
|
22
36
|
churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
|
23
|
-
|
37
|
+
|
24
38
|
churn.stubs(:parse_log_for_changes).returns([['file.rb', 4],['most.rb', 9],['less.rb',1]])
|
25
39
|
churn.stubs(:parse_log_for_revision_changes).returns(['revision'])
|
26
40
|
report = churn.report(false)
|
@@ -36,7 +50,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
|
|
36
50
|
within_construct do |container|
|
37
51
|
Churn::ChurnCalculator.stubs(:git?).returns(true)
|
38
52
|
churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
|
39
|
-
|
53
|
+
|
40
54
|
churn.stubs(:parse_log_for_changes).returns([['less.rb',1]])
|
41
55
|
churn.stubs(:parse_log_for_revision_changes).returns(['first'])
|
42
56
|
churn.stubs(:parse_logs_for_updated_files).returns({'fake_file.rb'=>[]})
|
@@ -49,7 +63,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
|
|
49
63
|
within_construct do |container|
|
50
64
|
Churn::ChurnCalculator.stubs(:git?).returns(true)
|
51
65
|
churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
|
52
|
-
|
66
|
+
|
53
67
|
churn.stubs(:parse_log_for_changes).returns([['less.rb',1]])
|
54
68
|
churn.stubs(:parse_log_for_revision_changes).returns(['first'])
|
55
69
|
churn.stubs(:parse_logs_for_updated_files).returns({'fake_file.rb'=>[]})
|
@@ -66,7 +80,7 @@ class ChurnCalculatorTest < Test::Unit::TestCase
|
|
66
80
|
within_construct do |container|
|
67
81
|
Churn::ChurnCalculator.stubs(:git?).returns(true)
|
68
82
|
churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
|
69
|
-
|
83
|
+
|
70
84
|
churn.stubs(:parse_log_for_changes).returns([['less.rb',1]])
|
71
85
|
churn.stubs(:parse_log_for_revision_changes).returns(['first'])
|
72
86
|
churn.stubs(:parse_logs_for_updated_files).returns({'fake_file.rb'=>[]})
|
@@ -86,5 +100,5 @@ class ChurnCalculatorTest < Test::Unit::TestCase
|
|
86
100
|
assert churn.instance_variable_get(:@source_control).is_a?(Churn::HgAnalyzer)
|
87
101
|
end
|
88
102
|
|
89
|
-
|
103
|
+
|
90
104
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: churn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 53
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 21
|
10
|
+
version: 0.0.21
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dan Mayer
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-09-
|
18
|
+
date: 2012-09-14 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -187,82 +187,10 @@ dependencies:
|
|
187
187
|
version: "0"
|
188
188
|
requirement: *id012
|
189
189
|
prerelease: false
|
190
|
-
name: shoulda
|
191
|
-
type: :development
|
192
|
-
- !ruby/object:Gem::Dependency
|
193
|
-
version_requirements: &id013 !ruby/object:Gem::Requirement
|
194
|
-
none: false
|
195
|
-
requirements:
|
196
|
-
- - ">="
|
197
|
-
- !ruby/object:Gem::Version
|
198
|
-
hash: 3
|
199
|
-
segments:
|
200
|
-
- 0
|
201
|
-
version: "0"
|
202
|
-
requirement: *id013
|
203
|
-
prerelease: false
|
204
|
-
name: jeweler
|
205
|
-
type: :development
|
206
|
-
- !ruby/object:Gem::Dependency
|
207
|
-
version_requirements: &id014 !ruby/object:Gem::Requirement
|
208
|
-
none: false
|
209
|
-
requirements:
|
210
|
-
- - ">="
|
211
|
-
- !ruby/object:Gem::Version
|
212
|
-
hash: 3
|
213
|
-
segments:
|
214
|
-
- 0
|
215
|
-
version: "0"
|
216
|
-
requirement: *id014
|
217
|
-
prerelease: false
|
218
|
-
name: test-construct
|
219
|
-
type: :development
|
220
|
-
- !ruby/object:Gem::Dependency
|
221
|
-
version_requirements: &id015 !ruby/object:Gem::Requirement
|
222
|
-
none: false
|
223
|
-
requirements:
|
224
|
-
- - ">="
|
225
|
-
- !ruby/object:Gem::Version
|
226
|
-
hash: 3
|
227
|
-
segments:
|
228
|
-
- 0
|
229
|
-
version: "0"
|
230
|
-
requirement: *id015
|
231
|
-
prerelease: false
|
232
|
-
name: rake
|
233
|
-
type: :development
|
234
|
-
- !ruby/object:Gem::Dependency
|
235
|
-
version_requirements: &id016 !ruby/object:Gem::Requirement
|
236
|
-
none: false
|
237
|
-
requirements:
|
238
|
-
- - ~>
|
239
|
-
- !ruby/object:Gem::Version
|
240
|
-
hash: 49
|
241
|
-
segments:
|
242
|
-
- 0
|
243
|
-
- 9
|
244
|
-
- 5
|
245
|
-
version: 0.9.5
|
246
|
-
requirement: *id016
|
247
|
-
prerelease: false
|
248
|
-
name: mocha
|
249
|
-
type: :development
|
250
|
-
- !ruby/object:Gem::Dependency
|
251
|
-
version_requirements: &id017 !ruby/object:Gem::Requirement
|
252
|
-
none: false
|
253
|
-
requirements:
|
254
|
-
- - ">="
|
255
|
-
- !ruby/object:Gem::Version
|
256
|
-
hash: 3
|
257
|
-
segments:
|
258
|
-
- 0
|
259
|
-
version: "0"
|
260
|
-
requirement: *id017
|
261
|
-
prerelease: false
|
262
190
|
name: main
|
263
191
|
type: :runtime
|
264
192
|
- !ruby/object:Gem::Dependency
|
265
|
-
version_requirements: &
|
193
|
+
version_requirements: &id013 !ruby/object:Gem::Requirement
|
266
194
|
none: false
|
267
195
|
requirements:
|
268
196
|
- - ">="
|
@@ -271,12 +199,12 @@ dependencies:
|
|
271
199
|
segments:
|
272
200
|
- 0
|
273
201
|
version: "0"
|
274
|
-
requirement: *
|
202
|
+
requirement: *id013
|
275
203
|
prerelease: false
|
276
204
|
name: json_pure
|
277
205
|
type: :runtime
|
278
206
|
- !ruby/object:Gem::Dependency
|
279
|
-
version_requirements: &
|
207
|
+
version_requirements: &id014 !ruby/object:Gem::Requirement
|
280
208
|
none: false
|
281
209
|
requirements:
|
282
210
|
- - ">="
|
@@ -287,12 +215,12 @@ dependencies:
|
|
287
215
|
- 2
|
288
216
|
- 3
|
289
217
|
version: 0.2.3
|
290
|
-
requirement: *
|
218
|
+
requirement: *id014
|
291
219
|
prerelease: false
|
292
220
|
name: chronic
|
293
221
|
type: :runtime
|
294
222
|
- !ruby/object:Gem::Dependency
|
295
|
-
version_requirements: &
|
223
|
+
version_requirements: &id015 !ruby/object:Gem::Requirement
|
296
224
|
none: false
|
297
225
|
requirements:
|
298
226
|
- - ~>
|
@@ -302,12 +230,12 @@ dependencies:
|
|
302
230
|
- 3
|
303
231
|
- 0
|
304
232
|
version: "3.0"
|
305
|
-
requirement: *
|
233
|
+
requirement: *id015
|
306
234
|
prerelease: false
|
307
235
|
name: sexp_processor
|
308
236
|
type: :runtime
|
309
237
|
- !ruby/object:Gem::Dependency
|
310
|
-
version_requirements: &
|
238
|
+
version_requirements: &id016 !ruby/object:Gem::Requirement
|
311
239
|
none: false
|
312
240
|
requirements:
|
313
241
|
- - ~>
|
@@ -317,12 +245,12 @@ dependencies:
|
|
317
245
|
- 2
|
318
246
|
- 3
|
319
247
|
version: "2.3"
|
320
|
-
requirement: *
|
248
|
+
requirement: *id016
|
321
249
|
prerelease: false
|
322
250
|
name: ruby_parser
|
323
251
|
type: :runtime
|
324
252
|
- !ruby/object:Gem::Dependency
|
325
|
-
version_requirements: &
|
253
|
+
version_requirements: &id017 !ruby/object:Gem::Requirement
|
326
254
|
none: false
|
327
255
|
requirements:
|
328
256
|
- - ">="
|
@@ -331,7 +259,7 @@ dependencies:
|
|
331
259
|
segments:
|
332
260
|
- 0
|
333
261
|
version: "0"
|
334
|
-
requirement: *
|
262
|
+
requirement: *id017
|
335
263
|
prerelease: false
|
336
264
|
name: hirb
|
337
265
|
type: :runtime
|
@@ -343,13 +271,13 @@ extensions: []
|
|
343
271
|
|
344
272
|
extra_rdoc_files:
|
345
273
|
- LICENSE
|
346
|
-
- README.
|
274
|
+
- README.md
|
347
275
|
files:
|
348
276
|
- .document
|
349
277
|
- Gemfile
|
350
278
|
- Gemfile.lock
|
351
279
|
- LICENSE
|
352
|
-
- README.
|
280
|
+
- README.md
|
353
281
|
- Rakefile
|
354
282
|
- VERSION
|
355
283
|
- bin/churn
|
data/README.rdoc
DELETED
@@ -1,123 +0,0 @@
|
|
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.
|