churn 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/{LICENSE → LICENSE.txt} +0 -0
  3. data/README.md +137 -120
  4. data/bin/churn +27 -12
  5. data/churn.gemspec +7 -21
  6. data/lib/churn/calculator.rb +24 -11
  7. data/lib/churn/history.rb +1 -1
  8. data/lib/churn/location_mapping.rb +1 -1
  9. data/lib/churn/options.rb +7 -3
  10. data/lib/churn/scm/bzr_analyzer.rb +11 -4
  11. data/lib/churn/scm/git_analyzer.rb +5 -3
  12. data/lib/churn/scm/hg_analyzer.rb +11 -4
  13. data/lib/churn/scm/source_control.rb +6 -8
  14. data/lib/churn/scm/svn_analyzer.rb +9 -3
  15. data/lib/churn/version.rb +1 -1
  16. metadata +24 -190
  17. data/.deferred_server +0 -1
  18. data/.document +0 -5
  19. data/.gitignore +0 -11
  20. data/.travis.yml +0 -6
  21. data/Gemfile +0 -3
  22. data/Gemfile.lock +0 -79
  23. data/Rakefile +0 -41
  24. data/doc/Churn.html +0 -165
  25. data/doc/Churn/BzrAnalyzer.html +0 -276
  26. data/doc/Churn/ChurnCalculator.html +0 -578
  27. data/doc/Churn/ChurnHistory.html +0 -250
  28. data/doc/Churn/ChurnOptions.html +0 -393
  29. data/doc/Churn/GitAnalyzer.html +0 -311
  30. data/doc/Churn/HgAnalyzer.html +0 -276
  31. data/doc/Churn/LocationMapping.html +0 -448
  32. data/doc/Churn/SourceControl.html +0 -451
  33. data/doc/Churn/SvnAnalyzer.html +0 -311
  34. data/doc/LICENSE.html +0 -123
  35. data/doc/Object.html +0 -246
  36. data/doc/created.rid +0 -15
  37. data/doc/images/add.png +0 -0
  38. data/doc/images/arrow_up.png +0 -0
  39. data/doc/images/brick.png +0 -0
  40. data/doc/images/brick_link.png +0 -0
  41. data/doc/images/bug.png +0 -0
  42. data/doc/images/bullet_black.png +0 -0
  43. data/doc/images/bullet_toggle_minus.png +0 -0
  44. data/doc/images/bullet_toggle_plus.png +0 -0
  45. data/doc/images/date.png +0 -0
  46. data/doc/images/delete.png +0 -0
  47. data/doc/images/find.png +0 -0
  48. data/doc/images/loadingAnimation.gif +0 -0
  49. data/doc/images/macFFBgHack.png +0 -0
  50. data/doc/images/package.png +0 -0
  51. data/doc/images/page_green.png +0 -0
  52. data/doc/images/page_white_text.png +0 -0
  53. data/doc/images/page_white_width.png +0 -0
  54. data/doc/images/plugin.png +0 -0
  55. data/doc/images/ruby.png +0 -0
  56. data/doc/images/tag_blue.png +0 -0
  57. data/doc/images/tag_green.png +0 -0
  58. data/doc/images/transparent.png +0 -0
  59. data/doc/images/wrench.png +0 -0
  60. data/doc/images/wrench_orange.png +0 -0
  61. data/doc/images/zoom.png +0 -0
  62. data/doc/index.html +0 -100
  63. data/doc/js/darkfish.js +0 -155
  64. data/doc/js/jquery.js +0 -18
  65. data/doc/js/navigation.js +0 -142
  66. data/doc/js/search.js +0 -94
  67. data/doc/js/search_index.js +0 -1
  68. data/doc/js/searcher.js +0 -228
  69. data/doc/rdoc.css +0 -595
  70. data/doc/table_of_contents.html +0 -167
  71. data/test/data/churn_calculator.rb +0 -217
  72. data/test/data/test_helper.rb +0 -14
  73. data/test/test_helper.rb +0 -21
  74. data/test/unit/bzr_analyzer_test.rb +0 -65
  75. data/test/unit/churn_calculator_test.rb +0 -181
  76. data/test/unit/churn_history_test.rb +0 -24
  77. data/test/unit/churn_options_test.rb +0 -16
  78. data/test/unit/git_analyzer_test.rb +0 -88
  79. data/test/unit/hg_analyzer_test.rb +0 -66
  80. data/test/unit/location_mapping_test.rb +0 -35
  81. data/test/unit/source_control_test.rb +0 -22
  82. data/test/unit/svn_analyzer_test.rb +0 -65
@@ -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 &mdash; Churn::ChurnHistory</a>
76
-
77
- <li class="method"><a href="Churn/LocationMapping.html#method-c-new">::new &mdash; Churn::LocationMapping</a>
78
-
79
- <li class="method"><a href="Churn/ChurnCalculator.html#method-c-new">::new &mdash; Churn::ChurnCalculator</a>
80
-
81
- <li class="method"><a href="Churn/SourceControl.html#method-c-new">::new &mdash; Churn::SourceControl</a>
82
-
83
- <li class="method"><a href="Churn/ChurnOptions.html#method-c-new">::new &mdash; Churn::ChurnOptions</a>
84
-
85
- <li class="method"><a href="Churn/SourceControl.html#method-c-set_source_control">::set_source_control &mdash; Churn::SourceControl</a>
86
-
87
- <li class="method"><a href="Churn/ChurnHistory.html#method-c-store_revision_history">::store_revision_history &mdash; Churn::ChurnHistory</a>
88
-
89
- <li class="method"><a href="Churn/BzrAnalyzer.html#method-c-supported-3F">::supported? &mdash; Churn::BzrAnalyzer</a>
90
-
91
- <li class="method"><a href="Churn/HgAnalyzer.html#method-c-supported-3F">::supported? &mdash; Churn::HgAnalyzer</a>
92
-
93
- <li class="method"><a href="Churn/SourceControl.html#method-c-supported-3F">::supported? &mdash; Churn::SourceControl</a>
94
-
95
- <li class="method"><a href="Churn/GitAnalyzer.html#method-c-supported-3F">::supported? &mdash; Churn::GitAnalyzer</a>
96
-
97
- <li class="method"><a href="Churn/SvnAnalyzer.html#method-c-supported-3F">::supported? &mdash; Churn::SvnAnalyzer</a>
98
-
99
- <li class="method"><a href="Churn/ChurnCalculator.html#method-c-to_s">::to_s &mdash; Churn::ChurnCalculator</a>
100
-
101
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-analyze">#analyze &mdash; Churn::ChurnCalculator</a>
102
-
103
- <li class="method"><a href="Churn/LocationMapping.html#method-i-analyze_list">#analyze_list &mdash; Churn::LocationMapping</a>
104
-
105
- <li class="method"><a href="Churn/LocationMapping.html#method-i-deep_last_line">#deep_last_line &mdash; Churn::LocationMapping</a>
106
-
107
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-emit">#emit &mdash; Churn::ChurnCalculator</a>
108
-
109
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-generate_history">#generate_history &mdash; Churn::ChurnCalculator</a>
110
-
111
- <li class="method"><a href="Churn/GitAnalyzer.html#method-i-get_commit_history">#get_commit_history &mdash; Churn::GitAnalyzer</a>
112
-
113
- <li class="method"><a href="Churn/LocationMapping.html#method-i-get_info">#get_info &mdash; Churn::LocationMapping</a>
114
-
115
- <li class="method"><a href="Churn/SvnAnalyzer.html#method-i-get_logs">#get_logs &mdash; Churn::SvnAnalyzer</a>
116
-
117
- <li class="method"><a href="Churn/HgAnalyzer.html#method-i-get_logs">#get_logs &mdash; Churn::HgAnalyzer</a>
118
-
119
- <li class="method"><a href="Churn/BzrAnalyzer.html#method-i-get_logs">#get_logs &mdash; Churn::BzrAnalyzer</a>
120
-
121
- <li class="method"><a href="Churn/GitAnalyzer.html#method-i-get_logs">#get_logs &mdash; Churn::GitAnalyzer</a>
122
-
123
- <li class="method"><a href="Churn/SourceControl.html#method-i-get_logs">#get_logs &mdash; Churn::SourceControl</a>
124
-
125
- <li class="method"><a href="Churn/BzrAnalyzer.html#method-i-get_revisions">#get_revisions &mdash; Churn::BzrAnalyzer</a>
126
-
127
- <li class="method"><a href="Churn/GitAnalyzer.html#method-i-get_revisions">#get_revisions &mdash; Churn::GitAnalyzer</a>
128
-
129
- <li class="method"><a href="Churn/SourceControl.html#method-i-get_revisions">#get_revisions &mdash; Churn::SourceControl</a>
130
-
131
- <li class="method"><a href="Churn/SvnAnalyzer.html#method-i-get_revisions">#get_revisions &mdash; Churn::SvnAnalyzer</a>
132
-
133
- <li class="method"><a href="Churn/HgAnalyzer.html#method-i-get_revisions">#get_revisions &mdash; 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 &mdash; 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 &mdash; 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 &mdash; Churn::SourceControl</a>
140
-
141
- <li class="method"><a href="Churn/LocationMapping.html#method-i-process_class">#process_class &mdash; Churn::LocationMapping</a>
142
-
143
- <li class="method"><a href="Churn/LocationMapping.html#method-i-process_defn">#process_defn &mdash; Churn::LocationMapping</a>
144
-
145
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-remote_report">#remote_report &mdash; Churn::ChurnCalculator</a>
146
-
147
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-report">#report &mdash; Churn::ChurnCalculator</a>
148
-
149
- <li class="method"><a href="Object.html#method-i-report_churn">#report_churn &mdash; Object</a>
150
-
151
- <li class="method"><a href="Object.html#method-i-run">#run &mdash; Object</a>
152
-
153
- <li class="method"><a href="Churn/ChurnOptions.html#method-i-set_options">#set_options &mdash; Churn::ChurnOptions</a>
154
-
155
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-to_h">#to_h &mdash; Churn::ChurnCalculator</a>
156
-
157
- <li class="method"><a href="Churn/ChurnCalculator.html#method-i-to_s">#to_s &mdash; 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
@@ -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
@@ -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
-