churn 0.0.33 → 0.0.34

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -7,4 +7,5 @@ tmp
7
7
  .rvmrc
8
8
  .bundle
9
9
  specs
10
- .yardoc/
10
+ .yardoc/
11
+ coverage
@@ -3,4 +3,5 @@ rvm:
3
3
  - 1.9.3
4
4
  - rbx-18mode
5
5
  - rbx-19mode
6
- - 1.8.7
6
+ - 1.8.7
7
+ - 2.0.0
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- churn (0.0.33)
4
+ churn (0.0.34)
5
5
  chronic (>= 0.2.3)
6
6
  hirb
7
7
  json_pure
@@ -48,6 +48,10 @@ GEM
48
48
  shoulda-context (1.0.2)
49
49
  shoulda-matchers (1.4.1)
50
50
  activesupport (>= 3.0.0)
51
+ simplecov (0.7.1)
52
+ multi_json (~> 1.0)
53
+ simplecov-html (~> 0.7.1)
54
+ simplecov-html (0.7.1)
51
55
  test-construct (1.2.0)
52
56
 
53
57
  PLATFORMS
@@ -59,4 +63,5 @@ DEPENDENCIES
59
63
  mocha (~> 0.9.5)
60
64
  rake
61
65
  shoulda
66
+ simplecov
62
67
  test-construct
data/README.md CHANGED
@@ -6,8 +6,9 @@ Churn for files is immediate, but classes and methods requires buildings up a hi
6
6
 
7
7
  Currently has full Git, Mercurial (hg), and Bazaar (bzr) support, and partial SVN support (supports only file level churn currently)
8
8
 
9
- Authors:
9
+ File changes can be calculated on any single commit to look at method changes you need to be running churn over time. Using a git post-commit hook, configuring your CI to run churn, or using [churn-site](http://churn.picoappz.com) is the best way to build up your churn history. See the --past_history (-p) option to do a one time run building up past class and method level churn.
10
10
 
11
+ ####Authors:
11
12
  * danmayer
12
13
  * ajwalters
13
14
  * cldwalker
@@ -20,11 +21,17 @@ Authors:
20
21
 
21
22
  This project runs [travis-ci.org](http://travis-ci.org)
22
23
 
24
+ ## TODO
25
+
26
+ Want to help out, there are easy tasks ready for some attention. The list of items has been moved to the [churn wafflie.io](http://waffle.io/danmayer/churn)
27
+
28
+ [![Stories in Ready](https://badge.waffle.io/danmayer/churn.png)](http://waffle.io/danmayer/churn)
29
+
23
30
  ## Churn Usage
24
31
 
25
32
  Install with `gem install churn` or for bundler add to your Gemfile `gem 'churn', :require => false`.
26
33
 
27
- The reason you want require false is that when required by default churn is expecting to add some rake tasks, you don't really want or need it loading when running your server or tests. Previous versions required this change, churn will now do the right thing if you forget to add `require => false`.
34
+ The reason you want require false is that when required by default churn is expecting to add some rake tasks, you don't really want or need it loading when running your server or tests.
28
35
 
29
36
  * rake:
30
37
  * add `require 'churn'` to Rakefile
@@ -45,6 +52,8 @@ The reason you want require false is that when required by default churn is expe
45
52
  churn -c 10 #set minimum churn count on a file to 10
46
53
  churn -c 5 -y -i "Gemfile" #mix and match
47
54
  churn --start_date "6 months ago" #Start looking at file changes from 6 months ago
55
+ churn -p "4 months ago" #churn the past history to build up data for the last 4 months
56
+ churn --past_history #churn the past history for default 3 months to build up data
48
57
 
49
58
 
50
59
  ## Example Output
@@ -125,17 +134,14 @@ The reason you want require false is that when required by default churn is expe
125
134
  churn [options]+
126
135
 
127
136
  PARAMETERS
128
- --minimum_churn_count=minimum_churn_count, -c (0 ~> int(minimum_churn_count=3))
129
- --yaml, -y
130
- --ignore_files=[ignore_files], -i (0 ~> string(ignore_files=))
131
- --start_date=[start_date], -s (0 ~> string(start_date=))
132
- --help, -h
133
-
134
- ## TODO
135
-
136
- The list of items has been moved to the [churn wafflie.io](http://waffle.io/danmayer/churn)
137
-
138
- [![Stories in Ready](https://badge.waffle.io/danmayer/churn.png)](http://waffle.io/danmayer/churn)
137
+ --minimum_churn_count=minimum_churn_count, -c (0 ~>
138
+ int(minimum_churn_count=3))
139
+ --yaml, -y
140
+ --ignore_files=[ignore_files], -i (0 ~> string(ignore_files=))
141
+ --start_date=[start_date], -s (0 ~> string(start_date=))
142
+ --data_directory=[data_directory], -d (0 ~> string(data_directory=))
143
+ --past_history=[past_history], -p (0 ~> string(past_history=))
144
+ --help, -h
139
145
 
140
146
  ## Notes on Patches/Pull Requests
141
147
 
data/bin/churn CHANGED
@@ -33,9 +33,22 @@ Main do
33
33
  default ''
34
34
  end
35
35
 
36
+ #grrr h is already taken by --help / -h so whent with 'p'
37
+ option('past_history', 'p') do
38
+ cast :string
39
+ argument :optional
40
+ default ''
41
+ end
42
+
36
43
  def report_churn(output_string)
37
44
  require File.join(File.dirname(__FILE__), '..', 'lib', 'churn', 'churn_calculator')
38
- result = Churn::ChurnCalculator.new({:minimum_churn_count => params['minimum_churn_count'].value, :ignore_files => params['ignore_files'].value, :start_date => params['start_date'].value, :data_directory => params['data_directory'].value}).report(output_string)
45
+ options = {:minimum_churn_count => params['minimum_churn_count'].value,
46
+ :ignore_files => params['ignore_files'].value,
47
+ :start_date => params['start_date'].value,
48
+ :data_directory => params['data_directory'].value,
49
+ :history => params['past_history'].value
50
+ }
51
+ result = Churn::ChurnCalculator.new(options).report(output_string)
39
52
  unless output_string
40
53
  result = YAML::dump(result)
41
54
  end
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
31
31
  s.add_development_dependency(%q<test-construct>, [">= 0"])
32
32
  s.add_development_dependency(%q<rake>, [">= 0"])
33
33
  s.add_development_dependency(%q<mocha>, ["~> 0.9.5"])
34
+ s.add_development_dependency(%q<simplecov>,[">= 0"])
34
35
  #s.add_development_dependency(%q<ruby-debug>, ["~> 0.10.4"])
35
36
  s.add_runtime_dependency(%q<main>, [">= 0"])
36
37
  s.add_runtime_dependency(%q<json_pure>, [">= 0"])
@@ -44,9 +44,37 @@ module Churn
44
44
  # @param [Bolean] format to return the data, true for string or false for hash
45
45
  # @return [Object] returns either a pretty string or a hash representing the chrun of the project
46
46
  def report(print = true)
47
- self.emit
48
- self.analyze
49
- print ? self.to_s : self.to_h
47
+ if @churn_options.history
48
+ generate_history
49
+ else
50
+ self.emit
51
+ self.analyze
52
+ print ? self.to_s : self.to_h
53
+ end
54
+ end
55
+
56
+ # this method generates the past history of a churn project from first commit to current
57
+ # running the report for oldest commits first so they are built up correctly
58
+ def generate_history
59
+ if @source_control.is_a?(GitAnalyzer)
60
+ begin
61
+ history_starting_point = Chronic.parse(@churn_options.history)
62
+ @source_control.get_commit_history.each do |commit|
63
+ `git checkout #{commit}`
64
+ commit_date = `git show -s --format="%ci"`
65
+ commit_date = Time.parse(commit_date)
66
+ next if commit_date < history_starting_point
67
+ #7776000 == 3.months without adding active support depenancy
68
+ start_date = (commit_date - 7776000)
69
+ `churn -s "#{start_date}"`
70
+ end
71
+ ensure
72
+ `git checkout master`
73
+ end
74
+ "churn history complete, this has munipulated git please make sure you are back on HEAD where you expect to be"
75
+ else
76
+ raise "currently generate history only supports git"
77
+ end
50
78
  end
51
79
 
52
80
  # Emits various data from source control to be analyses later... Currently this is broken up like this as a throwback to metric_fu
@@ -87,6 +115,11 @@ module Churn
87
115
  hash
88
116
  end
89
117
 
118
+ def to_s
119
+ ChurnCalculator.to_s(to_h[:churn])
120
+ end
121
+
122
+ # Pretty print the data as a string for the user
90
123
  def self.to_s(hash)
91
124
  result = seperator
92
125
  result +="* Revision Changes \n"
@@ -110,14 +143,10 @@ module Churn
110
143
  result += display_array(method_churn)
111
144
  end
112
145
 
113
- # Pretty print the data as a string for the user
114
- def to_s
115
- ChurnCalculator.to_s(to_h[:churn])
116
- end
117
-
118
146
  private
119
147
 
120
148
  def self.collect_items(collection, match)
149
+ return [] unless collection
121
150
  collection.map {|item| (item.delete(match) || {}).merge(item) }
122
151
  end
123
152
 
@@ -137,20 +166,16 @@ module Churn
137
166
  "*"*70+"\n"
138
167
  end
139
168
 
140
- def seperator
141
- ChurnCalculator.seperator
142
- end
143
-
144
169
  def self.git?
145
- system("git branch")
170
+ !!(`git branch 2>&1` && $?.success?)
146
171
  end
147
-
172
+
148
173
  def self.hg?
149
- system("hg branch")
174
+ !!(`hg branch 2>&1` && $?.success?)
150
175
  end
151
-
176
+
152
177
  def self.bzr?
153
- system("bzr nick")
178
+ !!(`bzr nick 2>&1` && $?.success?)
154
179
  end
155
180
 
156
181
  def set_source_control(start_date)
@@ -9,6 +9,10 @@ module Churn
9
9
  def get_revisions
10
10
  `git log #{date_range} --pretty=format:"%H"`.split(/\n/).reject{|line| line == ""}
11
11
  end
12
+
13
+ def get_commit_history
14
+ `git log --reverse --pretty=format:"%H"`.split(/\n/).reject{|line| line == ""}
15
+ end
12
16
 
13
17
  private
14
18
 
@@ -1,3 +1,3 @@
1
1
  module Churn
2
- VERSION = "0.0.33"
2
+ VERSION = "0.0.34"
3
3
  end
@@ -7,14 +7,16 @@ module Churn
7
7
  include Singleton
8
8
  DEFAULT_CHURN_DIRECTORY = "tmp/churn"
9
9
  DEFAULT_MINIMUM_CHURN_COUNT = 5
10
+ DEFAULT_START_TIME = '3 months ago'
10
11
 
11
- attr_accessor :data_directory, :minimum_churn_count, :ignore_files, :start_date
12
+ attr_accessor :data_directory, :minimum_churn_count, :ignore_files, :start_date, :history
12
13
 
13
14
  def initialize()
14
15
  @data_directory = DEFAULT_CHURN_DIRECTORY
15
16
  @minimum_churn_count = DEFAULT_MINIMUM_CHURN_COUNT
16
17
  @ignore_files = ['/dev/null']
17
- @start_date = '3 months ago'
18
+ @start_date = DEFAULT_START_TIME
19
+ @history = nil
18
20
  end
19
21
 
20
22
  def set_options(options = {})
@@ -22,7 +24,12 @@ module Churn
22
24
  @minimum_churn_count = options.fetch(:minimum_churn_count){ @minimum_churn_count }.to_i
23
25
  @ignore_files = (options.fetch(:ignore_files){ @ignore_files }).to_s.split(',').map(&:strip)
24
26
  @ignore_files << '/dev/null' unless @ignore_files.include?('/dev/null')
25
- @start_date = options[:start_date] if options[:start_date].nil? || options[:start_date]!=''
27
+ @start_date = options[:start_date] if !options[:start_date].nil? && options[:start_date]!=''
28
+ @history = options[:history] if !options[:history].nil? && options[:history]!=''
29
+ if @history=='true'
30
+ @history = DEFAULT_START_TIME
31
+ end
32
+
26
33
  self
27
34
  end
28
35
 
@@ -1,9 +1,16 @@
1
1
  require 'rubygems'
2
+ require 'simplecov'
2
3
  require 'test/unit'
3
4
  require 'shoulda'
4
5
  require 'construct'
5
6
  require 'mocha'
6
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
+
7
14
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
15
  $LOAD_PATH.unshift(File.dirname(__FILE__))
9
16
  require 'churn/churn_calculator'
@@ -102,12 +102,55 @@ class ChurnCalculatorTest < Test::Unit::TestCase
102
102
  end
103
103
  end
104
104
 
105
+ should "have expected output for self.to_s" do
106
+ output = Churn::ChurnCalculator.to_s({})
107
+ assert_match /Revision Changes/, output
108
+ assert_match /Project Churn/, output
109
+ end
110
+
111
+ should "have expected output for to_s" do
112
+ calc = Churn::ChurnCalculator.new
113
+ calc.expects(:to_h).returns({:churn => {}})
114
+ output = calc.to_s
115
+ assert_match /Revision Changes/, output
116
+ assert_match /Project Churn/, output
117
+ end
118
+
105
119
  should "initialize a churn calculator for hg repositories" do
106
120
  Churn::ChurnCalculator.stubs(:git?).returns(false)
107
- Churn::ChurnCalculator.stubs(:system).with('hg branch').returns(true)
121
+ Churn::ChurnCalculator.expects(:`).with("hg branch 2>&1").returns(true) #` fix syntax hilighting
108
122
  churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
109
123
  assert churn.instance_variable_get(:@source_control).is_a?(Churn::HgAnalyzer)
110
124
  end
111
125
 
126
+ should "initialize a churn calculator for bzr repositories" do
127
+ Churn::ChurnCalculator.stubs(:git?).returns(false)
128
+ Churn::ChurnCalculator.stubs(:hg?).returns(false)
129
+ Churn::ChurnCalculator.expects(:`).with("bzr nick 2>&1").returns(true) #` fix syntax hilighting
130
+ churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
131
+ assert churn.instance_variable_get(:@source_control).is_a?(Churn::BzrAnalyzer)
132
+ end
133
+
134
+ should "initialize a churn calculator for svn repositories" do
135
+ Churn::ChurnCalculator.stubs(:git?).returns(false)
136
+ Churn::ChurnCalculator.stubs(:hg?).returns(false)
137
+ Churn::ChurnCalculator.stubs(:bzr?).returns(false)
138
+ File.stubs(:exist?).returns(true)
139
+ churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
140
+ assert churn.instance_variable_get(:@source_control).is_a?(Churn::SvnAnalyzer)
141
+ end
142
+
143
+ should "raise exception on a churn calculator for unknown repositories" do
144
+ Churn::ChurnCalculator.stubs(:git?).returns(false)
145
+ Churn::ChurnCalculator.stubs(:hg?).returns(false)
146
+ Churn::ChurnCalculator.stubs(:bzr?).returns(false)
147
+ File.stubs(:exist?).returns(false)
148
+ assert_raises RuntimeError do
149
+ churn = Churn::ChurnCalculator.new({:minimum_churn_count => 3})
150
+ end
151
+ end
152
+
153
+
154
+
112
155
 
113
156
  end
@@ -12,6 +12,77 @@ class GitAnalyzerTest < Test::Unit::TestCase
12
12
  expected_hash = {"lib/churn/churn_calculator.rb"=>[18..18, 19..19]}
13
13
  assert_equal = updated
14
14
  end
15
+
16
+ should "run get_logs correctly" do
17
+ git_analyzer = Churn::GitAnalyzer.new
18
+ git_analyzer.expects(:`).returns(git_logs_output) #`fix syntax hilighting
19
+ assert_equal ["public/css/application.css", "views/layout.erb", "README.md", "app.rb"], git_analyzer.get_logs
20
+ end
21
+
22
+ should "run get_revisions correctly" do
23
+ git_analyzer = Churn::GitAnalyzer.new
24
+ git_analyzer.expects(:`).returns(git_revisions_output) #`fix syntax hilighting
25
+ assert_equal ["0aef1f56d5b3b546457e996450fd9ceca379f0a8",
26
+ "8038f1b17c3749540650aaab3f4e5e846cfc3b47",
27
+ "4d7e4859b2ed8a7e4f73e3540e7879c00cba9783"], git_analyzer.get_revisions
28
+ end
15
29
 
16
- end
30
+ should "run date range correctly" do
31
+ git_analyzer = Churn::GitAnalyzer.new(Date.parse('3/3/2010'))
32
+ assert_equal "--after=2010-03-03", git_analyzer.send(:date_range)
33
+ end
17
34
 
35
+ should "run get_diff correctly" do
36
+ git_analyzer = Churn::GitAnalyzer.new
37
+ git_analyzer.expects(:`).returns(git_git_diff_output) #`fix syntax hilighting
38
+ assert_equal ["--- a/public/css/application.css",
39
+ "+++ b/public/css/application.css",
40
+ "@@ -18,0 +19,4 @@ footer{",
41
+ "--- a/views/layout.erb",
42
+ "+++ b/views/layout.erb",
43
+ "@@ -43,0 +44 @@"], git_analyzer.send(:get_diff, 'rev', 'prev_rev')
44
+ end
45
+
46
+ protected
47
+
48
+ # ran in a project
49
+ # git log --after=2013-09-05 --name-only --pretty=format:
50
+ def git_logs_output
51
+ "public/css/application.css
52
+ views/layout.erb
53
+
54
+ README.md
55
+ app.rb"
56
+ end
57
+
58
+ # ran in a project
59
+ # git log --after=2013-09-05 --pretty=format:"%H"
60
+ def git_revisions_output
61
+ "0aef1f56d5b3b546457e996450fd9ceca379f0a8
62
+ 8038f1b17c3749540650aaab3f4e5e846cfc3b47
63
+ 4d7e4859b2ed8a7e4f73e3540e7879c00cba9783"
64
+ end
65
+
66
+ # ran in a project
67
+ # git diff 4d7e4859b2ed8a7e4f73e3540e7879c00cba9783 8038f1b17c3749540650aaab3f4e5e846cfc3b47 --unified=0
68
+ def git_git_diff_output
69
+ output = <<EOF
70
+ diff --git a/public/css/application.css b/public/css/application.css
71
+ index 522ca1a..730eb1e 100644
72
+ --- a/public/css/application.css
73
+ +++ b/public/css/application.css
74
+ @@ -18,0 +19,4 @@ footer{
75
+ +
76
+ +footer .container .right {
77
+ + float:right;
78
+ +}
79
+ diff --git a/views/layout.erb b/views/layout.erb
80
+ index f8d3aea..7f4fb2f 100644
81
+ --- a/views/layout.erb
82
+ +++ b/views/layout.erb
83
+ @@ -43,0 +44 @@
84
+ + <span class="right">a part of <a href="http://picoappz.com">picoappz</a></span>
85
+ EOF
86
+ output
87
+ end
88
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../test_helper', File.dirname(__FILE__))
2
+
3
+ class SourceControlTest < Test::Unit::TestCase
4
+
5
+ should "get_updated_files_from_log if revision and previous revision" do
6
+ sc = Churn::SourceControl.new(Date.today)
7
+ current = 'current'
8
+ revisions = ['future',current,'past']
9
+ def sc.get_diff(revision, previous_revision)
10
+ [previous_revision]
11
+ end
12
+ assert_equal ['past'], sc.get_updated_files_from_log(current,revisions)
13
+ end
14
+
15
+ should "get_updated_files_from_log get empty array when no revisions found" do
16
+ sc = Churn::SourceControl.new(Date.today)
17
+ current = 'current'
18
+ revisions = ['future',current]
19
+ assert_equal [], sc.get_updated_files_from_log(current,revisions)
20
+ end
21
+
22
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path('../test_helper', File.dirname(__FILE__))
2
+
3
+ class SvnAnalyzerTest < Test::Unit::TestCase
4
+
5
+ should "parses logs correctly" do
6
+ svn_analyzer = Churn::SvnAnalyzer.new
7
+ revision = 'first'
8
+ revisions = ['first']
9
+ lines = ["--- a/lib/churn/churn_calculator.rb", "+++ b/lib/churn/churn_calculator.rb", "@@ -18,0 +19 @@ module Churn"]
10
+ svn_analyzer.stubs(:get_updated_files_from_log).returns(lines)
11
+ updated = svn_analyzer.get_updated_files_change_info(revision, revisions)
12
+ expected_hash = {"lib/churn/churn_calculator.rb"=>[18..18, 19..19]}
13
+ assert_equal = updated
14
+ end
15
+
16
+ should "run get_logs correctly" do
17
+ svn_analyzer = Churn::SvnAnalyzer.new
18
+ svn_analyzer.expects(:`).returns(svn_output) #`fix syntax hilighting
19
+ assert_equal ["/trunk", "/trunk/test.txt"], svn_analyzer.get_logs
20
+ end
21
+
22
+ should "run date range correctly" do
23
+ svn_analyzer = Churn::SvnAnalyzer.new(Date.parse('3/3/2010'))
24
+ assert_equal "--revision {2010-03-03}:{#{Date.today.to_s}}", svn_analyzer.send(:date_range)
25
+ end
26
+
27
+ protected
28
+
29
+ def svn_output
30
+ "------------------------------------------------------------------------
31
+ r1 | danmayer | 2013-09-07 10:45:32 -0400 (Sat, 07 Sep 2013) | 1 line
32
+ Changed paths:
33
+ A /trunk
34
+ A /trunk/test.txt
35
+
36
+ Initial import of project1
37
+ ------------------------------------------------------------------------"
38
+ end
39
+
40
+ end
metadata CHANGED
@@ -1,192 +1,219 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: churn
3
- version: !ruby/object:Gem::Version
4
- hash: 93
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.34
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 33
10
- version: 0.0.33
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Dan Mayer
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-12-17 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
22
- none: false
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- hash: 3
27
- segments:
28
- - 0
29
- version: "0"
30
- requirement: *id001
31
- prerelease: false
12
+ date: 2012-12-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
32
15
  name: shoulda
33
- type: :development
34
- - !ruby/object:Gem::Dependency
35
- version_requirements: &id002 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
36
17
  none: false
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- hash: 3
41
- segments:
42
- - 0
43
- version: "0"
44
- requirement: *id002
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
45
23
  prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
46
31
  name: jeweler
47
- type: :development
48
- - !ruby/object:Gem::Dependency
49
- version_requirements: &id003 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
50
33
  none: false
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- hash: 3
55
- segments:
56
- - 0
57
- version: "0"
58
- requirement: *id003
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
59
39
  prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
60
47
  name: test-construct
61
- type: :development
62
- - !ruby/object:Gem::Dependency
63
- version_requirements: &id004 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
64
49
  none: false
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- hash: 3
69
- segments:
70
- - 0
71
- version: "0"
72
- requirement: *id004
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
73
55
  prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
74
63
  name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
75
70
  type: :development
76
- - !ruby/object:Gem::Dependency
77
- version_requirements: &id005 !ruby/object:Gem::Requirement
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
78
73
  none: false
79
- requirements:
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: mocha
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
80
83
  - - ~>
81
- - !ruby/object:Gem::Version
82
- hash: 49
83
- segments:
84
- - 0
85
- - 9
86
- - 5
84
+ - !ruby/object:Gem::Version
87
85
  version: 0.9.5
88
- requirement: *id005
89
- prerelease: false
90
- name: mocha
91
86
  type: :development
92
- - !ruby/object:Gem::Dependency
93
- version_requirements: &id006 !ruby/object:Gem::Requirement
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.5
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
94
97
  none: false
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- hash: 3
99
- segments:
100
- - 0
101
- version: "0"
102
- requirement: *id006
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
103
  prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
104
111
  name: main
105
- type: :runtime
106
- - !ruby/object:Gem::Dependency
107
- version_requirements: &id007 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
108
113
  none: false
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- hash: 3
113
- segments:
114
- - 0
115
- version: "0"
116
- requirement: *id007
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
117
119
  prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
118
127
  name: json_pure
119
- type: :runtime
120
- - !ruby/object:Gem::Dependency
121
- version_requirements: &id008 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
122
129
  none: false
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- hash: 17
127
- segments:
128
- - 0
129
- - 2
130
- - 3
131
- version: 0.2.3
132
- requirement: *id008
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :runtime
133
135
  prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
134
143
  name: chronic
135
- type: :runtime
136
- - !ruby/object:Gem::Dependency
137
- version_requirements: &id009 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
138
145
  none: false
139
- requirements:
140
- - - ~>
141
- - !ruby/object:Gem::Version
142
- hash: 25
143
- segments:
144
- - 4
145
- - 1
146
- version: "4.1"
147
- requirement: *id009
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: 0.2.3
150
+ type: :runtime
148
151
  prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: 0.2.3
158
+ - !ruby/object:Gem::Dependency
149
159
  name: sexp_processor
150
- type: :runtime
151
- - !ruby/object:Gem::Dependency
152
- version_requirements: &id010 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
153
161
  none: false
154
- requirements:
162
+ requirements:
155
163
  - - ~>
156
- - !ruby/object:Gem::Version
157
- hash: 7
158
- segments:
159
- - 3
160
- - 0
161
- version: "3.0"
162
- requirement: *id010
164
+ - !ruby/object:Gem::Version
165
+ version: '4.1'
166
+ type: :runtime
163
167
  prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: '4.1'
174
+ - !ruby/object:Gem::Dependency
164
175
  name: ruby_parser
165
- type: :runtime
166
- - !ruby/object:Gem::Dependency
167
- version_requirements: &id011 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
168
177
  none: false
169
- requirements:
170
- - - ">="
171
- - !ruby/object:Gem::Version
172
- hash: 3
173
- segments:
174
- - 0
175
- version: "0"
176
- requirement: *id011
178
+ requirements:
179
+ - - ~>
180
+ - !ruby/object:Gem::Version
181
+ version: '3.0'
182
+ type: :runtime
177
183
  prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ~>
188
+ - !ruby/object:Gem::Version
189
+ version: '3.0'
190
+ - !ruby/object:Gem::Dependency
178
191
  name: hirb
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
179
198
  type: :runtime
180
- description: "High method and class churn has been shown to have increased bug and error rates. This gem helps you know what is changing a lot so you can do additional testing, code review, or refactoring to try to tame the volatile code. "
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ description: ! 'High method and class churn has been shown to have increased bug and
207
+ error rates. This gem helps you know what is changing a lot so you can do additional
208
+ testing, code review, or refactoring to try to tame the volatile code. '
181
209
  email: dan@mayerdan.com
182
- executables:
210
+ executables:
183
211
  - churn
184
212
  extensions: []
185
-
186
- extra_rdoc_files:
213
+ extra_rdoc_files:
187
214
  - LICENSE
188
215
  - README.md
189
- files:
216
+ files:
190
217
  - .deferred_server
191
218
  - .document
192
219
  - .gitignore
@@ -222,40 +249,37 @@ files:
222
249
  - test/unit/git_analyzer_test.rb
223
250
  - test/unit/hg_analyzer_test.rb
224
251
  - test/unit/location_mapping_test.rb
252
+ - test/unit/source_control_test.rb
253
+ - test/unit/svn_analyzer_test.rb
225
254
  homepage: http://github.com/danmayer/churn
226
- licenses:
255
+ licenses:
227
256
  - MIT
228
257
  post_install_message:
229
258
  rdoc_options: []
230
-
231
- require_paths:
259
+ require_paths:
232
260
  - lib
233
- required_ruby_version: !ruby/object:Gem::Requirement
261
+ required_ruby_version: !ruby/object:Gem::Requirement
234
262
  none: false
235
- requirements:
236
- - - ">="
237
- - !ruby/object:Gem::Version
238
- hash: 3
239
- segments:
263
+ requirements:
264
+ - - ! '>='
265
+ - !ruby/object:Gem::Version
266
+ version: '0'
267
+ segments:
240
268
  - 0
241
- version: "0"
242
- required_rubygems_version: !ruby/object:Gem::Requirement
269
+ hash: 837759494224756390
270
+ required_rubygems_version: !ruby/object:Gem::Requirement
243
271
  none: false
244
- requirements:
245
- - - ">="
246
- - !ruby/object:Gem::Version
247
- hash: 3
248
- segments:
249
- - 0
250
- version: "0"
272
+ requirements:
273
+ - - ! '>='
274
+ - !ruby/object:Gem::Version
275
+ version: '0'
251
276
  requirements: []
252
-
253
277
  rubyforge_project: churn
254
- rubygems_version: 1.8.10
278
+ rubygems_version: 1.8.25
255
279
  signing_key:
256
280
  specification_version: 3
257
281
  summary: Providing additional churn metrics over the original metric_fu churn
258
- test_files:
282
+ test_files:
259
283
  - test/data/churn_calculator.rb
260
284
  - test/data/test_helper.rb
261
285
  - test/test_helper.rb
@@ -266,3 +290,5 @@ test_files:
266
290
  - test/unit/git_analyzer_test.rb
267
291
  - test/unit/hg_analyzer_test.rb
268
292
  - test/unit/location_mapping_test.rb
293
+ - test/unit/source_control_test.rb
294
+ - test/unit/svn_analyzer_test.rb