churn 1.0.2 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{LICENSE → LICENSE.txt} +0 -0
- data/README.md +137 -120
- data/bin/churn +27 -12
- data/churn.gemspec +7 -21
- data/lib/churn/calculator.rb +24 -11
- data/lib/churn/history.rb +1 -1
- data/lib/churn/location_mapping.rb +1 -1
- data/lib/churn/options.rb +7 -3
- data/lib/churn/scm/bzr_analyzer.rb +11 -4
- data/lib/churn/scm/git_analyzer.rb +5 -3
- data/lib/churn/scm/hg_analyzer.rb +11 -4
- data/lib/churn/scm/source_control.rb +6 -8
- data/lib/churn/scm/svn_analyzer.rb +9 -3
- data/lib/churn/version.rb +1 -1
- metadata +24 -190
- data/.deferred_server +0 -1
- data/.document +0 -5
- data/.gitignore +0 -11
- data/.travis.yml +0 -6
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -79
- data/Rakefile +0 -41
- data/doc/Churn.html +0 -165
- data/doc/Churn/BzrAnalyzer.html +0 -276
- data/doc/Churn/ChurnCalculator.html +0 -578
- data/doc/Churn/ChurnHistory.html +0 -250
- data/doc/Churn/ChurnOptions.html +0 -393
- data/doc/Churn/GitAnalyzer.html +0 -311
- data/doc/Churn/HgAnalyzer.html +0 -276
- data/doc/Churn/LocationMapping.html +0 -448
- data/doc/Churn/SourceControl.html +0 -451
- data/doc/Churn/SvnAnalyzer.html +0 -311
- data/doc/LICENSE.html +0 -123
- data/doc/Object.html +0 -246
- data/doc/created.rid +0 -15
- data/doc/images/add.png +0 -0
- data/doc/images/arrow_up.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +0 -100
- data/doc/js/darkfish.js +0 -155
- data/doc/js/jquery.js +0 -18
- data/doc/js/navigation.js +0 -142
- data/doc/js/search.js +0 -94
- data/doc/js/search_index.js +0 -1
- data/doc/js/searcher.js +0 -228
- data/doc/rdoc.css +0 -595
- data/doc/table_of_contents.html +0 -167
- data/test/data/churn_calculator.rb +0 -217
- data/test/data/test_helper.rb +0 -14
- data/test/test_helper.rb +0 -21
- data/test/unit/bzr_analyzer_test.rb +0 -65
- data/test/unit/churn_calculator_test.rb +0 -181
- data/test/unit/churn_history_test.rb +0 -24
- data/test/unit/churn_options_test.rb +0 -16
- data/test/unit/git_analyzer_test.rb +0 -88
- data/test/unit/hg_analyzer_test.rb +0 -66
- data/test/unit/location_mapping_test.rb +0 -35
- data/test/unit/source_control_test.rb +0 -22
- data/test/unit/svn_analyzer_test.rb +0 -65
data/doc/table_of_contents.html
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
|
3
|
-
<html>
|
4
|
-
<head>
|
5
|
-
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
6
|
-
|
7
|
-
<title>Table of Contents - RDoc Documentation</title>
|
8
|
-
|
9
|
-
<link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
|
10
|
-
|
11
|
-
<script type="text/javascript">
|
12
|
-
var rdoc_rel_prefix = "./";
|
13
|
-
</script>
|
14
|
-
|
15
|
-
<script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
|
16
|
-
<script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
|
17
|
-
<script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
|
18
|
-
<script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
|
19
|
-
<script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
|
20
|
-
<script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
|
21
|
-
|
22
|
-
|
23
|
-
<body class="indexpage">
|
24
|
-
<h1>Table of Contents - RDoc Documentation</h1>
|
25
|
-
|
26
|
-
<h2>Pages</h2>
|
27
|
-
<ul>
|
28
|
-
<li class="file">
|
29
|
-
<a href="LICENSE.html">LICENSE</a>
|
30
|
-
</li>
|
31
|
-
|
32
|
-
</ul>
|
33
|
-
|
34
|
-
<h2 id="classes">Classes/Modules</h2>
|
35
|
-
<ul>
|
36
|
-
<li class="module">
|
37
|
-
<a href="Churn.html">Churn</a>
|
38
|
-
</li>
|
39
|
-
<li class="class">
|
40
|
-
<a href="Churn/BzrAnalyzer.html">Churn::BzrAnalyzer</a>
|
41
|
-
</li>
|
42
|
-
<li class="class">
|
43
|
-
<a href="Churn/ChurnCalculator.html">Churn::ChurnCalculator</a>
|
44
|
-
</li>
|
45
|
-
<li class="class">
|
46
|
-
<a href="Churn/ChurnHistory.html">Churn::ChurnHistory</a>
|
47
|
-
</li>
|
48
|
-
<li class="class">
|
49
|
-
<a href="Churn/ChurnOptions.html">Churn::ChurnOptions</a>
|
50
|
-
</li>
|
51
|
-
<li class="class">
|
52
|
-
<a href="Churn/GitAnalyzer.html">Churn::GitAnalyzer</a>
|
53
|
-
</li>
|
54
|
-
<li class="class">
|
55
|
-
<a href="Churn/HgAnalyzer.html">Churn::HgAnalyzer</a>
|
56
|
-
</li>
|
57
|
-
<li class="class">
|
58
|
-
<a href="Churn/LocationMapping.html">Churn::LocationMapping</a>
|
59
|
-
</li>
|
60
|
-
<li class="class">
|
61
|
-
<a href="Churn/SourceControl.html">Churn::SourceControl</a>
|
62
|
-
</li>
|
63
|
-
<li class="class">
|
64
|
-
<a href="Churn/SvnAnalyzer.html">Churn::SvnAnalyzer</a>
|
65
|
-
</li>
|
66
|
-
<li class="class">
|
67
|
-
<a href="Object.html">Object</a>
|
68
|
-
</li>
|
69
|
-
|
70
|
-
</ul>
|
71
|
-
|
72
|
-
<h2 id="methods">Methods</h2>
|
73
|
-
<ul>
|
74
|
-
|
75
|
-
<li class="method"><a href="Churn/ChurnHistory.html#method-c-load_revision_data">::load_revision_data — Churn::ChurnHistory</a>
|
76
|
-
|
77
|
-
<li class="method"><a href="Churn/LocationMapping.html#method-c-new">::new — Churn::LocationMapping</a>
|
78
|
-
|
79
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-c-new">::new — Churn::ChurnCalculator</a>
|
80
|
-
|
81
|
-
<li class="method"><a href="Churn/SourceControl.html#method-c-new">::new — Churn::SourceControl</a>
|
82
|
-
|
83
|
-
<li class="method"><a href="Churn/ChurnOptions.html#method-c-new">::new — Churn::ChurnOptions</a>
|
84
|
-
|
85
|
-
<li class="method"><a href="Churn/SourceControl.html#method-c-set_source_control">::set_source_control — Churn::SourceControl</a>
|
86
|
-
|
87
|
-
<li class="method"><a href="Churn/ChurnHistory.html#method-c-store_revision_history">::store_revision_history — Churn::ChurnHistory</a>
|
88
|
-
|
89
|
-
<li class="method"><a href="Churn/BzrAnalyzer.html#method-c-supported-3F">::supported? — Churn::BzrAnalyzer</a>
|
90
|
-
|
91
|
-
<li class="method"><a href="Churn/HgAnalyzer.html#method-c-supported-3F">::supported? — Churn::HgAnalyzer</a>
|
92
|
-
|
93
|
-
<li class="method"><a href="Churn/SourceControl.html#method-c-supported-3F">::supported? — Churn::SourceControl</a>
|
94
|
-
|
95
|
-
<li class="method"><a href="Churn/GitAnalyzer.html#method-c-supported-3F">::supported? — Churn::GitAnalyzer</a>
|
96
|
-
|
97
|
-
<li class="method"><a href="Churn/SvnAnalyzer.html#method-c-supported-3F">::supported? — Churn::SvnAnalyzer</a>
|
98
|
-
|
99
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-c-to_s">::to_s — Churn::ChurnCalculator</a>
|
100
|
-
|
101
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-analyze">#analyze — Churn::ChurnCalculator</a>
|
102
|
-
|
103
|
-
<li class="method"><a href="Churn/LocationMapping.html#method-i-analyze_list">#analyze_list — Churn::LocationMapping</a>
|
104
|
-
|
105
|
-
<li class="method"><a href="Churn/LocationMapping.html#method-i-deep_last_line">#deep_last_line — Churn::LocationMapping</a>
|
106
|
-
|
107
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-emit">#emit — Churn::ChurnCalculator</a>
|
108
|
-
|
109
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-generate_history">#generate_history — Churn::ChurnCalculator</a>
|
110
|
-
|
111
|
-
<li class="method"><a href="Churn/GitAnalyzer.html#method-i-get_commit_history">#get_commit_history — Churn::GitAnalyzer</a>
|
112
|
-
|
113
|
-
<li class="method"><a href="Churn/LocationMapping.html#method-i-get_info">#get_info — Churn::LocationMapping</a>
|
114
|
-
|
115
|
-
<li class="method"><a href="Churn/SvnAnalyzer.html#method-i-get_logs">#get_logs — Churn::SvnAnalyzer</a>
|
116
|
-
|
117
|
-
<li class="method"><a href="Churn/HgAnalyzer.html#method-i-get_logs">#get_logs — Churn::HgAnalyzer</a>
|
118
|
-
|
119
|
-
<li class="method"><a href="Churn/BzrAnalyzer.html#method-i-get_logs">#get_logs — Churn::BzrAnalyzer</a>
|
120
|
-
|
121
|
-
<li class="method"><a href="Churn/GitAnalyzer.html#method-i-get_logs">#get_logs — Churn::GitAnalyzer</a>
|
122
|
-
|
123
|
-
<li class="method"><a href="Churn/SourceControl.html#method-i-get_logs">#get_logs — Churn::SourceControl</a>
|
124
|
-
|
125
|
-
<li class="method"><a href="Churn/BzrAnalyzer.html#method-i-get_revisions">#get_revisions — Churn::BzrAnalyzer</a>
|
126
|
-
|
127
|
-
<li class="method"><a href="Churn/GitAnalyzer.html#method-i-get_revisions">#get_revisions — Churn::GitAnalyzer</a>
|
128
|
-
|
129
|
-
<li class="method"><a href="Churn/SourceControl.html#method-i-get_revisions">#get_revisions — Churn::SourceControl</a>
|
130
|
-
|
131
|
-
<li class="method"><a href="Churn/SvnAnalyzer.html#method-i-get_revisions">#get_revisions — Churn::SvnAnalyzer</a>
|
132
|
-
|
133
|
-
<li class="method"><a href="Churn/HgAnalyzer.html#method-i-get_revisions">#get_revisions — Churn::HgAnalyzer</a>
|
134
|
-
|
135
|
-
<li class="method"><a href="Churn/SourceControl.html#method-i-get_updated_files_change_info">#get_updated_files_change_info — Churn::SourceControl</a>
|
136
|
-
|
137
|
-
<li class="method"><a href="Churn/SvnAnalyzer.html#method-i-get_updated_files_change_info">#get_updated_files_change_info — Churn::SvnAnalyzer</a>
|
138
|
-
|
139
|
-
<li class="method"><a href="Churn/SourceControl.html#method-i-get_updated_files_from_log">#get_updated_files_from_log — Churn::SourceControl</a>
|
140
|
-
|
141
|
-
<li class="method"><a href="Churn/LocationMapping.html#method-i-process_class">#process_class — Churn::LocationMapping</a>
|
142
|
-
|
143
|
-
<li class="method"><a href="Churn/LocationMapping.html#method-i-process_defn">#process_defn — Churn::LocationMapping</a>
|
144
|
-
|
145
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-remote_report">#remote_report — Churn::ChurnCalculator</a>
|
146
|
-
|
147
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-report">#report — Churn::ChurnCalculator</a>
|
148
|
-
|
149
|
-
<li class="method"><a href="Object.html#method-i-report_churn">#report_churn — Object</a>
|
150
|
-
|
151
|
-
<li class="method"><a href="Object.html#method-i-run">#run — Object</a>
|
152
|
-
|
153
|
-
<li class="method"><a href="Churn/ChurnOptions.html#method-i-set_options">#set_options — Churn::ChurnOptions</a>
|
154
|
-
|
155
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-to_h">#to_h — Churn::ChurnCalculator</a>
|
156
|
-
|
157
|
-
<li class="method"><a href="Churn/ChurnCalculator.html#method-i-to_s">#to_s — Churn::ChurnCalculator</a>
|
158
|
-
|
159
|
-
</ul>
|
160
|
-
|
161
|
-
|
162
|
-
<footer id="validator-badges">
|
163
|
-
<p><a href="http://validator.w3.org/check/referer">[Validate]</a>
|
164
|
-
<p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 4.0.1.
|
165
|
-
<p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
|
166
|
-
</footer>
|
167
|
-
|
@@ -1,217 +0,0 @@
|
|
1
|
-
require 'chronic'
|
2
|
-
require 'sexp_processor'
|
3
|
-
require 'ruby_parser'
|
4
|
-
require 'json'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'lib/churn/source_control'
|
7
|
-
require 'lib/churn/git_analyzer'
|
8
|
-
require 'lib/churn/svn_analyzer'
|
9
|
-
require 'lib/churn/location_mapping'
|
10
|
-
require 'lib/churn/churn_history'
|
11
|
-
|
12
|
-
module Churn
|
13
|
-
|
14
|
-
class ChurnCalculator
|
15
|
-
|
16
|
-
def initialize(options={})
|
17
|
-
start_date = options.fetch(:start_date) { '3 months ago' }
|
18
|
-
@minimum_churn_count = options.fetch(:minimum_churn_count) { 5 }
|
19
|
-
puts start_date
|
20
|
-
if self.class.git?
|
21
|
-
@source_control = GitAnalyzer.new(start_date)
|
22
|
-
elsif File.exist?(".svn")
|
23
|
-
@source_control = SvnAnalyzer.new(start_date)
|
24
|
-
else
|
25
|
-
raise "Churning requires a subversion or git repo"
|
26
|
-
end
|
27
|
-
@revision_changes = {}
|
28
|
-
@method_changes = {}
|
29
|
-
@class_changes = {}
|
30
|
-
end
|
31
|
-
|
32
|
-
def report
|
33
|
-
self.emit
|
34
|
-
self.analyze
|
35
|
-
self.to_h
|
36
|
-
end
|
37
|
-
|
38
|
-
def emit
|
39
|
-
@changes = parse_log_for_changes.reject {|file, change_count| change_count < @minimum_churn_count}
|
40
|
-
@revisions = parse_log_for_revision_changes
|
41
|
-
end
|
42
|
-
|
43
|
-
def analyze
|
44
|
-
@changes = @changes.to_a.sort {|x,y| y[1] <=> x[1]}
|
45
|
-
@changes = @changes.map {|file_path, times_changed| {:file_path => file_path, :times_changed => times_changed }}
|
46
|
-
|
47
|
-
calculate_revision_changes
|
48
|
-
|
49
|
-
@method_changes.to_a.sort {|x,y| y[1] <=> x[1]}
|
50
|
-
@method_changes = @method_changes.map {|method, times_changed| {'method' => method, 'times_changed' => times_changed }}
|
51
|
-
@class_changes.to_a.sort {|x,y| y[1] <=> x[1]}
|
52
|
-
@class_changes = @class_changes.map {|klass, times_changed| {'klass' => klass, 'times_changed' => times_changed }}
|
53
|
-
end
|
54
|
-
|
55
|
-
def to_h
|
56
|
-
hash = {:churn => {:changes => @changes}}
|
57
|
-
hash[:churn][:method_churn] = @method_changes
|
58
|
-
hash[:churn][:class_churn] = @class_changes
|
59
|
-
#detail the most recent changes made this revision
|
60
|
-
if @revision_changes[@revisions.first]
|
61
|
-
changes = @revision_changes[@revisions.first]
|
62
|
-
hash[:churn][:changed_files] = changes[:files]
|
63
|
-
hash[:churn][:changed_classes] = changes[:classes]
|
64
|
-
hash[:churn][:changed_methods] = changes[:methods]
|
65
|
-
end
|
66
|
-
#TODO crappy place to do this but save hash to revision file but while entirely under metric_fu only choice
|
67
|
-
revision = @revisions.first
|
68
|
-
ChurnHistory.store_revision_history(revision, hash)
|
69
|
-
hash
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def self.git?
|
75
|
-
system("git branch")
|
76
|
-
end
|
77
|
-
|
78
|
-
def calculate_revision_changes
|
79
|
-
@revisions.each do |revision|
|
80
|
-
if revision == @revisions.first
|
81
|
-
#can't iterate through all the changes and tally them up
|
82
|
-
#it only has the current files not the files at the time of the revision
|
83
|
-
#parsing requires the files
|
84
|
-
changed_files, changed_classes, changed_methods = calculate_revision_data(revision)
|
85
|
-
else
|
86
|
-
changed_files, changed_classes, changed_methods = ChurnHistory.load_revision_data(revision)
|
87
|
-
end
|
88
|
-
calculate_changes!(changed_methods, @method_changes) if changed_methods
|
89
|
-
calculate_changes!(changed_classes, @class_changes) if changed_classes
|
90
|
-
|
91
|
-
@revision_changes[revision] = { :files => changed_files, :classes => changed_classes, :methods => changed_methods }
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def calculate_revision_data(revision)
|
96
|
-
changed_files = parse_logs_for_updated_files(revision, @revisions)
|
97
|
-
|
98
|
-
changed_classes = []
|
99
|
-
changed_methods = []
|
100
|
-
changed_files.each do |file|
|
101
|
-
classes, methods = get_changes(file)
|
102
|
-
changed_classes += classes
|
103
|
-
changed_methods += methods
|
104
|
-
end
|
105
|
-
changed_files = changed_files.map { |file, lines| file }
|
106
|
-
[changed_files, changed_classes, changed_methods]
|
107
|
-
end
|
108
|
-
|
109
|
-
def calculate_changes!(changed, total_changes)
|
110
|
-
if changed
|
111
|
-
changed.each do |change|
|
112
|
-
total_changes.include?(change) ? total_changes[change] = total_changes[change]+1 : total_changes[change] = 1
|
113
|
-
end
|
114
|
-
end
|
115
|
-
total_changes
|
116
|
-
end
|
117
|
-
|
118
|
-
def get_changes(change)
|
119
|
-
begin
|
120
|
-
file = change.first
|
121
|
-
breakdown = LocationMapping.new
|
122
|
-
breakdown.get_info(file)
|
123
|
-
changes = change.last
|
124
|
-
classes = changes_for_type(changes, breakdown, :classes)
|
125
|
-
methods = changes_for_type(changes, breakdown, :methods)
|
126
|
-
#todo move to method
|
127
|
-
classes = classes.map{ |klass| {'file' => file, 'klass' => klass} }
|
128
|
-
methods = methods.map{ |method| {'file' => file, 'klass' => get_klass_for(method), 'method' => method} }
|
129
|
-
[classes, methods]
|
130
|
-
rescue => error
|
131
|
-
[[],[]]
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def get_klass_for(method)
|
136
|
-
method.gsub(/(#|\.).*/,'')
|
137
|
-
end
|
138
|
-
|
139
|
-
def changes_for_type(changes, breakdown, type)
|
140
|
-
item_collection = if type == :classes
|
141
|
-
breakdown.klasses_collection
|
142
|
-
elsif type == :methods
|
143
|
-
breakdown.methods_collection
|
144
|
-
end
|
145
|
-
changed_items = []
|
146
|
-
item_collection.each_pair do |item, item_lines|
|
147
|
-
item_lines = item_lines[0].to_a
|
148
|
-
changes.each do |change_range|
|
149
|
-
item_lines.each do |line|
|
150
|
-
changed_items << item if change_range.include?(line) && !changed_items.include?(item)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
changed_items
|
155
|
-
end
|
156
|
-
|
157
|
-
def parse_log_for_changes
|
158
|
-
changes = Hash.new(0)
|
159
|
-
|
160
|
-
logs = @source_control.get_logs
|
161
|
-
logs.each do |line|
|
162
|
-
changes[line] += 1
|
163
|
-
end
|
164
|
-
changes
|
165
|
-
end
|
166
|
-
|
167
|
-
def parse_log_for_revision_changes
|
168
|
-
@source_control.get_revisions
|
169
|
-
end
|
170
|
-
|
171
|
-
def parse_logs_for_updated_files(revision, revisions)
|
172
|
-
updated = {}
|
173
|
-
recent_file = nil
|
174
|
-
|
175
|
-
#SVN doesn't support this
|
176
|
-
return updated unless @source_control.respond_to?(:get_updated_files_from_log)
|
177
|
-
logs = @source_control.get_updated_files_from_log(revision, revisions)
|
178
|
-
logs.each do |line|
|
179
|
-
if /^---|^\+\+\+/ =~ line
|
180
|
-
line = line.gsub(/^--- /,'').gsub(/^\+\+\+ /,'').gsub(/^a\//,'').gsub(/^b\//,'')
|
181
|
-
unless updated.include?(line)
|
182
|
-
updated[line] = []
|
183
|
-
end
|
184
|
-
recent_file = line
|
185
|
-
elsif /^@@/ =~ line
|
186
|
-
#TODO cleanup / refactor
|
187
|
-
#puts "#{recent_file}: #{line}"
|
188
|
-
removed = line.match(/-[0-9]+/)
|
189
|
-
removed_length = line.match(/-[0-9]+,[0-9]+/)
|
190
|
-
removed = removed.to_s.gsub(/-/,'')
|
191
|
-
removed_length = removed_length.to_s.gsub(/.*,/,'')
|
192
|
-
added = line.match(/\+[0-9]+/)
|
193
|
-
added_length = line.match(/\+[0-9]+,[0-9]+/)
|
194
|
-
added = added.to_s.gsub(/\+/,'')
|
195
|
-
added_length = added_length.to_s.gsub(/.*,/,'')
|
196
|
-
removed_range = if removed_length && removed_length!=''
|
197
|
-
(removed.to_i..(removed.to_i+removed_length.to_i))
|
198
|
-
else
|
199
|
-
(removed.to_i..removed.to_i)
|
200
|
-
end
|
201
|
-
added_range = if added_length && added_length!=''
|
202
|
-
(added.to_i..(added.to_i+added_length.to_i))
|
203
|
-
else
|
204
|
-
(added.to_i..added.to_i)
|
205
|
-
end
|
206
|
-
updated[recent_file] << removed_range
|
207
|
-
updated[recent_file] << added_range
|
208
|
-
else
|
209
|
-
raise "git diff lines that don't match the two patterns aren't expected"
|
210
|
-
end
|
211
|
-
end
|
212
|
-
updated
|
213
|
-
end
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
end
|
data/test/data/test_helper.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'shoulda'
|
4
|
-
require 'test_construct'
|
5
|
-
require 'mocha/mini_test'
|
6
|
-
|
7
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
-
require 'churn/churn_calculator'
|
10
|
-
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
11
|
-
|
12
|
-
class Minitest::Test
|
13
|
-
include TestConstruct::Helpers
|
14
|
-
end
|
data/test/test_helper.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'simplecov'
|
3
|
-
require 'minitest/autorun'
|
4
|
-
require 'shoulda'
|
5
|
-
require 'test_construct'
|
6
|
-
require 'mocha/mini_test'
|
7
|
-
|
8
|
-
SimpleCov.start do
|
9
|
-
add_filter 'specs/ruby/1.9.1/gems/'
|
10
|
-
add_filter '/test/'
|
11
|
-
add_filter '/config/'
|
12
|
-
end
|
13
|
-
|
14
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
16
|
-
require 'churn/calculator'
|
17
|
-
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
18
|
-
|
19
|
-
class Minitest::Test
|
20
|
-
include TestConstruct::Helpers
|
21
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require File.expand_path('../test_helper', File.dirname(__FILE__))
|
2
|
-
|
3
|
-
class BzrAnalyzerTest < Minitest::Test
|
4
|
-
context "BzrAnalyzer#get_logs" do
|
5
|
-
should "return a list of changed files" do
|
6
|
-
bzr_analyzer = Churn::BzrAnalyzer.new
|
7
|
-
bzr_analyzer.expects(:`).with('bzr log -v --short ').returns(" 1947 Adam Walters 2010-01-16\n Second commit with 3 files now.\n M file1.rb\n M file2.rb\n M file3.rb\n\n 1946 Adam Walters 2010-01-16\n First commit\n A file1.rb\n")
|
8
|
-
assert_equal ["file1.rb", "file2.rb", "file3.rb", "file1.rb"], bzr_analyzer.get_logs
|
9
|
-
end
|
10
|
-
|
11
|
-
should "scope the changed files to an optional date range" do
|
12
|
-
bzr_analyzer = Churn::BzrAnalyzer.new("1/16/2010")
|
13
|
-
bzr_analyzer.expects(:`).with('bzr log -v --short -r 2010-01-16..').returns(" 1947 Adam Walters 2010-01-16\n Second commit with 3 files now.\n M file1.rb\n M file2.rb\n M file3.rb\n\n 1946 Adam Walters 2010-01-16\n First commit\n A file1.rb\n")
|
14
|
-
assert_equal ["file1.rb", "file2.rb", "file3.rb", "file1.rb"], bzr_analyzer.get_logs
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context "BzrAnalyzer#get_revisions" do
|
19
|
-
should "return a list of changeset ids" do
|
20
|
-
bzr_analyzer = Churn::BzrAnalyzer.new
|
21
|
-
bzr_analyzer.expects(:`).with('bzr log --line ').returns("1947: Adam Walters 2010-01-16 Second commit with 3 files now.\n1946: Adam Walters 2010-01-16 First commit\n")
|
22
|
-
assert_equal ["1947", "1946"], bzr_analyzer.get_revisions
|
23
|
-
end
|
24
|
-
|
25
|
-
should "scope the changesets to an optional date range" do
|
26
|
-
bzr_analyzer = Churn::BzrAnalyzer.new("1/16/2010")
|
27
|
-
bzr_analyzer.expects(:`).with('bzr log --line -r 2010-01-16..').returns("1947: Adam Walters 2010-01-16 Second commit with 3 files now.\n1946: Adam Walters 2010-01-16 First commit\n")
|
28
|
-
assert_equal ["1947", "1946"], bzr_analyzer.get_revisions
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "BzrAnalyzer#get_updated_files_from_log(revision, revisions)" do
|
33
|
-
should "return a list of modified files and the change hunks (chunks)" do
|
34
|
-
bzr_analyzer = Churn::BzrAnalyzer.new
|
35
|
-
bzr_analyzer.expects(:`).with('bzr diff -r 1946..1947').returns("=== modified file 'a/file1.rb'\n--- a/file1.rb\tSat Jan 16 14:21:28 2010 -0600\n+++ b/file1.rb\tSat Jan 16 14:19:32 2010 -0600\n@@ -1,3 +0,0 @@\n-First\n-Adding sample data\n-Third line\ndiff -r 1947 -r 1946 file2.rb\n=== modified file 'a/file2.rb'\n--- a/file2.rb\tSat Jan 16 14:21:28 2010 -0600\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,7 +0,0 @@\n-This is the second file.\n-\n-Little more data\n-\n-def cool_method\n- \"hello\"\n-end\ndiff -r 1947 -r 1946 file3.rb\n--- a/file3.rb\tSat Jan 16 14:21:28 2010 -0600\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,5 +0,0 @@\n-Third file here.\n-\n-def another_method\n- \"foo\"\n-end\n")
|
36
|
-
assert_equal ["--- a/file1.rb\tSat Jan 16 14:21:28 2010 -0600", "+++ b/file1.rb\tSat Jan 16 14:19:32 2010 -0600", "@@ -1,3 +0,0 @@", "--- a/file2.rb\tSat Jan 16 14:21:28 2010 -0600", "+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000", "@@ -1,7 +0,0 @@", "--- a/file3.rb\tSat Jan 16 14:21:28 2010 -0600", "+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000", "@@ -1,5 +0,0 @@"], bzr_analyzer.get_updated_files_from_log("1947", ["1947", "1946"])
|
37
|
-
end
|
38
|
-
|
39
|
-
should "return an empty array if it's the final revision" do
|
40
|
-
bzr_analyzer = Churn::BzrAnalyzer.new
|
41
|
-
assert_equal [], bzr_analyzer.get_updated_files_from_log("1946", ["1947", "1946"])
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context "BzrAnalyzer#get_updated_files_change_info(revision, revisions)" do
|
46
|
-
setup do
|
47
|
-
@bzr_analyzer = Churn::BzrAnalyzer.new
|
48
|
-
end
|
49
|
-
|
50
|
-
should "return all modified files with their line differences" do
|
51
|
-
@bzr_analyzer.expects(:get_updated_files_from_log).with("1947", ["1947", "1946"]).returns(["--- a/file1.rb\tSat Jan 16 14:21:28 2010 -0600", "+++ b/file1.rb\tSat Jan 16 14:19:32 2010 -0600", "@@ -1,3 +0,0 @@", "--- a/file2.rb\tSat Jan 16 14:21:28 2010 -0600", "+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000", "@@ -1,7 +0,0 @@", "--- a/file3.rb\tSat Jan 16 14:21:28 2010 -0600", "+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000", "@@ -1,5 +0,0 @@"])
|
52
|
-
assert_equal({"/dev/null" => [1..8, 0..0, 1..6, 0..0], "file3.rb" => [], "file1.rb" => [], "file2.rb" => [], "file1.rb" => [1..4, 0..0]}, @bzr_analyzer.get_updated_files_change_info("1947", ["1947", "1946"]))
|
53
|
-
end
|
54
|
-
|
55
|
-
should "raise an error if it encounters a line it cannot parse" do
|
56
|
-
@bzr_analyzer.expects(:get_updated_files_from_log).with("1947", ["1947", "1946"]).returns(["foo"])
|
57
|
-
assert_raises RuntimeError do
|
58
|
-
@bzr_analyzer.stubs(:puts) # supress output from raised error
|
59
|
-
@bzr_analyzer.get_updated_files_change_info("1947", ["1947", "1946"])
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|