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.
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
-