churn 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
|